Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
package com.github.manevolent.ts3j.protocol;
|
||||
|
||||
import org.xbill.DNS.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class TS3DNS {
|
||||
private static final int TS3_VOICE_DEFAULT_PORT = 9987;
|
||||
private static final int TS3_QUERY_DEFAULT_PORT = 10011;
|
||||
private static final int TS3_FILETRANSFER_DEFAULT_PORT = 30033;
|
||||
private static final int TSDNS_DEFAULT_PORT = 41144;
|
||||
|
||||
private static final String DNS_PREFIX_TCP = "_tsdns._tcp.";
|
||||
private static final String DNS_PREFIX_UDP = "_ts3._udp.";
|
||||
|
||||
private static List<InetSocketAddress> lookupSRV(String domain) throws IOException {
|
||||
org.xbill.DNS.Record[] records = new Lookup(domain, Type.SRV).run();
|
||||
|
||||
if (records == null || records.length <= 0) throw new UnknownHostException("Host not found");
|
||||
|
||||
return Arrays.stream(records)
|
||||
.filter(Objects::nonNull)
|
||||
.map(x -> (SRVRecord) x)
|
||||
.filter(x -> x.getTarget() != null)
|
||||
.sorted((a, b) -> {
|
||||
// Loose sorting
|
||||
int prioComp = Integer.compare(a.getPriority(), b.getPriority());
|
||||
if (prioComp != 0) return prioComp;
|
||||
else return Integer.compare(a.getWeight(), b.getWeight());
|
||||
})
|
||||
.map(x -> new InetSocketAddress(x.getTarget().toString(), x.getPort()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<InetSocketAddress> lookup(String domain) throws IOException {
|
||||
return lookupSRV(DNS_PREFIX_UDP + domain);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -40,7 +40,7 @@ public class PacketReassembly {
|
||||
temporaryCounter.setPacketId(currentPacketId.getKey());
|
||||
temporaryCounter.setGeneration(currentPacketId.getValue());
|
||||
|
||||
while (true) {
|
||||
while (queue.size() > 0) {
|
||||
Pair<Integer, Integer> thisPacketId = temporaryCounter.current();
|
||||
Packet packet = queue.get(thisPacketId.getKey());
|
||||
|
||||
|
||||
+42
-41
@@ -1,9 +1,11 @@
|
||||
package com.github.manevolent.ts3j.protocol.packet.handler.client;
|
||||
|
||||
import com.github.manevolent.ts3j.command.Command;
|
||||
import com.github.manevolent.ts3j.command.SingleCommand;
|
||||
import com.github.manevolent.ts3j.command.parameter.CommandSingleParameter;
|
||||
import com.github.manevolent.ts3j.protocol.Packet;
|
||||
import com.github.manevolent.ts3j.protocol.ProtocolRole;
|
||||
import com.github.manevolent.ts3j.protocol.TS3DNS;
|
||||
import com.github.manevolent.ts3j.protocol.client.ClientConnectionState;
|
||||
import com.github.manevolent.ts3j.protocol.packet.PacketBody2Command;
|
||||
import com.github.manevolent.ts3j.protocol.packet.PacketBody8Init1;
|
||||
@@ -188,49 +190,48 @@ public class LocalClientHandlerConnecting extends LocalClientHandler {
|
||||
|
||||
alphaBytes = null;
|
||||
|
||||
getClient().writePacket(new PacketBody2Command(
|
||||
Command clientinit = new SingleCommand(
|
||||
"clientinit",
|
||||
ProtocolRole.CLIENT,
|
||||
new SingleCommand(
|
||||
"clientinit",
|
||||
ProtocolRole.CLIENT,
|
||||
new CommandSingleParameter("client_nickname", getClient().getNickname()),
|
||||
new CommandSingleParameter("client_version", "3.?.? [Build: 5680278000]"),
|
||||
new CommandSingleParameter("client_platform", "Windows"),
|
||||
new CommandSingleParameter(
|
||||
"client_version_sign",
|
||||
"DX5NIYLvfJEUjuIbCidnoeozxIDRRkpq3I9vVMBmE9L2qnekOoBzSenkzsg2lC9CMv8K5hkEzhr2TYUYSwUXCg=="
|
||||
),
|
||||
new CommandSingleParameter("client_input_hardware", "1"),
|
||||
new CommandSingleParameter("client_output_hardware", "1"),
|
||||
new CommandSingleParameter("client_default_channel",
|
||||
getClient().getOption("client.default_channel", String.class)
|
||||
),
|
||||
new CommandSingleParameter("client_default_channel_password",
|
||||
getClient().getOption("client.default_channel_password", String.class)
|
||||
),
|
||||
new CommandSingleParameter(
|
||||
"client_server_password",
|
||||
getClient().getOption("client.server_password", String.class)
|
||||
),
|
||||
new CommandSingleParameter("client_nickname_phonetic",
|
||||
getClient().getOption("client.nickname_phonetic", String.class)
|
||||
),
|
||||
new CommandSingleParameter("client_meta_data", ""),
|
||||
new CommandSingleParameter("client_default_token",
|
||||
getClient().getOption("client.default_token", String.class)
|
||||
),
|
||||
new CommandSingleParameter(
|
||||
"client_key_offset",
|
||||
Long.toString(getClient().getIdentity().getKeyOffset())
|
||||
),
|
||||
new CommandSingleParameter(
|
||||
"hwid",
|
||||
getClient().getOption("client.hwid", String.class) != null ?
|
||||
getClient().getOption("client.hwid", String.class) :
|
||||
"+LyYqbDqOvEEpN5pdAbF8/v5kZ0="
|
||||
)
|
||||
new CommandSingleParameter("client_nickname", getClient().getNickname()),
|
||||
new CommandSingleParameter("client_version", "3.?.? [Build: 5680278000]"),
|
||||
new CommandSingleParameter("client_platform", "Windows"),
|
||||
new CommandSingleParameter(
|
||||
"client_version_sign",
|
||||
"DX5NIYLvfJEUjuIbCidnoeozxIDRRkpq3I9vVMBmE9L2qnekOoBzSenkzsg2lC9CMv8K5hkEzhr2TYUYSwUXCg=="
|
||||
),
|
||||
new CommandSingleParameter("client_input_hardware", "1"),
|
||||
new CommandSingleParameter("client_output_hardware", "1"),
|
||||
new CommandSingleParameter("client_default_channel",
|
||||
getClient().getOption("client.default_channel", String.class)
|
||||
),
|
||||
new CommandSingleParameter("client_default_channel_password",
|
||||
getClient().getOption("client.default_channel_password", String.class)
|
||||
),
|
||||
new CommandSingleParameter("client_server_password",
|
||||
getClient().getOption("client.server_password", String.class)
|
||||
),
|
||||
new CommandSingleParameter("client_nickname_phonetic",
|
||||
getClient().getOption("client.nickname_phonetic", String.class)
|
||||
),
|
||||
new CommandSingleParameter("client_meta_data", ""),
|
||||
new CommandSingleParameter("client_default_token",
|
||||
getClient().getOption("client.default_token", String.class)
|
||||
),
|
||||
new CommandSingleParameter("client_key_offset",
|
||||
Long.toString(getClient().getIdentity().getKeyOffset())
|
||||
),
|
||||
new CommandSingleParameter(
|
||||
"hwid",
|
||||
getClient().getOption("client.hwid", String.class) != null ?
|
||||
getClient().getOption("client.hwid", String.class) :
|
||||
"+LyYqbDqOvEEpN5pdAbF8/v5kZ0="
|
||||
)
|
||||
));
|
||||
);
|
||||
|
||||
Ts3Debugging.debug(clientinit.build());
|
||||
|
||||
getClient().writePacket(new PacketBody2Command(ProtocolRole.CLIENT, clientinit));
|
||||
|
||||
getClient().setCommandProcessor(getClient());
|
||||
getClient().setState(ClientConnectionState.RETRIEVING_DATA);
|
||||
|
||||
+22
@@ -1,9 +1,31 @@
|
||||
package com.github.manevolent.ts3j.protocol.packet.handler.client;
|
||||
|
||||
import com.github.manevolent.ts3j.command.CommandProcessException;
|
||||
import com.github.manevolent.ts3j.command.CommandProcessor;
|
||||
import com.github.manevolent.ts3j.command.MultiCommand;
|
||||
import com.github.manevolent.ts3j.protocol.client.ClientConnectionState;
|
||||
import com.github.manevolent.ts3j.protocol.socket.client.LocalTeamspeakClientSocket;
|
||||
|
||||
|
||||
public class LocalClientHandlerRetrievingData extends LocalClientHandlerFull {
|
||||
public LocalClientHandlerRetrievingData(LocalTeamspeakClientSocket client) {
|
||||
super(client);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleCommand(MultiCommand command) throws CommandProcessException {
|
||||
if (command.getName().equalsIgnoreCase("error")) {
|
||||
try {
|
||||
getClient().setState(ClientConnectionState.DISCONNECTED);
|
||||
} catch (Exception e) {
|
||||
getClient().getExceptionHandler().accept(e);
|
||||
}
|
||||
|
||||
throw new CommandProcessException(command.simplifyOne().get("msg").getValue());
|
||||
}
|
||||
|
||||
CommandProcessor processor = getClient().getCommandProcessor();
|
||||
if (processor != null) processor.process(getClient(), command);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-4
@@ -107,8 +107,8 @@ public abstract class AbstractTeamspeakClientSocket
|
||||
|
||||
private boolean reading = false;
|
||||
|
||||
protected AbstractTeamspeakClientSocket() {
|
||||
super(SocketRole.CLIENT);
|
||||
protected AbstractTeamspeakClientSocket(SocketRole role) {
|
||||
super(role);
|
||||
|
||||
// Initialize reassembly queue
|
||||
for (PacketBodyType bodyType : PacketBodyType.values())
|
||||
@@ -205,8 +205,6 @@ public abstract class AbstractTeamspeakClientSocket
|
||||
}
|
||||
|
||||
protected void onDisconnect() {
|
||||
clientOptions.clear();
|
||||
|
||||
clientId = -1;
|
||||
|
||||
readQueue.clear();
|
||||
|
||||
+56
-7
@@ -12,9 +12,7 @@ import com.github.manevolent.ts3j.command.response.CommandResponse;
|
||||
import com.github.manevolent.ts3j.event.*;
|
||||
import com.github.manevolent.ts3j.identity.LocalIdentity;
|
||||
import com.github.manevolent.ts3j.identity.Uid;
|
||||
import com.github.manevolent.ts3j.protocol.NetworkPacket;
|
||||
import com.github.manevolent.ts3j.protocol.PacketKind;
|
||||
import com.github.manevolent.ts3j.protocol.ProtocolRole;
|
||||
import com.github.manevolent.ts3j.protocol.*;
|
||||
import com.github.manevolent.ts3j.protocol.client.ClientConnectionState;
|
||||
import com.github.manevolent.ts3j.protocol.header.PacketHeader;
|
||||
import com.github.manevolent.ts3j.protocol.packet.PacketBody0Voice;
|
||||
@@ -60,7 +58,7 @@ public class LocalTeamspeakClientSocket
|
||||
private Map<Integer, ClientCommandResponse> awaitingCommands = new ConcurrentHashMap<>();
|
||||
|
||||
public LocalTeamspeakClientSocket() {
|
||||
super();
|
||||
super(SocketRole.CLIENT);
|
||||
|
||||
namedProcessors.put("initserver", new InitServerHandler());
|
||||
|
||||
@@ -254,12 +252,34 @@ public class LocalTeamspeakClientSocket
|
||||
remote = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initiates a connection to a server
|
||||
* @param hostname Hostname to contact
|
||||
* @param password server password (may be null)
|
||||
* @param timeout timeout, in milliseconds, to complete a connection.
|
||||
*/
|
||||
public void connect(String hostname, String password, long timeout) throws
|
||||
IOException,
|
||||
TimeoutException {
|
||||
|
||||
InetSocketAddress address;
|
||||
|
||||
try {
|
||||
// Attempt TS3DNS
|
||||
address = TS3DNS.lookup(hostname).stream().findFirst().orElseThrow(() -> new UnknownHostException(hostname));
|
||||
} catch (UnknownHostException e) {
|
||||
address = new InetSocketAddress(hostname, 9987);
|
||||
}
|
||||
|
||||
connect(address, password, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates a connection to a server
|
||||
* @param remote remote sever to contact
|
||||
* @param password server password
|
||||
* @param password server password (may be null)
|
||||
* @param timeout timeout, in milliseconds, to complete a connection.
|
||||
* @throws IOException
|
||||
*/
|
||||
public void connect(InetSocketAddress remote, String password, long timeout)
|
||||
throws IOException, TimeoutException {
|
||||
@@ -286,7 +306,7 @@ public class LocalTeamspeakClientSocket
|
||||
|
||||
setOption("client.hostname", remote.getHostString());
|
||||
|
||||
if (password != null) setOption("client.password", password);
|
||||
if (password != null && password.length() > 0) setOption("client.password", password);
|
||||
|
||||
setState(ClientConnectionState.CONNECTING);
|
||||
|
||||
@@ -297,6 +317,7 @@ public class LocalTeamspeakClientSocket
|
||||
0.01F,
|
||||
new MicrophoneTask()
|
||||
);
|
||||
|
||||
microphoneThread.setDaemon(true);
|
||||
microphoneThread.start();
|
||||
} catch (TimeoutException e) {
|
||||
@@ -629,6 +650,14 @@ public class LocalTeamspeakClientSocket
|
||||
super.setNickname(nickname);
|
||||
}
|
||||
|
||||
public void setHWID(String hwid) {
|
||||
setOption("client.hwid", hwid);
|
||||
}
|
||||
|
||||
public String getHWID() {
|
||||
return getOption("client.hwid", String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Commands
|
||||
*/
|
||||
@@ -878,6 +907,26 @@ public class LocalTeamspeakClientSocket
|
||||
return executeCommand(command, x -> new Client(x.toMap())).get();
|
||||
}
|
||||
|
||||
public void serverGroupAddClient(int groupId, int clientDatabaseId)
|
||||
throws IOException, TimeoutException, ExecutionException, InterruptedException {
|
||||
Command command = new SingleCommand("servergroupaddclient", ProtocolRole.CLIENT);
|
||||
|
||||
command.add(new CommandSingleParameter("sgid", Integer.toString(groupId)));
|
||||
command.add(new CommandSingleParameter("cldbid", Integer.toString(clientDatabaseId)));
|
||||
|
||||
executeCommand(command).complete();
|
||||
}
|
||||
|
||||
public void serverGroupRemoveClient(int groupId, int clientDatabaseId)
|
||||
throws IOException, TimeoutException, ExecutionException, InterruptedException {
|
||||
Command command = new SingleCommand("servergroupdelclient", ProtocolRole.CLIENT);
|
||||
|
||||
command.add(new CommandSingleParameter("sgid", Integer.toString(groupId)));
|
||||
command.add(new CommandSingleParameter("cldbid", Integer.toString(clientDatabaseId)));
|
||||
|
||||
executeCommand(command).complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves one or more clients specified with clid to the channel with ID cid. If
|
||||
the target channel has a password, it needs to be specified with cpw. If the
|
||||
|
||||
Reference in New Issue
Block a user