Working on encryption
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
package com.github.manevolent.ts3j.command;
|
||||
|
||||
import com.github.manevolent.ts3j.command.type.client.*;
|
||||
import com.github.manevolent.ts3j.command.type.server.*;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class Commands {
|
||||
private static final Map<String, Class<? extends TypedCommand>> commands = new LinkedHashMap<>();
|
||||
|
||||
static {
|
||||
// Client
|
||||
commands.put("clientinitiv", ClientInitIV.class);
|
||||
|
||||
// Server
|
||||
commands.put("initivexpand", ServerInitIVExpand.class);
|
||||
commands.put("initivexpand2", ServerInitIVExpand2.class);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package com.github.manevolent.ts3j.command;
|
||||
|
||||
import com.github.manevolent.ts3j.command.part.CommandParameter;
|
||||
import com.github.manevolent.ts3j.protocol.ProtocolRole;
|
||||
import com.github.manevolent.ts3j.protocol.client.TeamspeakClient;
|
||||
import com.github.manevolent.ts3j.protocol.server.TeamspeakServer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -47,4 +49,12 @@ public abstract class TypedCommand implements Command {
|
||||
public String toString() {
|
||||
return build();
|
||||
}
|
||||
|
||||
public void handleServer(TeamspeakServer server) {
|
||||
|
||||
}
|
||||
|
||||
public void handleClient(TeamspeakClient client) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.github.manevolent.ts3j.command.type.server;
|
||||
|
||||
import com.github.manevolent.ts3j.command.TypedCommand;
|
||||
import com.github.manevolent.ts3j.command.part.CommandSingleParameter;
|
||||
import com.github.manevolent.ts3j.protocol.ProtocolRole;
|
||||
|
||||
public class ServerInitIVExpand extends TypedCommand {
|
||||
public ServerInitIVExpand() {
|
||||
super(ProtocolRole.CLIENT, "initivexpand");
|
||||
|
||||
set(new CommandSingleParameter("alpha"));
|
||||
set(new CommandSingleParameter("beta"));
|
||||
set(new CommandSingleParameter("omega"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.github.manevolent.ts3j.command.type.server;
|
||||
|
||||
import com.github.manevolent.ts3j.command.TypedCommand;
|
||||
import com.github.manevolent.ts3j.command.part.CommandSingleParameter;
|
||||
import com.github.manevolent.ts3j.protocol.ProtocolRole;
|
||||
|
||||
public class ServerInitIVExpand2 extends TypedCommand {
|
||||
public ServerInitIVExpand2() {
|
||||
super(ProtocolRole.CLIENT, "initivexpand2");
|
||||
|
||||
set(new CommandSingleParameter("l"));
|
||||
set(new CommandSingleParameter("beta"));
|
||||
set(new CommandSingleParameter("omega"));
|
||||
set(new CommandSingleParameter("ot"));
|
||||
set(new CommandSingleParameter("proof"));
|
||||
set(new CommandSingleParameter("tvd"));
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.github.manevolent.ts3j.protocol;
|
||||
import com.github.manevolent.ts3j.protocol.packet.Packet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface Endpoint {
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.github.manevolent.ts3j.protocol;
|
||||
|
||||
import com.github.manevolent.ts3j.identity.LocalIdentity;
|
||||
import com.github.manevolent.ts3j.protocol.header.HeaderFlag;
|
||||
import com.github.manevolent.ts3j.protocol.packet.handler.PacketHandler;
|
||||
import com.github.manevolent.ts3j.protocol.socket.LocalTeamspeakSocket;
|
||||
import com.github.manevolent.ts3j.util.Ts3Logging;
|
||||
@@ -77,8 +78,12 @@ public abstract class LocalEndpoint implements Endpoint {
|
||||
}
|
||||
|
||||
protected void handlePacket(NetworkPacket packet) throws IOException {
|
||||
if (packet.getHeader().getPacketFlag(HeaderFlag.FRAGMENTED)) {
|
||||
|
||||
} else {
|
||||
if (this.handler != null) this.handler.handlePacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
public LocalIdentity getLocalIdentity() {
|
||||
return localIdentity;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.github.manevolent.ts3j.protocol;
|
||||
|
||||
import com.github.manevolent.ts3j.protocol.header.PacketHeader;
|
||||
import com.github.manevolent.ts3j.protocol.packet.Packet;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface TeamspeakSocket {
|
||||
SocketRole getSocketRole();
|
||||
|
||||
void send(PacketHeader header, Packet packet) throws IOException;
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import java.net.SocketException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class LocalTeamspeakClient extends LocalEndpoint implements TeamspeakClient {
|
||||
private final Object connectionStateLock = new Object();
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface TeamspeakClient extends Endpoint {
|
||||
void connect(InetSocketAddress remote, String password, long timeout) throws IOException;
|
||||
|
||||
@@ -21,7 +21,7 @@ public class ClientPacketHeader extends PacketHeader {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeHeader(ByteBuffer buffer) {
|
||||
protected ByteBuffer writeHeader(ByteBuffer buffer) {
|
||||
super.writeHeader(buffer);
|
||||
|
||||
// https://github.com/ReSpeak/tsdeclarations/blob/master/ts3protocol.md
|
||||
@@ -30,11 +30,13 @@ public class ClientPacketHeader extends PacketHeader {
|
||||
buffer.put((byte) ((getType().getIndex() & 0x0F) | (getPacketFlags() & 0xF0))); // PT / Packet Type + Flags
|
||||
|
||||
// (payload) -- see writeBody impl in higher levels
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void readHeader(ByteBuffer buffer) {
|
||||
protected ByteBuffer readHeader(ByteBuffer buffer) {
|
||||
super.readHeader(buffer);
|
||||
|
||||
// https://github.com/ReSpeak/tsdeclarations/blob/master/ts3protocol.md
|
||||
@@ -46,6 +48,8 @@ public class ClientPacketHeader extends PacketHeader {
|
||||
setPacketFlags(packetTypeAndFlags & 0xF0);
|
||||
|
||||
// (payload) -- see writeBody impl in higher levels
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -30,7 +30,7 @@ public abstract class PacketHeader {
|
||||
public boolean getPacketFlag(HeaderFlag flag) {
|
||||
int idx = flag.getIndex();
|
||||
|
||||
return (packetFlags & idx) == idx;
|
||||
return (getPacketFlags() & idx) == idx;
|
||||
}
|
||||
|
||||
public void setPacketFlag(HeaderFlag flag, boolean value) {
|
||||
@@ -69,24 +69,28 @@ public abstract class PacketHeader {
|
||||
this.mac = mac;
|
||||
}
|
||||
|
||||
public final void write(ByteBuffer buffer) {
|
||||
writeHeader(buffer);
|
||||
public final ByteBuffer write(ByteBuffer buffer) {
|
||||
return writeHeader(buffer);
|
||||
}
|
||||
|
||||
public final void read(ByteBuffer buffer) {
|
||||
readHeader(buffer);
|
||||
public final ByteBuffer read(ByteBuffer buffer) {
|
||||
return readHeader(buffer);
|
||||
}
|
||||
|
||||
protected void writeHeader(ByteBuffer buffer) {
|
||||
protected ByteBuffer writeHeader(ByteBuffer buffer) {
|
||||
// https://github.com/ReSpeak/tsdeclarations/blob/master/ts3protocol.md
|
||||
buffer.put(getMac(), 0, 8);
|
||||
buffer.putShort((short) (getPacketId() & 0x0000FFFF)); // PiD / Packet ID
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
protected void readHeader(ByteBuffer buffer) {
|
||||
protected ByteBuffer readHeader(ByteBuffer buffer) {
|
||||
// https://github.com/ReSpeak/tsdeclarations/blob/master/ts3protocol.md
|
||||
buffer.get(mac);
|
||||
setPacketId((int) buffer.getShort() & 0x0000FFFF);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.github.manevolent.ts3j.protocol.header;
|
||||
|
||||
import com.github.manevolent.ts3j.protocol.ProtocolRole;
|
||||
import com.github.manevolent.ts3j.protocol.packet.PacketType;
|
||||
import com.github.manevolent.ts3j.util.Ts3Logging;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -21,7 +22,7 @@ public class ServerPacketHeader extends PacketHeader {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeHeader(ByteBuffer buffer) {
|
||||
protected ByteBuffer writeHeader(ByteBuffer buffer) {
|
||||
super.writeHeader(buffer);
|
||||
|
||||
// https://github.com/ReSpeak/tsdeclarations/blob/master/ts3protocol.md
|
||||
@@ -29,10 +30,12 @@ public class ServerPacketHeader extends PacketHeader {
|
||||
buffer.put((byte) ((getType().getIndex() & 0x0F) | (getPacketFlags() & 0xF0))); // PT / Packet Type + Flags
|
||||
|
||||
// (payload) -- see writeBody impl in higher levels
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readHeader(ByteBuffer buffer) {
|
||||
protected ByteBuffer readHeader(ByteBuffer buffer) {
|
||||
super.readHeader(buffer);
|
||||
|
||||
// https://github.com/ReSpeak/tsdeclarations/blob/master/ts3protocol.md
|
||||
@@ -40,6 +43,8 @@ public class ServerPacketHeader extends PacketHeader {
|
||||
setType(PacketType.fromId((packetTypeAndFlags & 0x0F))); // PT / Packet Type + Flags
|
||||
setPacketFlags(packetTypeAndFlags & 0xF0);
|
||||
// (payload) -- see writeBody impl in higher levels
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.github.manevolent.ts3j.protocol.packet;
|
||||
|
||||
import com.github.manevolent.ts3j.protocol.ProtocolRole;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class Packet2Command extends Packet {
|
||||
public Packet2Command(ProtocolRole role) {
|
||||
super(PacketType.COMMAND, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(ByteBuffer buffer) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuffer buffer) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,36 @@
|
||||
package com.github.manevolent.ts3j.protocol.packet;
|
||||
|
||||
public enum PacketType {
|
||||
VOICE(0x0, null),
|
||||
VOICE_WHISPER(0x1, null),
|
||||
COMMAND(0x2, null),
|
||||
COMMAND_LOW(0x3, null),
|
||||
PING(0x4, null),
|
||||
PONG(0x5, null),
|
||||
ACK(0x6, null),
|
||||
ACK_LOW(0x7, null),
|
||||
INIT1(0x8, Packet8Init1.class)
|
||||
VOICE(0x0, null, null, false, false, false, false),
|
||||
VOICE_WHISPER(0x1, null, null, false, false, false, false),
|
||||
PONG(0x5, null, null, false, false, false, false),
|
||||
PING(0x4, null, PONG, false, false, false, false),
|
||||
ACK(0x6, null, null, true, true, false, false),
|
||||
ACK_LOW(0x7, null, null, true, true, false, false),
|
||||
INIT1(0x8, Packet8Init1.class, null, false, true, false, false),
|
||||
COMMAND_LOW(0x3, null, ACK_LOW, true, true, true, true),
|
||||
COMMAND(0x2, Packet2Command.class, ACK, true, true, true, true)
|
||||
;
|
||||
|
||||
private final int index;
|
||||
private final Class<? extends Packet> packetClass;
|
||||
|
||||
PacketType(int index, Class<? extends Packet> packetClass) {
|
||||
private final PacketType acknolwedgedBy;
|
||||
private final boolean encrypted, resend, splittable, compressible;
|
||||
|
||||
PacketType(int index, Class<? extends Packet> packetClass,
|
||||
PacketType acknolwedgedBy,
|
||||
boolean encrypted,
|
||||
boolean resend,
|
||||
boolean splittable,
|
||||
boolean compressible) {
|
||||
this.index = index;
|
||||
this.packetClass = packetClass;
|
||||
this.acknolwedgedBy = acknolwedgedBy;
|
||||
this.resend = resend;
|
||||
this.encrypted = encrypted;
|
||||
this.splittable = splittable;
|
||||
this.compressible = compressible;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
@@ -34,4 +47,24 @@ public enum PacketType {
|
||||
public Class<? extends Packet> getPacketClass() {
|
||||
return packetClass;
|
||||
}
|
||||
|
||||
public boolean isEncrypted() {
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
public PacketType getAcknolwedgedBy() {
|
||||
return acknolwedgedBy;
|
||||
}
|
||||
|
||||
public boolean canResend() {
|
||||
return resend;
|
||||
}
|
||||
|
||||
public boolean isSplittable() {
|
||||
return splittable;
|
||||
}
|
||||
|
||||
public boolean isCompressible() {
|
||||
return compressible;
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -4,6 +4,7 @@ import com.github.manevolent.ts3j.command.type.client.ClientInitIV;
|
||||
import com.github.manevolent.ts3j.protocol.NetworkPacket;
|
||||
import com.github.manevolent.ts3j.protocol.ProtocolRole;
|
||||
import com.github.manevolent.ts3j.protocol.client.LocalTeamspeakClient;
|
||||
import com.github.manevolent.ts3j.protocol.packet.Packet2Command;
|
||||
import com.github.manevolent.ts3j.protocol.packet.Packet8Init1;
|
||||
import com.github.manevolent.ts3j.util.Ts3Logging;
|
||||
|
||||
@@ -25,6 +26,8 @@ public class LocalClientHandlerConnecting extends LocalClientHandler {
|
||||
public void onAssigned() throws IOException {
|
||||
Packet8Init1 packet = new Packet8Init1(ProtocolRole.CLIENT);
|
||||
|
||||
// Initialize connection
|
||||
|
||||
Packet8Init1.Step0 step = new Packet8Init1.Step0();
|
||||
Random random = new Random();
|
||||
randomBytes = new byte[4];
|
||||
@@ -132,6 +135,8 @@ public class LocalClientHandlerConnecting extends LocalClientHandler {
|
||||
throw new IllegalArgumentException("unexpected Init1 server step: " + init1.getStep().getNumber());
|
||||
|
||||
}
|
||||
} else if (packet.getPacket() instanceof Packet2Command) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.github.manevolent.ts3j.protocol.packet.transformation;
|
||||
|
||||
|
||||
import com.github.manevolent.ts3j.protocol.header.PacketHeader;
|
||||
import javafx.util.Pair;
|
||||
|
||||
public class DefaultPacketTransformation extends PacketTransformation {
|
||||
private static final byte[] key =
|
||||
{0x63, 0x3A, 0x5C, 0x77, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x5C, 0x73, 0x79, 0x73, 0x74, 0x65};
|
||||
|
||||
private static final byte[] nonce =
|
||||
{0x6D, 0x5C, 0x66, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6C, 0x6C, 0x33, 0x32, 0x2E, 0x63, 0x70, 0x6C};
|
||||
|
||||
public DefaultPacketTransformation() {
|
||||
super(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<byte[], byte[]> computeParameters(PacketHeader header) {
|
||||
return new Pair<>(key, nonce);
|
||||
}
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
package com.github.manevolent.ts3j.protocol.packet.transformation;
|
||||
|
||||
import com.github.manevolent.ts3j.protocol.ProtocolRole;
|
||||
import com.github.manevolent.ts3j.protocol.header.PacketHeader;
|
||||
import com.github.manevolent.ts3j.util.Ts3Logging;
|
||||
import javafx.util.Pair;
|
||||
import org.bouncycastle.crypto.CipherParameters;
|
||||
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||||
import org.bouncycastle.crypto.engines.AESEngine;
|
||||
import org.bouncycastle.crypto.modes.EAXBlockCipher;
|
||||
import org.bouncycastle.crypto.params.AEADParameters;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class PacketTransformation {
|
||||
private static MessageDigest SHA256;
|
||||
|
||||
{
|
||||
try {
|
||||
SHA256 = MessageDigest.getInstance("SHA256");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final byte[] key;
|
||||
|
||||
private final EAXBlockCipher cipher;
|
||||
|
||||
public PacketTransformation(byte[] key) {
|
||||
this.key = key;
|
||||
this.cipher = new EAXBlockCipher(new AESEngine());
|
||||
}
|
||||
|
||||
public Pair<byte[], byte[]> computeParameters(PacketHeader header) {
|
||||
ByteBuffer temporaryByteBuffer = ByteBuffer
|
||||
.allocate(key.length == 20 ? 26 : 70)
|
||||
.order(ByteOrder.BIG_ENDIAN);
|
||||
|
||||
temporaryByteBuffer.put((byte) (header.getRole() == ProtocolRole.SERVER ? 0x30 : 0x31));
|
||||
temporaryByteBuffer.put((byte) (header.getType().getIndex() & 0xFF));
|
||||
temporaryByteBuffer.put((byte) 0); // TODO generation
|
||||
|
||||
if (key.length == 20) {
|
||||
//temporary[6 - 26] = SIV[0 - 20]
|
||||
temporaryByteBuffer.put(key, 0, 20);
|
||||
} else {
|
||||
//temporary[6 - 70] = SIV[0 - 64]
|
||||
temporaryByteBuffer.put(key, 0, 64);
|
||||
}
|
||||
|
||||
byte[] key_nonce = SHA256.digest(temporaryByteBuffer.array());
|
||||
|
||||
byte[] key = new byte[16];
|
||||
byte[] nonce = new byte[16];
|
||||
|
||||
System.arraycopy(key_nonce, 0, key, 0, 16);
|
||||
System.arraycopy(key_nonce, 16, nonce, 0, 16);
|
||||
|
||||
// key[0] = key[0] xor ((PId & 0xFF00) >> 8)
|
||||
// key[1] = key[1] xor ((PId & 0x00FF) >> 0)
|
||||
|
||||
key[0] = (byte) (key[0] ^ ((byte) (header.getType().getIndex() & 0xFF00) >> 8));
|
||||
key[1] = (byte) (key[0] ^ ((byte) (header.getType().getIndex() & 0x00FF) >> 0));
|
||||
|
||||
return new Pair<>(key, nonce);
|
||||
}
|
||||
|
||||
public byte[] encrypt(PacketHeader header, byte[] body) {
|
||||
return transform(header, body, true);
|
||||
}
|
||||
|
||||
public byte[] decrypt(PacketHeader header, byte[] body) {
|
||||
return transform(header, body, false);
|
||||
}
|
||||
|
||||
private byte[] transform(PacketHeader header, byte[] body, boolean encrypt) {
|
||||
Pair<byte[], byte[]> parameters = computeParameters(header);
|
||||
|
||||
byte[] associatedText = new byte[8];
|
||||
|
||||
CipherParameters cipherParameters = new AEADParameters(new KeyParameter(
|
||||
parameters.getKey()),
|
||||
8 * associatedText.length,
|
||||
parameters.getValue(),
|
||||
encrypt ? associatedText : header.getMac()
|
||||
);
|
||||
|
||||
byte[] result;
|
||||
int len;
|
||||
synchronized (cipher){
|
||||
cipher.init(encrypt, cipherParameters);
|
||||
|
||||
result = new byte[cipher.getOutputSize(body.length)];
|
||||
len = cipher.processBytes(body, 0, body.length, result, 0);
|
||||
|
||||
try {
|
||||
len += cipher.doFinal(result, len);
|
||||
} catch (InvalidCipherTextException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] output = new byte[len];
|
||||
System.arraycopy(result, 0, output, 0, len);
|
||||
|
||||
if (encrypt)
|
||||
header.setMac(associatedText);
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.github.manevolent.ts3j.protocol.socket;
|
||||
|
||||
import com.github.manevolent.ts3j.protocol.packet.transformation.DefaultPacketTransformation;
|
||||
import com.github.manevolent.ts3j.protocol.packet.transformation.PacketTransformation;
|
||||
|
||||
public abstract class AbstractTeamspeakSocket implements TeamspeakSocket {
|
||||
private PacketTransformation transformation = new DefaultPacketTransformation();
|
||||
|
||||
@Override
|
||||
public PacketTransformation getPacketTransformation() {
|
||||
return transformation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPacketTransformation(PacketTransformation transformation) {
|
||||
this.transformation = transformation;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package com.github.manevolent.ts3j.protocol.socket;
|
||||
|
||||
import com.github.manevolent.ts3j.protocol.NetworkPacket;
|
||||
import com.github.manevolent.ts3j.protocol.SocketRole;
|
||||
import com.github.manevolent.ts3j.protocol.TeamspeakSocket;
|
||||
import com.github.manevolent.ts3j.protocol.header.HeaderFlag;
|
||||
import com.github.manevolent.ts3j.protocol.header.PacketHeader;
|
||||
import com.github.manevolent.ts3j.protocol.packet.Packet;
|
||||
import com.github.manevolent.ts3j.util.Ts3Logging;
|
||||
@@ -17,7 +17,7 @@ import java.nio.ByteOrder;
|
||||
*
|
||||
* Used simply to transcribe packets on the network
|
||||
*/
|
||||
public class LocalTeamspeakSocket implements TeamspeakSocket {
|
||||
public class LocalTeamspeakSocket extends AbstractTeamspeakSocket implements TeamspeakSocket {
|
||||
private final SocketRole socketRole;
|
||||
|
||||
private final DatagramSocket datagramSocket;
|
||||
@@ -88,7 +88,20 @@ public class LocalTeamspeakSocket implements TeamspeakSocket {
|
||||
|
||||
ByteBuffer outputBuffer = ByteBuffer.allocate(networkPacket.getSize());
|
||||
outputBuffer.order(ByteOrder.BIG_ENDIAN);
|
||||
networkPacket.write(outputBuffer);
|
||||
networkPacket.writeHeader(outputBuffer);
|
||||
|
||||
if (networkPacket.getHeader().getType().isEncrypted() &&
|
||||
!networkPacket.getHeader().getPacketFlag(HeaderFlag.UNENCRYPTED)) {
|
||||
ByteBuffer encryptionBuffer = ByteBuffer.allocate(500);
|
||||
networkPacket.writeBody(encryptionBuffer);
|
||||
|
||||
byte[] unencryptedBody = new byte[encryptionBuffer.position()];
|
||||
System.arraycopy(encryptionBuffer.array(), 0, unencryptedBody, 0, unencryptedBody.length);
|
||||
|
||||
outputBuffer.put(getPacketTransformation().encrypt(header, unencryptedBody));
|
||||
} else {
|
||||
networkPacket.writeBody(outputBuffer);
|
||||
}
|
||||
|
||||
Ts3Logging.debug("[PROTOCOL] WRITE " + packet.getType().name());
|
||||
|
||||
@@ -120,7 +133,17 @@ public class LocalTeamspeakSocket implements TeamspeakSocket {
|
||||
networkPacket.readHeader(buffer);
|
||||
|
||||
Ts3Logging.debug("[PROTOCOL] READ " + networkPacket.getHeader().getType().name());
|
||||
|
||||
if (networkPacket.getHeader().getType().isEncrypted()) {
|
||||
byte[] transformBuffer = new byte[buffer.remaining()];
|
||||
buffer.get(transformBuffer);
|
||||
|
||||
networkPacket.readBody(ByteBuffer.wrap(
|
||||
getPacketTransformation().decrypt(networkPacket.getHeader(), transformBuffer)
|
||||
));
|
||||
} else {
|
||||
networkPacket.readBody(buffer);
|
||||
}
|
||||
|
||||
return networkPacket;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.github.manevolent.ts3j.protocol.socket;
|
||||
|
||||
import com.github.manevolent.ts3j.protocol.SocketRole;
|
||||
import com.github.manevolent.ts3j.protocol.header.PacketHeader;
|
||||
import com.github.manevolent.ts3j.protocol.packet.Packet;
|
||||
import com.github.manevolent.ts3j.protocol.packet.transformation.PacketTransformation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface TeamspeakSocket {
|
||||
SocketRole getSocketRole();
|
||||
|
||||
void send(PacketHeader header, Packet packet) throws IOException;
|
||||
|
||||
PacketTransformation getPacketTransformation();
|
||||
|
||||
void setPacketTransformation(PacketTransformation transformation);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user