Command processing started

This commit is contained in:
Manevolent
2018-07-27 16:30:49 -04:00
parent e4bb886d64
commit ab4cb12010
14 changed files with 191 additions and 36 deletions
@@ -0,0 +1,11 @@
package com.github.manevolent.ts3j.command;
import com.github.manevolent.ts3j.protocol.socket.client.AbstractTeamspeakClientSocket;
public final class CommandHandler implements CommandProcessor {
@Override
public void process(AbstractTeamspeakClientSocket socket, ComplexCommand complexCommand)
throws CommandProcessException {
}
}
@@ -0,0 +1,11 @@
package com.github.manevolent.ts3j.command;
public class CommandProcessException extends Exception {
public CommandProcessException(Exception cause) {
super(cause);
}
public CommandProcessException(String message) {
super(message);
}
}
@@ -0,0 +1,8 @@
package com.github.manevolent.ts3j.command;
import com.github.manevolent.ts3j.protocol.socket.client.AbstractTeamspeakClientSocket;
public interface CommandProcessor {
void process(AbstractTeamspeakClientSocket socket, ComplexCommand complexCommand)
throws CommandProcessException;
}
@@ -0,0 +1,90 @@
package com.github.manevolent.ts3j.command;
import com.github.manevolent.ts3j.command.part.CommandOption;
import com.github.manevolent.ts3j.command.part.CommandParameter;
import com.github.manevolent.ts3j.command.part.CommandSingleParameter;
import com.github.manevolent.ts3j.protocol.ProtocolRole;
import com.github.manevolent.ts3j.util.Ts3String;
import java.util.*;
public class ComplexCommand implements Command {
private final String name;
private final ProtocolRole role;
private final List<CommandParameter> params;
public ComplexCommand(String name, ProtocolRole role, CommandParameter... params) {
this(name, role, Arrays.asList(params));
}
public ComplexCommand(String name, ProtocolRole role, List<CommandParameter> params) {
this.name = name;
this.role = role;
this.params = new LinkedList<>();
for (CommandParameter parameter : params) add(parameter);
}
@Override
public String getName() {
return name;
}
@Override
public ProtocolRole getRole() {
return role;
}
@Override
public Iterable<CommandParameter> getParameters() {
return Collections.unmodifiableCollection(params);
}
public boolean has(String key) {
return params.stream().anyMatch(x -> x.getName().equalsIgnoreCase(key));
}
public void add(CommandParameter parameter) {
if (parameter.getName().trim().length() <= 0)
throw new IllegalArgumentException("invalid key (empty)");
this.params.add(parameter);
}
public SimpleCommand simplify() {
return new SimpleCommand(
name,
role,
params
);
}
public static ComplexCommand parse(ProtocolRole role, String commandText) {
String[] commandParts = commandText.split(" ");
String commandLabel = commandParts[0].toLowerCase();
List<CommandParameter> parameterList = new LinkedList<>();
for (int i = 1; i < commandParts.length; i ++) {
String commandParamText = commandParts[i].trim();
if (commandParamText.length() <= 0) continue;
if (commandParamText.startsWith("-")) { // Option
parameterList.add(new CommandOption(commandParamText.substring(1)));
} else {
String[] commandParamParts = commandParamText.split("=", 2);
parameterList.add(new CommandSingleParameter(
commandParamParts[0].toLowerCase(),
commandParamParts.length > 1 ?
Ts3String.unescape(commandParamParts[1]) :
null
)
);
}
}
return new ComplexCommand(commandLabel, role, parameterList);
}
}
@@ -64,31 +64,6 @@ public class SimpleCommand implements Command {
} }
public static SimpleCommand parse(ProtocolRole role, String commandText) { public static SimpleCommand parse(ProtocolRole role, String commandText) {
String[] commandParts = commandText.split(" "); return ComplexCommand.parse(role, commandText).simplify();
String commandLabel = commandParts[0].toLowerCase();
List<CommandParameter> parameterList = new LinkedList<>();
for (int i = 1; i < commandParts.length; i ++) {
String commandParamText = commandParts[i].trim();
if (commandParamText.length() <= 0) continue;
if (commandParamText.startsWith("-")) { // Option
parameterList.add(new CommandOption(commandParamText.substring(1)));
} else {
String[] commandParamParts = commandParamText.split("=", 2);
parameterList.add(new CommandSingleParameter(
commandParamParts[0].toLowerCase(),
commandParamParts.length > 1 ?
Ts3String.unescape(commandParamParts[1]) :
null
)
);
}
}
return new SimpleCommand(commandLabel, role, parameterList);
} }
} }
@@ -3,13 +3,12 @@ package com.github.manevolent.ts3j.protocol.client;
import com.github.manevolent.ts3j.protocol.packet.handler.PacketHandler; import com.github.manevolent.ts3j.protocol.packet.handler.PacketHandler;
import com.github.manevolent.ts3j.protocol.packet.handler.local.*; import com.github.manevolent.ts3j.protocol.packet.handler.local.*;
import com.github.manevolent.ts3j.protocol.socket.client.AbstractTeamspeakClientSocket;
import com.github.manevolent.ts3j.protocol.socket.client.TeamspeakClientSocket; import com.github.manevolent.ts3j.protocol.socket.client.TeamspeakClientSocket;
import org.apache.commons.lang.reflect.ConstructorUtils; import org.apache.commons.lang.reflect.ConstructorUtils;
public enum ClientConnectionState { public enum ClientConnectionState {
CONNECTING(LocalClientHandlerConnecting.class), CONNECTING(LocalClientHandlerConnecting.class),
NEGOTIATING(LocalClientHandlerNegotiating.class), RETRIEVING_DATA(LocalClientHandlerRetrievingData.class),
CONNECTED(LocalClientHandlerConnected.class), CONNECTED(LocalClientHandlerConnected.class),
DISCONNECTED(LocalClientHandlerDisconnected.class); DISCONNECTED(LocalClientHandlerDisconnected.class);
@@ -1,6 +1,7 @@
package com.github.manevolent.ts3j.protocol.packet; package com.github.manevolent.ts3j.protocol.packet;
import com.github.manevolent.ts3j.command.Command; import com.github.manevolent.ts3j.command.Command;
import com.github.manevolent.ts3j.command.ComplexCommand;
import com.github.manevolent.ts3j.command.SimpleCommand; import com.github.manevolent.ts3j.command.SimpleCommand;
import com.github.manevolent.ts3j.protocol.ProtocolRole; import com.github.manevolent.ts3j.protocol.ProtocolRole;
@@ -28,8 +29,8 @@ public class PacketBody2Command extends PacketBody {
return text; return text;
} }
public SimpleCommand parse() { public ComplexCommand parse() {
return SimpleCommand.parse(getRole(), getText()); return ComplexCommand.parse(getRole(), getText());
} }
public void setText(String text) { public void setText(String text) {
@@ -1,5 +1,6 @@
package com.github.manevolent.ts3j.protocol.packet.handler; package com.github.manevolent.ts3j.protocol.packet.handler;
import com.github.manevolent.ts3j.command.Command;
import com.github.manevolent.ts3j.protocol.Packet; import com.github.manevolent.ts3j.protocol.Packet;
import com.github.manevolent.ts3j.protocol.socket.client.TeamspeakClientSocket; import com.github.manevolent.ts3j.protocol.socket.client.TeamspeakClientSocket;
@@ -25,6 +26,10 @@ public abstract class PacketHandler {
} }
public void handleCommand(Command command) {
}
public TeamspeakClientSocket getClient() { public TeamspeakClientSocket getClient() {
return clientSocket; return clientSocket;
} }
@@ -1,10 +1,15 @@
package com.github.manevolent.ts3j.protocol.packet.handler.local; package com.github.manevolent.ts3j.protocol.packet.handler.local;
import com.github.manevolent.ts3j.protocol.Packet;
import com.github.manevolent.ts3j.protocol.client.ClientConnectionState; import com.github.manevolent.ts3j.protocol.client.ClientConnectionState;
import com.github.manevolent.ts3j.protocol.packet.PacketBody2Command;
import com.github.manevolent.ts3j.protocol.packet.handler.PacketHandler; import com.github.manevolent.ts3j.protocol.packet.handler.PacketHandler;
import com.github.manevolent.ts3j.protocol.socket.client.LocalTeamspeakClientSocket; import com.github.manevolent.ts3j.protocol.socket.client.LocalTeamspeakClientSocket;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public abstract class LocalClientHandler extends PacketHandler { public abstract class LocalClientHandler extends PacketHandler {
private final LocalTeamspeakClientSocket client; private final LocalTeamspeakClientSocket client;
@@ -1,9 +1,15 @@
package com.github.manevolent.ts3j.protocol.packet.handler.local; package com.github.manevolent.ts3j.protocol.packet.handler.local;
import com.github.manevolent.ts3j.command.ComplexCommand;
import com.github.manevolent.ts3j.protocol.socket.client.LocalTeamspeakClientSocket; import com.github.manevolent.ts3j.protocol.socket.client.LocalTeamspeakClientSocket;
public class LocalClientHandlerConnected extends LocalClientHandler { public class LocalClientHandlerConnected extends LocalClientHandlerFull {
public LocalClientHandlerConnected(LocalTeamspeakClientSocket client) { public LocalClientHandlerConnected(LocalTeamspeakClientSocket client) {
super(client); super(client);
} }
@Override
protected void handleCommand(ComplexCommand command) {
}
} }
@@ -141,7 +141,7 @@ public class LocalClientHandlerConnecting extends LocalClientHandler {
} }
} else if (packet.getBody() instanceof PacketBody2Command) { } else if (packet.getBody() instanceof PacketBody2Command) {
SimpleCommand command = ((PacketBody2Command) packet.getBody()).parse(); SimpleCommand command = ((PacketBody2Command) packet.getBody()).parse().simplify();
if (command.getName().equalsIgnoreCase("initivexpand2")) { if (command.getName().equalsIgnoreCase("initivexpand2")) {
// 3.2.2 initivexpand2 (Client <- Server) // 3.2.2 initivexpand2 (Client <- Server)
@@ -228,7 +228,7 @@ public class LocalClientHandlerConnecting extends LocalClientHandler {
) )
); );
getClient().setState(ClientConnectionState.CONNECTED); getClient().setState(ClientConnectionState.RETRIEVING_DATA);
} else if (command.getName().equals("error")) { } else if (command.getName().equals("error")) {
getClient().setState(ClientConnectionState.DISCONNECTED); getClient().setState(ClientConnectionState.DISCONNECTED);
@@ -0,0 +1,32 @@
package com.github.manevolent.ts3j.protocol.packet.handler.local;
import com.github.manevolent.ts3j.command.CommandProcessException;
import com.github.manevolent.ts3j.command.CommandProcessor;
import com.github.manevolent.ts3j.command.ComplexCommand;
import com.github.manevolent.ts3j.protocol.Packet;
import com.github.manevolent.ts3j.protocol.packet.PacketBody2Command;
import com.github.manevolent.ts3j.protocol.socket.client.LocalTeamspeakClientSocket;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public abstract class LocalClientHandlerFull extends LocalClientHandler {
protected LocalClientHandlerFull(LocalTeamspeakClientSocket client) {
super(client);
}
protected void handleCommand(ComplexCommand command) throws CommandProcessException {
CommandProcessor processor = getClient().getCommandProcessor();
if (processor != null) processor.process(getClient(), command);
}
@Override
public void handlePacket(Packet packet) throws IOException, TimeoutException {
if (packet.getBody() instanceof PacketBody2Command)
try {
handleCommand(ComplexCommand.parse(packet.getRole(), ((PacketBody2Command) packet.getBody()).getText()));
} catch (CommandProcessException e) {
throw new IOException(e);
}
}
}
@@ -1,17 +1,18 @@
package com.github.manevolent.ts3j.protocol.packet.handler.local; package com.github.manevolent.ts3j.protocol.packet.handler.local;
import com.github.manevolent.ts3j.command.ComplexCommand;
import com.github.manevolent.ts3j.protocol.socket.client.LocalTeamspeakClientSocket; import com.github.manevolent.ts3j.protocol.socket.client.LocalTeamspeakClientSocket;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
public class LocalClientHandlerNegotiating extends LocalClientHandler { public class LocalClientHandlerRetrievingData extends LocalClientHandlerFull {
public LocalClientHandlerNegotiating(LocalTeamspeakClientSocket client) { public LocalClientHandlerRetrievingData(LocalTeamspeakClientSocket client) {
super(client); super(client);
} }
@Override @Override
public void onAssigned() throws IOException, TimeoutException { protected void handleCommand(ComplexCommand command) {
} }
} }
@@ -1,6 +1,7 @@
package com.github.manevolent.ts3j.protocol.socket.client; package com.github.manevolent.ts3j.protocol.socket.client;
import com.github.manevolent.ts3j.command.Command; import com.github.manevolent.ts3j.command.Command;
import com.github.manevolent.ts3j.command.CommandProcessor;
import com.github.manevolent.ts3j.command.response.CommandResponse; import com.github.manevolent.ts3j.command.response.CommandResponse;
import com.github.manevolent.ts3j.identity.Identity; import com.github.manevolent.ts3j.identity.Identity;
import com.github.manevolent.ts3j.protocol.NetworkPacket; import com.github.manevolent.ts3j.protocol.NetworkPacket;
@@ -41,6 +42,8 @@ public abstract class AbstractTeamspeakClientSocket
private final Map<String, Object> clientOptions = new ConcurrentHashMap<>(); private final Map<String, Object> clientOptions = new ConcurrentHashMap<>();
private final Map<Integer, PacketResponse> sendQueue = new ConcurrentHashMap<>(); private final Map<Integer, PacketResponse> sendQueue = new ConcurrentHashMap<>();
private CommandProcessor commandProcessor;
private Identity identity = null; private Identity identity = null;
private ClientConnectionState connectionState = null; private ClientConnectionState connectionState = null;
private PacketTransformation transformation = new DefaultPacketTransformation(); private PacketTransformation transformation = new DefaultPacketTransformation();
@@ -551,6 +554,14 @@ public abstract class AbstractTeamspeakClientSocket
setOption("client.nickname", name); setOption("client.nickname", name);
} }
public CommandProcessor getCommandProcessor() {
return commandProcessor;
}
public void setCommandProcessor(CommandProcessor commandProcessor) {
this.commandProcessor = commandProcessor;
}
private class NetworkHandler implements Runnable { private class NetworkHandler implements Runnable {
@Override @Override
public void run() { public void run() {