diff --git a/src/main/java/com/github/manevolent/ts3j/event/ChannelPermHintsEvent.java b/src/main/java/com/github/manevolent/ts3j/event/ChannelPermHintsEvent.java new file mode 100644 index 0000000..e6291e8 --- /dev/null +++ b/src/main/java/com/github/manevolent/ts3j/event/ChannelPermHintsEvent.java @@ -0,0 +1,51 @@ +package com.github.manevolent.ts3j.event; + +/* + * #%L + * TeamSpeak 3 Java API + * %% + * Copyright (C) 2014 Bert De Geyter + * %% + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * #L% + */ + +import com.github.manevolent.ts3j.api.*; + +import java.util.*; + +public class ChannelPermHintsEvent extends BaseEvent { + + public ChannelPermHintsEvent(Map map) { + super(map); + } + + public int getChannelId() { + return getInt(ChannelProperty.CID); + } + + @Override + public void fire(TS3Listener listener) { + listener.onChannelPermHints(this); + } + + public int getFlags() { + return getInt("flags"); + } +} diff --git a/src/main/java/com/github/manevolent/ts3j/event/ClientPermHintsEvent.java b/src/main/java/com/github/manevolent/ts3j/event/ClientPermHintsEvent.java new file mode 100644 index 0000000..292aacb --- /dev/null +++ b/src/main/java/com/github/manevolent/ts3j/event/ClientPermHintsEvent.java @@ -0,0 +1,26 @@ +package com.github.manevolent.ts3j.event; + +import java.util.*; + +public class ClientPermHintsEvent extends BaseEvent { + public ClientPermHintsEvent(Map map) { + super(map); + } + + @Override + public void fire(TS3Listener listener) { + listener.onClientPermHints(this); + } + + public int getClientId() { + return getInt("clid"); + } + + public int getPermId() { + return getInt("permid"); + } + + public int getPermValue() { + return getInt("permvalue"); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/manevolent/ts3j/event/TS3Event.java b/src/main/java/com/github/manevolent/ts3j/event/TS3Event.java index e76b527..c38ffae 100644 --- a/src/main/java/com/github/manevolent/ts3j/event/TS3Event.java +++ b/src/main/java/com/github/manevolent/ts3j/event/TS3Event.java @@ -12,10 +12,10 @@ package com.github.manevolent.ts3j.event; * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -29,62 +29,66 @@ package com.github.manevolent.ts3j.event; import com.github.manevolent.ts3j.command.Command; public interface TS3Event { - void fire(TS3Listener listener); + void fire(TS3Listener listener); - static TS3Event createEvent(Command command) { - switch (command.getName()) { - case "notifytextmessage": - return new TextMessageEvent(command.toMap()); - case "notifycliententerview": - return new ClientJoinEvent(command.toMap()); - case "notifyclientleftview": - return new ClientLeaveEvent(command.toMap()); - case "notifyserveredited": - return new ServerEditedEvent(command.toMap()); - case "notifychanneledited": - return new ChannelEditedEvent(command.toMap()); - case "notifychanneldescriptionchanged": - return new ChannelDescriptionEditedEvent(command.toMap()); - case "notifyclientmoved": - return new ClientMovedEvent(command.toMap()); - case "notifychannelcreated": - return new ChannelCreateEvent(command.toMap()); - case "notifychanneldeleted": - return new ChannelDeletedEvent(command.toMap()); - case "notifychannelmoved": - return new ChannelMovedEvent(command.toMap()); - case "notifychannelpasswordchanged": - return new ChannelPasswordChangedEvent(command.toMap()); - case "notifytokenused": - return new PrivilegeKeyUsedEvent(command.toMap()); - case "notifyservergrouplist": // CLIENT - return new ServerGroupListEvent(command.toMap()); - case "notifychannelgrouplist": // CLIENT - return new ChannelGroupListEvent(command.toMap()); - case "notifyclientchannelgroupchanged": // CLIENT - return new ClientChannelGroupChangedEvent(command.toMap()); - case "notifyclientneededpermissions": // CLIENT - return new ClientNeededPermissionsEvent(command.toMap()); - case "notifyclientupdated": // CLIENT - return new ClientUpdatedEvent(command.toMap()); - case "notifychannelsubscribed": // CLIENT - return new ChannelSubscribedEvent(command.toMap()); - case "notifychannelunsubscribed": // CLIENT - return new ChannelUnsubscribedEvent(command.toMap()); - case "notifyservergroupclientadded": // CLIENT - return new ServerGroupClientAddedEvent(command.toMap()); - case "notifyservergroupclientdeleted": // CLIENT - return new ServerGroupClientDeletedEvent(command.toMap()); - case "notifyclientpoke": // CLIENT - return new ClientPokeEvent(command.toMap()); - case "notifyclientchatcomposing": // CLIENT - return new ClientChatComposingEvent(command.toMap()); - case "notifyclientchatclosed": // CLIENT - return new ClientChatClosedEvent(command.toMap()); - case "notifypermissionlist": // CLIENT - return new PermissionListEvent(command.toMap()); - default: - throw new IllegalArgumentException("unknown event: " + command.getName()); - } + static TS3Event createEvent(Command command) { + switch (command.getName()) { + case "notifytextmessage": + return new TextMessageEvent(command.toMap()); + case "notifycliententerview": + return new ClientJoinEvent(command.toMap()); + case "notifyclientleftview": + return new ClientLeaveEvent(command.toMap()); + case "notifyserveredited": + return new ServerEditedEvent(command.toMap()); + case "notifychanneledited": + return new ChannelEditedEvent(command.toMap()); + case "notifychanneldescriptionchanged": + return new ChannelDescriptionEditedEvent(command.toMap()); + case "notifyclientmoved": + return new ClientMovedEvent(command.toMap()); + case "notifychannelcreated": + return new ChannelCreateEvent(command.toMap()); + case "notifychanneldeleted": + return new ChannelDeletedEvent(command.toMap()); + case "notifychannelmoved": + return new ChannelMovedEvent(command.toMap()); + case "notifychannelpasswordchanged": + return new ChannelPasswordChangedEvent(command.toMap()); + case "notifytokenused": + return new PrivilegeKeyUsedEvent(command.toMap()); + case "notifyservergrouplist": // CLIENT + return new ServerGroupListEvent(command.toMap()); + case "notifychannelgrouplist": // CLIENT + return new ChannelGroupListEvent(command.toMap()); + case "notifyclientchannelgroupchanged": // CLIENT + return new ClientChannelGroupChangedEvent(command.toMap()); + case "notifyclientneededpermissions": // CLIENT + return new ClientNeededPermissionsEvent(command.toMap()); + case "notifyclientupdated": // CLIENT + return new ClientUpdatedEvent(command.toMap()); + case "notifychannelsubscribed": // CLIENT + return new ChannelSubscribedEvent(command.toMap()); + case "notifychannelunsubscribed": // CLIENT + return new ChannelUnsubscribedEvent(command.toMap()); + case "notifyservergroupclientadded": // CLIENT + return new ServerGroupClientAddedEvent(command.toMap()); + case "notifyservergroupclientdeleted": // CLIENT + return new ServerGroupClientDeletedEvent(command.toMap()); + case "notifyclientpoke": // CLIENT + return new ClientPokeEvent(command.toMap()); + case "notifyclientchatcomposing": // CLIENT + return new ClientChatComposingEvent(command.toMap()); + case "notifyclientchatclosed": // CLIENT + return new ClientChatClosedEvent(command.toMap()); + case "notifypermissionlist": // CLIENT + return new PermissionListEvent(command.toMap()); + case "notifyclientpermhints": // CLIENT + return new ClientPermHintsEvent(command.toMap()); + case "notifychannelpermhints": // CLIENT + return new ChannelPermHintsEvent(command.toMap()); + default: + throw new IllegalArgumentException("unknown event: " + command.getName()); } + } } diff --git a/src/main/java/com/github/manevolent/ts3j/event/TS3Listener.java b/src/main/java/com/github/manevolent/ts3j/event/TS3Listener.java index 4aee012..e2024fd 100644 --- a/src/main/java/com/github/manevolent/ts3j/event/TS3Listener.java +++ b/src/main/java/com/github/manevolent/ts3j/event/TS3Listener.java @@ -55,4 +55,6 @@ public interface TS3Listener { default void onPermissionList(PermissionListEvent e) {} default void onConnected(ConnectedEvent e) {} default void onClientChatClosed(ClientChatClosedEvent e) {} + default void onClientPermHints(ClientPermHintsEvent e) {} + default void onChannelPermHints(ChannelPermHintsEvent e) {} } diff --git a/src/main/java/com/github/manevolent/ts3j/protocol/socket/client/AbstractTeamspeakClientSocket.java b/src/main/java/com/github/manevolent/ts3j/protocol/socket/client/AbstractTeamspeakClientSocket.java index aa64383..c2c111f 100644 --- a/src/main/java/com/github/manevolent/ts3j/protocol/socket/client/AbstractTeamspeakClientSocket.java +++ b/src/main/java/com/github/manevolent/ts3j/protocol/socket/client/AbstractTeamspeakClientSocket.java @@ -594,7 +594,6 @@ public abstract class AbstractTeamspeakClientSocket packet.readBody(packetBuffer); } - PacketKind kind = networkPacket.getHeader().getType().getKind(); if (kind != null) packetStatistics @@ -615,8 +614,7 @@ public abstract class AbstractTeamspeakClientSocket while (isReading()) { // De-spool spooled-up packets if (handlerBacklog.size() > 0) { - Packet packet = handlerBacklog.remove(0); - return packet; + return handlerBacklog.remove(0); } try { @@ -780,7 +778,8 @@ public abstract class AbstractTeamspeakClientSocket Packet reassembled; while ((reassembled = reassembly.next()) != null) { Ts3Debugging.debug("[PROTOCOL] REASSEMBLE " + reassembled.getHeader().getType().name() + - " id=" + reassembled.getHeader().getPacketId() + " len=" + reassembled.getSize()); + " id=" + reassembled.getHeader().getPacketId() + " len=" + reassembled.getSize() + + " bodyType=" + reassembled.getBody().getClass().getSimpleName()); handlerBacklog.add(reassembled); } } else { @@ -934,6 +933,7 @@ public abstract class AbstractTeamspeakClientSocket } } } catch (Throwable e) { + Ts3Debugging.debug("Problem reading packet", e); getExceptionHandler().accept(e); } } diff --git a/src/main/java/com/github/manevolent/ts3j/protocol/socket/client/LocalTeamspeakClientSocket.java b/src/main/java/com/github/manevolent/ts3j/protocol/socket/client/LocalTeamspeakClientSocket.java index 5432e66..cfd337d 100644 --- a/src/main/java/com/github/manevolent/ts3j/protocol/socket/client/LocalTeamspeakClientSocket.java +++ b/src/main/java/com/github/manevolent/ts3j/protocol/socket/client/LocalTeamspeakClientSocket.java @@ -25,9 +25,7 @@ import com.github.manevolent.ts3j.protocol.packet.handler.client.LocalClientHand import com.github.manevolent.ts3j.protocol.packet.handler.client.LocalClientHandlerRetrievingData; import com.github.manevolent.ts3j.protocol.packet.statistics.PacketStatistics; import com.github.manevolent.ts3j.protocol.packet.transformation.InitPacketTransformation; -import com.github.manevolent.ts3j.util.HighPrecisionTimer; -import com.github.manevolent.ts3j.util.Ts3Debugging; -import com.github.manevolent.ts3j.util.Pair; +import com.github.manevolent.ts3j.util.*; import java.io.EOFException; import java.io.IOException; @@ -448,6 +446,8 @@ public class LocalTeamspeakClientSocket if (awaitingCommandProcessor != null) awaitingCommandProcessor.process(client, singleCommand); + else + Ts3Debugging.info("Dropping command, no awaiting processor: " + singleCommand.toString()); } } @@ -1098,7 +1098,7 @@ public class LocalTeamspeakClientSocket Command command = new SingleCommand("clientmove", ProtocolRole.CLIENT); command.add(new CommandSingleParameter("cid", Integer.toString(channelId))); - if (password != null) command.add(new CommandSingleParameter("cpw", Integer.toString(channelId))); + if (password != null) command.add(new CommandSingleParameter("cpw", Ts3Crypt.hashPassword(password))); command.add(new CommandSingleParameter("clid", Integer.toString(clientId))); executeCommand(command).complete(); diff --git a/src/main/java/com/github/manevolent/ts3j/util/Ts3Crypt.java b/src/main/java/com/github/manevolent/ts3j/util/Ts3Crypt.java index f4e0f9a..7929424 100644 --- a/src/main/java/com/github/manevolent/ts3j/util/Ts3Crypt.java +++ b/src/main/java/com/github/manevolent/ts3j/util/Ts3Crypt.java @@ -23,8 +23,9 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.nio.ByteBuffer; +import java.nio.charset.*; import java.security.*; -import java.util.List; +import java.util.*; public final class Ts3Crypt { static { @@ -312,6 +313,10 @@ public final class Ts3Crypt { return new LocalIdentity(publicKey, privateKey); } + public static String hashPassword(String password) { + return Base64.getEncoder().encodeToString(hash128(password.getBytes(StandardCharsets.UTF_8))); + } + public static final class SecureChannelParameters { private final byte[] fakeSignature; private final byte[] ivStruct; diff --git a/src/test/java/com/github/manevolent/ts3j/ServerConnectionTest.java b/src/test/java/com/github/manevolent/ts3j/ServerConnectionTest.java index e2693d7..86f6d09 100644 --- a/src/test/java/com/github/manevolent/ts3j/ServerConnectionTest.java +++ b/src/test/java/com/github/manevolent/ts3j/ServerConnectionTest.java @@ -1,11 +1,14 @@ package com.github.manevolent.ts3j; +import com.github.manevolent.ts3j.command.*; +import com.github.manevolent.ts3j.event.*; import com.github.manevolent.ts3j.identity.LocalIdentity; import com.github.manevolent.ts3j.protocol.client.ClientConnectionState; import com.github.manevolent.ts3j.protocol.socket.client.LocalTeamspeakClientSocket; import com.github.manevolent.ts3j.util.Ts3Debugging; -import java.io.File; +import java.io.*; +import java.util.concurrent.*; import static org.junit.Assert.assertEquals; @@ -25,10 +28,11 @@ public class ServerConnectionTest { "teamlixo.net", 10000L ); - client.getChannels().get().forEach(x -> System.err.println(x.getTopic())); assertEquals(client.getState(), ClientConnectionState.CONNECTED); + Thread.sleep(1000); + client.setDescription("Heyo"); client.subscribeAll();