Build AsminVoicechat / prepare-release (push) Successful in 14s
Build AsminVoicechat / build-and-test (17) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (18) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (19) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (20) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (21) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (22) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (23) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (24) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (25) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (26) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (27-ea) (push) Canceled after 0s
Build AsminVoicechat / build-and-test (16) (push) Canceled after 38s
176 lines
7.2 KiB
Java
176 lines
7.2 KiB
Java
/*
|
|
* 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<? extends Packet> packet;
|
|
private SocketAddress address;
|
|
private static final Map<Byte, Class<? extends Packet>> packetRegistry = new HashMap<Byte, Class<? extends Packet>>();
|
|
|
|
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<? extends 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<? extends Packet> 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<? extends Packet> packet) {
|
|
for (Map.Entry<Byte, Class<? extends Packet>> 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);
|
|
}
|
|
}
|
|
|