I've refactored most of the code. Init1 handshake is basically done, all we have to do now is send the clientinitiv command and we'll be in the higher level authentication steps.
I've made the code more server-ready as well since I plan to implement a server API at some point.
This commit is contained in:
@@ -1,300 +0,0 @@
|
||||
package com.github.manevolent.ts3j;
|
||||
|
||||
import com.github.manevolent.ts3j.command.Command;
|
||||
import com.github.manevolent.ts3j.command.part.CommandSingleParameter;
|
||||
import com.github.manevolent.ts3j.command.response.CommandResponse;
|
||||
import com.github.manevolent.ts3j.enums.ConnectionState;
|
||||
import com.github.manevolent.ts3j.enums.PacketFlags;
|
||||
import com.github.manevolent.ts3j.enums.PacketType;
|
||||
import com.github.manevolent.ts3j.handler.TeamspeakClientHandler;
|
||||
import com.github.manevolent.ts3j.util.Ts3Logging;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class TeamspeakClient {
|
||||
private final PacketReceiver packetReceiver = new PacketReceiver();
|
||||
|
||||
private final DatagramSocket datagramSocket;
|
||||
private final DatagramPacket datagramPacket = new DatagramPacket(new byte[1500], 1500);
|
||||
|
||||
private final Object connectionStateLock = new Object();
|
||||
|
||||
private TeamspeakClientHandler handler;
|
||||
|
||||
private InetSocketAddress remote = null;
|
||||
private ConnectionState connectionState = null;
|
||||
private int returnCodeIndex = 0;
|
||||
|
||||
public TeamspeakClient(DatagramSocket datagramSocket) {
|
||||
this.datagramSocket = datagramSocket;
|
||||
}
|
||||
|
||||
public TeamspeakClient() throws SocketException {
|
||||
this(new DatagramSocket());
|
||||
|
||||
setConnectionState(ConnectionState.DISCONNECTED);
|
||||
}
|
||||
|
||||
protected void setConnectionState(ConnectionState state) {
|
||||
synchronized (connectionStateLock) {
|
||||
if (state != this.connectionState) {
|
||||
boolean wasDisconnected = this.connectionState == ConnectionState.DISCONNECTED;
|
||||
|
||||
this.connectionState = state;
|
||||
|
||||
if (wasDisconnected) {
|
||||
Ts3Logging.debug("Starting network receiver thread...");
|
||||
|
||||
Thread receiverThread = new Thread(new PacketReceiver());
|
||||
receiverThread.setDaemon(true);
|
||||
receiverThread.start();
|
||||
}
|
||||
|
||||
if (handler != null)
|
||||
handler.handleConnectionStateChanging(state);
|
||||
|
||||
if (handler == null || handler.getClass() != state.getHandlerClass()) {
|
||||
Ts3Logging.debug("Assigning " + state.getHandlerClass().getName() + " handler...");
|
||||
|
||||
handler = state.createHandler(this);
|
||||
|
||||
try {
|
||||
handler.onAssigned();
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
connectionStateLock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return connectionState == ConnectionState.CONNECTED;
|
||||
}
|
||||
|
||||
public ConnectionState getConnectionState() {
|
||||
return connectionState;
|
||||
}
|
||||
|
||||
private void joinConnectionState(ConnectionState state, long wait)
|
||||
throws InterruptedException, TimeoutException {
|
||||
synchronized (connectionStateLock) {
|
||||
if (connectionState != state) {
|
||||
connectionStateLock.wait(wait);
|
||||
|
||||
if (connectionState != state)
|
||||
throw new TimeoutException("timeout waiting for " + state.name() + " state");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CommandResponse sendCommand(Command command) throws IOException {
|
||||
if (command.willExpectResponse() && !isConnected())
|
||||
throw new IOException("not connected");
|
||||
|
||||
CommandResponse response;
|
||||
|
||||
if (command.willExpectResponse()) {
|
||||
int returnCodeIndex = ++ this.returnCodeIndex;
|
||||
command.appendParameter(new CommandSingleParameter("return_code", returnCodeIndex));
|
||||
response = new CommandResponse(command, returnCodeIndex);
|
||||
} else {
|
||||
response = new CommandResponse(command, -1);
|
||||
}
|
||||
|
||||
String commandString = command.toString();
|
||||
|
||||
response.setDispatchedTime(System.currentTimeMillis());
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public void connect(InetSocketAddress remote, String password, long timeout) throws IOException {
|
||||
try {
|
||||
if (connectionState != ConnectionState.DISCONNECTED)
|
||||
throw new IllegalStateException(connectionState.name());
|
||||
|
||||
datagramSocket.connect(remote);
|
||||
|
||||
setConnectionState(ConnectionState.CONNECTING);
|
||||
joinConnectionState(ConnectionState.CONNECTED, timeout);
|
||||
} catch (Throwable e) {
|
||||
setConnectionState(ConnectionState.DISCONNECTED);
|
||||
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void send(PacketType type, byte[] data) throws IOException {
|
||||
C2SPacket packet = createOutgoingPacket(type, data);
|
||||
}
|
||||
|
||||
private C2SPacket createOutgoingPacket(PacketType type, byte[] data) throws IOException {
|
||||
C2SPacket packet = new C2SPacket();
|
||||
|
||||
//TODO
|
||||
packet.setPacketId(0);
|
||||
|
||||
//TODO
|
||||
packet.setGenerationId(0);
|
||||
|
||||
//TODO
|
||||
packet.setClientId(0);
|
||||
|
||||
//TODO
|
||||
packet.packetFlags |= 0;
|
||||
|
||||
switch (type) {
|
||||
case VOICE:
|
||||
case VOICE_WHISPER:
|
||||
|
||||
break;
|
||||
case COMMAND:
|
||||
case COMMAND_LOW:
|
||||
|
||||
break;
|
||||
case PING:
|
||||
|
||||
break;
|
||||
case PONG:
|
||||
|
||||
break;
|
||||
case ACK:
|
||||
case ACK_LOW:
|
||||
|
||||
break;
|
||||
case INIT:
|
||||
packet.setPacketFlags(packet.getPacketFlags() | PacketFlags.UNENCRYPTED.getIndex());
|
||||
break;
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wire packet write
|
||||
* @param packet Packet to write
|
||||
* @throws IOException
|
||||
*/
|
||||
private void sendNetworkPacket(DatagramPacket packet) throws IOException {
|
||||
Ts3Logging.debug(
|
||||
"[NETWORK] WRITE Len=" + packet.getLength() + " to " + datagramSocket.getRemoteSocketAddress() +
|
||||
"\n" + Ts3Logging.getHex(packet.getData())
|
||||
);
|
||||
|
||||
packet.setSocketAddress(datagramSocket.getRemoteSocketAddress());
|
||||
|
||||
datagramSocket.send(packet);
|
||||
}
|
||||
|
||||
private DatagramPacket receiveNetworkPacket() throws IOException {
|
||||
datagramSocket.receive(datagramPacket);
|
||||
return datagramPacket;
|
||||
}
|
||||
|
||||
private void handleNetworkPacket(DatagramPacket packet) {
|
||||
Ts3Logging.debug(
|
||||
"[NETWORK] READ Len=" + packet.getLength() + " from " + packet.getSocketAddress() +
|
||||
"\n" + Ts3Logging.getHex(packet.getData())
|
||||
);
|
||||
|
||||
if (handler != null) handler.handleNetworkPacket(packet);
|
||||
}
|
||||
|
||||
public InetSocketAddress getRemote() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
private class PacketReceiver implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
while (connectionState != ConnectionState.DISCONNECTED) {
|
||||
try {
|
||||
handleNetworkPacket(receiveNetworkPacket());
|
||||
} catch (IOException e) {
|
||||
Ts3Logging.info("Problem handling packet: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
Ts3Logging.debug("Leaving packet receiver");
|
||||
}
|
||||
}
|
||||
|
||||
private class C2SPacket {
|
||||
private int packetId;
|
||||
private int generationId;
|
||||
private int clientId;
|
||||
private int packetFlags;
|
||||
|
||||
private PacketType type;
|
||||
private byte[] data;
|
||||
private Date lastSendTime;
|
||||
|
||||
public PacketType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(PacketType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Date getLastSendTime() {
|
||||
return lastSendTime;
|
||||
}
|
||||
|
||||
public int getPacketId() {
|
||||
return packetId;
|
||||
}
|
||||
|
||||
public void setPacketId(int packetId) {
|
||||
this.packetId = packetId;
|
||||
}
|
||||
|
||||
public int getGenerationId() {
|
||||
return generationId;
|
||||
}
|
||||
|
||||
public void setGenerationId(int generationId) {
|
||||
this.generationId = generationId;
|
||||
}
|
||||
|
||||
public int getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(int clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public int getPacketFlags() {
|
||||
return packetFlags;
|
||||
}
|
||||
|
||||
public void setPacketFlags(int packetFlags) {
|
||||
this.packetFlags = packetFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends, or re-sends, a packet
|
||||
*/
|
||||
public void send() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
|
||||
package com.github.manevolent.ts3j.enums;
|
||||
|
||||
import com.github.manevolent.ts3j.TeamspeakClient;
|
||||
import com.github.manevolent.ts3j.handler.*;
|
||||
|
||||
public enum ConnectionState {
|
||||
CONNECTING(TeamspeakClientHandlerConnecting.class),
|
||||
NEGOTIATING(TeamspeakClientHandlerNegotiating.class),
|
||||
CONNECTED(TeamspeakClientHandlerConnected.class),
|
||||
DISCONNECTED(TeamspeakClientHandlerDisconnected.class);
|
||||
|
||||
private final Class<? extends TeamspeakClientHandler> clazz;
|
||||
|
||||
ConnectionState(Class<? extends TeamspeakClientHandler> clazz) {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
public Class<? extends TeamspeakClientHandler> getHandlerClass() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public TeamspeakClientHandler createHandler(TeamspeakClient client) {
|
||||
try {
|
||||
return clazz.getConstructor(TeamspeakClient.class).newInstance(client);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.github.manevolent.ts3j.enums;
|
||||
|
||||
public enum PacketFlags {
|
||||
NONE(0x0),
|
||||
FRAGMENTED(0X10),
|
||||
NEW_PROTOCOL(0x20),
|
||||
COMPRESSED(0x40),
|
||||
UNENCRYPTED(0x80);
|
||||
|
||||
private final int index;
|
||||
|
||||
PacketFlags(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public static PacketFlags fromId(int index) {
|
||||
for (PacketFlags value : values())
|
||||
if (value.getIndex() == index) return value;
|
||||
|
||||
throw new IllegalArgumentException("invalid index: " + index);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package com.github.manevolent.ts3j.enums;
|
||||
|
||||
public enum PacketType {
|
||||
VOICE(0x0),
|
||||
VOICE_WHISPER(0x1),
|
||||
COMMAND(0x2),
|
||||
COMMAND_LOW(0x3),
|
||||
PING(0x4),
|
||||
PONG(0x5),
|
||||
ACK(0x6),
|
||||
ACK_LOW(0x7),
|
||||
INIT(0x8)
|
||||
;
|
||||
|
||||
private final int index;
|
||||
|
||||
PacketType(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public static PacketType fromId(int index) {
|
||||
for (PacketType value : values())
|
||||
if (value.getIndex() == index) return value;
|
||||
|
||||
throw new IllegalArgumentException("invalid index: " + index);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,23 @@
|
||||
package com.github.manevolent.ts3j.handler;
|
||||
|
||||
import com.github.manevolent.ts3j.TeamspeakClient;
|
||||
import com.github.manevolent.ts3j.enums.ConnectionState;
|
||||
import com.github.manevolent.ts3j.Teamspeak3Client;
|
||||
import com.github.manevolent.ts3j.ClientConnectionState;
|
||||
import com.github.manevolent.ts3j.protocol.NetworkPacket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
|
||||
public abstract class TeamspeakClientHandler {
|
||||
private final TeamspeakClient client;
|
||||
private final Teamspeak3Client client;
|
||||
|
||||
protected TeamspeakClientHandler(TeamspeakClient client) {
|
||||
protected TeamspeakClientHandler(Teamspeak3Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public void handleConnectionStateChanging(ConnectionState connectionState) {
|
||||
|
||||
protected final Teamspeak3Client getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void handleNetworkPacket(DatagramPacket packet) {
|
||||
public void handleConnectionStateChanging(ClientConnectionState clientConnectionState) {
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ public abstract class TeamspeakClientHandler {
|
||||
|
||||
}
|
||||
|
||||
protected TeamspeakClient getClient() {
|
||||
return client;
|
||||
public void handlePacket(NetworkPacket packet) throws IOException {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
package com.github.manevolent.ts3j.handler;
|
||||
|
||||
import com.github.manevolent.ts3j.TeamspeakClient;
|
||||
import com.github.manevolent.ts3j.Teamspeak3Client;
|
||||
|
||||
public class TeamspeakClientHandlerConnected extends TeamspeakClientHandler {
|
||||
public TeamspeakClientHandlerConnected(TeamspeakClient client) {
|
||||
public TeamspeakClientHandlerConnected(Teamspeak3Client client) {
|
||||
super(client);
|
||||
}
|
||||
}
|
||||
|
||||
+96
-55
@@ -1,80 +1,121 @@
|
||||
package com.github.manevolent.ts3j.handler;
|
||||
|
||||
import com.github.manevolent.ts3j.TeamspeakClient;
|
||||
import com.github.manevolent.ts3j.enums.PacketType;
|
||||
import com.github.manevolent.ts3j.Teamspeak3Client;
|
||||
import com.github.manevolent.ts3j.protocol.NetworkPacket;
|
||||
import com.github.manevolent.ts3j.protocol.ProtocolRole;
|
||||
import com.github.manevolent.ts3j.protocol.packet.Packet8Init1;
|
||||
import com.github.manevolent.ts3j.util.Ts3Logging;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
public class TeamspeakClientHandlerConnecting extends TeamspeakClientHandler {
|
||||
private byte[] randomBytes;
|
||||
|
||||
|
||||
public TeamspeakClientHandlerConnecting(TeamspeakClient client) {
|
||||
public TeamspeakClientHandlerConnecting(Teamspeak3Client client) {
|
||||
super(client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAssigned() throws IOException {
|
||||
Ts3Logging.debug("Connecting: sending Init1...");
|
||||
|
||||
processInit1();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the first client dispatch of the Init1 packet (C2S initial handshake packet)
|
||||
*/
|
||||
public void processInit1() throws IOException {
|
||||
processInit1(null);
|
||||
}
|
||||
|
||||
public void processInit1(byte[] data) throws IOException {
|
||||
int versionLen = 4;
|
||||
int initTypeLen = 1;
|
||||
Integer type = null;
|
||||
|
||||
if (data != null) {
|
||||
type = (int) data[0];
|
||||
|
||||
if (data.length < initTypeLen)
|
||||
throw new IllegalArgumentException("invalid Init1 packet (too short)");
|
||||
}
|
||||
|
||||
ByteBuffer buffer = null;
|
||||
|
||||
if (type == null) {
|
||||
buffer = ByteBuffer.allocate(versionLen + initTypeLen + 4 + 4 + 8);
|
||||
|
||||
buffer.put(new byte[] { 0x09, (byte)0x83, (byte)0x8C, (byte)0xCF });
|
||||
buffer.put((byte) 0x00); // initType
|
||||
buffer.order(ByteOrder.BIG_ENDIAN);
|
||||
buffer.putInt((int) (System.currentTimeMillis() / 1000L));
|
||||
Packet8Init1 packet = new Packet8Init1(ProtocolRole.CLIENT);
|
||||
|
||||
Packet8Init1.Step0 step = new Packet8Init1.Step0();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < 4; i++)
|
||||
buffer.put((byte) random.nextInt(256)); // 4byte random
|
||||
} else {
|
||||
switch (type) {
|
||||
case 1:
|
||||
randomBytes = new byte[4];
|
||||
random.nextBytes(randomBytes);
|
||||
step.setRandom(randomBytes);
|
||||
step.setTimestamp((int) ((System.currentTimeMillis() / 1000L) & 0x000000FFFFFF));
|
||||
packet.setStep(step);
|
||||
|
||||
sendInit1(packet);
|
||||
}
|
||||
|
||||
private void sendInit1(Packet8Init1 packet) throws IOException {
|
||||
Ts3Logging.debug("Connecting: sending " + packet.getClass().getSimpleName()
|
||||
+ ":"
|
||||
+ packet.getStep().getClass().getSimpleName() + "..."
|
||||
);
|
||||
|
||||
packet.setVersion(new byte[] { 0x09, (byte)0x83, (byte)0x8C, (byte)0xCF });
|
||||
|
||||
getClient().send(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePacket(NetworkPacket packet) throws IOException {
|
||||
Ts3Logging.debug("Connecting: handling " + packet.getClass().getSimpleName());
|
||||
|
||||
if (packet.getPacket() instanceof Packet8Init1) {
|
||||
Packet8Init1 init1 = (Packet8Init1) packet.getPacket();
|
||||
|
||||
switch (init1.getStep().getNumber()) {
|
||||
case 1:
|
||||
Packet8Init1.Step1 serverReplyStep1 = (Packet8Init1.Step1)init1.getStep();
|
||||
// Check nonce. It's received backwards, so walk backwards over the array received
|
||||
for (int i = 0; i < 4; i ++) {
|
||||
if (randomBytes[3 - i] != serverReplyStep1.getA0reversed()[i])
|
||||
throw new IllegalArgumentException("invalid server nonce");
|
||||
}
|
||||
|
||||
// Build response
|
||||
Packet8Init1 response2 = new Packet8Init1(ProtocolRole.CLIENT);
|
||||
|
||||
Packet8Init1.Step2 step2 = new Packet8Init1.Step2();
|
||||
step2.setA0reversed(serverReplyStep1.getA0reversed());
|
||||
step2.setServerStuff(serverReplyStep1.getServerStuff());
|
||||
response2.setStep(step2);
|
||||
|
||||
sendInit1(response2);
|
||||
break;
|
||||
case 3:
|
||||
Packet8Init1.Step3 serverReplyStep3 = (Packet8Init1.Step3)init1.getStep();
|
||||
|
||||
break;
|
||||
case 0x7F:
|
||||
// 0x7F: Some strange servers do this
|
||||
// the normal client responds by starting again
|
||||
// Calculate 'y'
|
||||
// which is the result of x ^ (2 ^ level) % n as an unsigned
|
||||
// BigInteger. Padded from the lower side with '0x00' when shorter
|
||||
// than 64 bytes.
|
||||
// CITE: https://github.com/Splamy/TS3AudioBot/blob/master/TS3Client/Full/Ts3Crypt.cs
|
||||
// Prepare solution
|
||||
if (serverReplyStep3.getLevel() < 0 || serverReplyStep3.getLevel() > 1_000_000)
|
||||
throw new IllegalArgumentException("RSA challange level is not within an acceptable range");
|
||||
|
||||
BigInteger x = new BigInteger(1, serverReplyStep3.getX());
|
||||
BigInteger n = new BigInteger(1, serverReplyStep3.getN());
|
||||
|
||||
byte[] y = new byte[64];
|
||||
|
||||
byte[] solution =
|
||||
x.modPow(BigInteger.valueOf(2L).pow(serverReplyStep3.getLevel()), n).toByteArray();
|
||||
|
||||
System.arraycopy(
|
||||
solution, Math.max(0, solution.length - 64),
|
||||
y, 64 - solution.length,
|
||||
solution.length
|
||||
);
|
||||
|
||||
// Build response
|
||||
Packet8Init1 response4 = new Packet8Init1(ProtocolRole.CLIENT);
|
||||
|
||||
Packet8Init1.Step4 step4 = new Packet8Init1.Step4();
|
||||
|
||||
step4.setLevel(serverReplyStep3.getLevel());
|
||||
step4.setX(serverReplyStep3.getX());
|
||||
step4.setN(serverReplyStep3.getN());
|
||||
step4.setY(y);
|
||||
step4.setServerStuff(serverReplyStep3.getServerStuff());
|
||||
|
||||
step4.setClientIVcommand(new byte[4]); // TODO
|
||||
|
||||
response4.setStep(step4);
|
||||
|
||||
sendInit1(response4);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("invalid Init1 packet id: " + type);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("unexpected Init1 server step: " + init1.getStep().getNumber());
|
||||
|
||||
if (buffer == null || buffer.position() <= 0)
|
||||
throw new IllegalStateException("invalid send buffer");
|
||||
|
||||
getClient().send(PacketType.INIT, buffer.array());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
package com.github.manevolent.ts3j.handler;
|
||||
|
||||
import com.github.manevolent.ts3j.TeamspeakClient;
|
||||
import com.github.manevolent.ts3j.Teamspeak3Client;
|
||||
|
||||
public class TeamspeakClientHandlerDisconnected extends TeamspeakClientHandler {
|
||||
public TeamspeakClientHandlerDisconnected(TeamspeakClient client) {
|
||||
public TeamspeakClientHandlerDisconnected(Teamspeak3Client client) {
|
||||
super(client);
|
||||
}
|
||||
}
|
||||
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
package com.github.manevolent.ts3j.handler;
|
||||
|
||||
import com.github.manevolent.ts3j.TeamspeakClient;
|
||||
|
||||
public class TeamspeakClientHandlerNegotiating extends TeamspeakClientHandler {
|
||||
public TeamspeakClientHandlerNegotiating(TeamspeakClient client) {
|
||||
super(client);
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,12 @@ package com.github.manevolent.ts3j.util;
|
||||
public final class Ts3Logging {
|
||||
private static final String HEXES = "0123456789ABCDEF";
|
||||
public static String getHex(byte[] raw) {
|
||||
return getHex(raw, raw.length);
|
||||
}
|
||||
public static String getHex(byte[] raw, int len) {
|
||||
final StringBuilder hex = new StringBuilder(2 * raw.length);
|
||||
for (final byte b : raw) {
|
||||
for (int x = 0; x < len; x ++) {
|
||||
byte b = raw[x];
|
||||
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
|
||||
}
|
||||
return hex.toString();
|
||||
@@ -17,4 +21,9 @@ public final class Ts3Logging {
|
||||
public static void debug(String message) {
|
||||
System.err.println("[DEBUG] " + message);
|
||||
}
|
||||
|
||||
public static void debug(String message, Throwable ex) {
|
||||
System.err.println("[DEBUG] " + message);
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.github.manevolent.ts3j;
|
||||
|
||||
import com.github.manevolent.ts3j.enums.ConnectionState;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -11,7 +10,7 @@ public class ServerConnectionTest extends TestCase {
|
||||
}
|
||||
|
||||
public void testParser() throws Exception {
|
||||
TeamspeakClient client = new TeamspeakClient();
|
||||
Teamspeak3Client client = new Teamspeak3Client();
|
||||
|
||||
client.connect(new InetSocketAddress(
|
||||
"voice.teamspeak.com",
|
||||
@@ -20,6 +19,6 @@ public class ServerConnectionTest extends TestCase {
|
||||
10000L
|
||||
);
|
||||
|
||||
assertEquals(client.getConnectionState(), ConnectionState.CONNECTED);
|
||||
assertEquals(client.getClientConnectionState(), ClientConnectionState.CONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user