/* * Decompiled with CFR 0.152. * * Could not load the following classes: * io.netty.buffer.Unpooled * io.netty.handler.codec.DecoderException * javax.annotation.Nonnull * javax.annotation.Nullable */ package de.maxhenkel.voicechat.voice.common; import de.maxhenkel.voicechat.Voicechat; import de.maxhenkel.voicechat.api.RawUdpPacket; import de.maxhenkel.voicechat.debug.PingHandler; import de.maxhenkel.voicechat.util.FriendlyByteBuf; import de.maxhenkel.voicechat.voice.common.AuthenticateAckPacket; import de.maxhenkel.voicechat.voice.common.AuthenticatePacket; import de.maxhenkel.voicechat.voice.common.ConnectionCheckAckPacket; import de.maxhenkel.voicechat.voice.common.ConnectionCheckPacket; import de.maxhenkel.voicechat.voice.common.GroupSoundPacket; import de.maxhenkel.voicechat.voice.common.KeepAlivePacket; import de.maxhenkel.voicechat.voice.common.LocationSoundPacket; import de.maxhenkel.voicechat.voice.common.MicPacket; import de.maxhenkel.voicechat.voice.common.Packet; import de.maxhenkel.voicechat.voice.common.PingPacket; import de.maxhenkel.voicechat.voice.common.PlayerSoundPacket; import de.maxhenkel.voicechat.voice.common.Secret; import de.maxhenkel.voicechat.voice.server.ClientConnection; import de.maxhenkel.voicechat.voice.server.Server; import io.netty.buffer.Unpooled; import io.netty.handler.codec.DecoderException; import java.lang.reflect.InvocationTargetException; import java.net.SocketAddress; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; public class NetworkMessage { public static final byte MAGIC_BYTE = -1; private final long timestamp; private Packet packet; private SocketAddress address; private static final Map> packetRegistry = new HashMap>(); public NetworkMessage(long timestamp, Packet packet) { this(timestamp); this.packet = packet; } public NetworkMessage(Packet packet) { this(System.currentTimeMillis()); this.packet = packet; } private NetworkMessage(long timestamp) { this.timestamp = timestamp; } @Nonnull public Packet getPacket() { return this.packet; } public long getTimestamp() { return this.timestamp; } public long getTTL() { return this.packet.getTTL(); } public SocketAddress getAddress() { return this.address; } @Nullable public static NetworkMessage readPacketServer(RawUdpPacket packet, Server server) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException { try { byte[] data = packet.getData(); FriendlyByteBuf b = new FriendlyByteBuf(Unpooled.wrappedBuffer((byte[])data)); if (b.readByte() != -1) { Voicechat.LOGGER.debug("Received invalid packet from {}", packet.getSocketAddress()); return null; } UUID playerID = b.readUUID(); if (!server.hasSecret(playerID)) { if (PingHandler.onPacket(server, packet.getSocketAddress(), playerID, b)) { return null; } Voicechat.LOGGER.debug("Player {} does not have a secret", playerID); return null; } return NetworkMessage.readFromBytes(packet.getSocketAddress(), server.getSecret(playerID), b.readByteArray(2048), packet.getTimestamp()); } catch (DecoderException | IndexOutOfBoundsException e) { Voicechat.LOGGER.debug("Received invalid packet from {}", packet.getSocketAddress()); return null; } } @Nullable private static NetworkMessage readFromBytes(SocketAddress socketAddress, Secret secret, byte[] encryptedPayload, long timestamp) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { byte[] decrypt; try { decrypt = secret.decrypt(encryptedPayload); } catch (Exception e) { Voicechat.LOGGER.debug("Failed to decrypt packet from {}", socketAddress); return null; } FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.wrappedBuffer((byte[])decrypt)); byte packetType = buffer.readByte(); Class packetClass = packetRegistry.get(packetType); if (packetClass == null) { Voicechat.LOGGER.debug("Got invalid packet ID {}", packetType); return null; } Packet p = packetClass.getDeclaredConstructor(new Class[0]).newInstance(new Object[0]); NetworkMessage message = new NetworkMessage(timestamp); message.address = socketAddress; message.packet = p.fromBytes(buffer); return message; } private static byte getPacketType(Packet packet) { for (Map.Entry> entry : packetRegistry.entrySet()) { if (!packet.getClass().equals(entry.getValue())) continue; return entry.getKey(); } return -1; } public byte[] writeServer(Server server, ClientConnection connection) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { byte[] payload = this.write(server.getSecret(connection.getPlayerUUID())); FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer((int)(1 + payload.length))); buffer.writeByte(-1); buffer.writeByteArray(payload); byte[] bytes = new byte[buffer.readableBytes()]; buffer.readBytes(bytes); return bytes; } public byte[] write(Secret secret) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); byte type = NetworkMessage.getPacketType(this.packet); if (type < 0) { throw new IllegalArgumentException("Packet type not found"); } buffer.writeByte(type); this.packet.toBytes(buffer); return secret.encrypt(buffer.array()); } static { packetRegistry.put((byte)1, MicPacket.class); packetRegistry.put((byte)2, PlayerSoundPacket.class); packetRegistry.put((byte)3, GroupSoundPacket.class); packetRegistry.put((byte)4, LocationSoundPacket.class); packetRegistry.put((byte)5, AuthenticatePacket.class); packetRegistry.put((byte)6, AuthenticateAckPacket.class); packetRegistry.put((byte)7, PingPacket.class); packetRegistry.put((byte)8, KeepAlivePacket.class); packetRegistry.put((byte)9, ConnectionCheckPacket.class); packetRegistry.put((byte)10, ConnectionCheckAckPacket.class); } }