From 3619791233f436c6f4dbf284c47070e692169cb5 Mon Sep 17 00:00:00 2001 From: lieght Date: Sat, 13 Sep 2025 13:51:55 +0200 Subject: [PATCH] Refactored servercommands, added tcp client, added command queue. --- src/main/java/org/toop/eventbus/Events.java | 5 +- src/main/java/org/toop/server/Server.java | 138 ++++++++---------- .../java/org/toop/server/ServerCommand.java | 66 +++++++++ .../server/backend/{ => local}/Local.java | 3 +- .../server/backend/{ => remote}/Remote.java | 3 +- .../toop/server/backend/remote/TcpClient.java | 56 +++++++ src/test/java/ServerTest.java | 3 +- 7 files changed, 190 insertions(+), 84 deletions(-) create mode 100644 src/main/java/org/toop/server/ServerCommand.java rename src/main/java/org/toop/server/backend/{ => local}/Local.java (81%) rename src/main/java/org/toop/server/backend/{ => remote}/Remote.java (81%) create mode 100644 src/main/java/org/toop/server/backend/remote/TcpClient.java diff --git a/src/main/java/org/toop/eventbus/Events.java b/src/main/java/org/toop/eventbus/Events.java index 8d20e93..d7d52c6 100644 --- a/src/main/java/org/toop/eventbus/Events.java +++ b/src/main/java/org/toop/eventbus/Events.java @@ -1,6 +1,7 @@ package org.toop.eventbus; import org.toop.server.Server; +import org.toop.server.ServerCommand; /** * Events that are used in the GlobalEventBus class. @@ -12,12 +13,12 @@ public class Events implements IEvents { /** * Triggers sending a command to a server. */ - public record command(Server.Command command, String... args) {} + public record command(String command, String... args) {} /** * Triggers when a command is sent to a server. */ - public record OnCommand(Server.Command command, String[] args, Server.Message result) {} + public record OnCommand(org.toop.server.ServerCommand command, String[] args, String result) {} /** * Triggers on changing the server backend. diff --git a/src/main/java/org/toop/server/Server.java b/src/main/java/org/toop/server/Server.java index 73d2a5b..51fe9c6 100644 --- a/src/main/java/org/toop/server/Server.java +++ b/src/main/java/org/toop/server/Server.java @@ -3,11 +3,17 @@ package org.toop.server; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.toop.Main; -import org.toop.eventbus.EventRegistry; import org.toop.eventbus.Events; import org.toop.eventbus.GlobalEventBus; import org.toop.server.backend.*; -import java.util.EnumSet; +import org.toop.server.backend.local.Local; +import org.toop.server.backend.remote.Remote; +import org.toop.server.backend.remote.TcpClient; + +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; public class Server extends Thread { @@ -18,35 +24,6 @@ public class Server extends Thread { REMOTE, } - public enum Command { - /** - * Login, "username" - */ - LOGIN, - /** - * Logout, "username" - */ - LOGOUT, - EXIT, - QUIT, - DISCONNECT, - BYE, - GET, - SUBSCRIBE, - MOVE, - CHALLENGE, - FORFEIT, - MESSAGE, - HELP, - } - - private static final EnumSet VALID_COMMANDS = EnumSet.of( - Command.LOGIN, Command.LOGOUT, Command.EXIT, Command.QUIT, - Command.DISCONNECT, Command.BYE, Command.GET, Command.SUBSCRIBE, - Command.MOVE, Command.CHALLENGE, Command.FORFEIT, - Command.MESSAGE, Command.HELP - ); - public enum Message { OK, ERR, @@ -56,12 +33,14 @@ public class Server extends Thread { String ip; String port; IBackend backend; + List commandQueue; public Server(ServerBackend set_backend, String set_ip, String set_port) { ip = set_ip; port = set_port; setBackend(set_backend); this.initEvents(); + this.commandQueue = new LinkedList<>(); } public IBackend getBackend() { @@ -97,61 +76,45 @@ public class Server extends Thread { GlobalEventBus.post(new Events.ServerEvents.OnChangingServerPort(port)); } - private Message sendCommandString(String sentence) { - return Message.OK; - } - - private boolean isCommandValid(Command command) { - return VALID_COMMANDS.contains(command); - } - - /** - * Sends a command to the server. - * - * @param command the command to execute - * @return a Message indicating success or error - */ - public Message sendCommand(Command command) { - if (!isCommandValid(command)) { - throw new IllegalArgumentException("Invalid command: " + command); - } - Message result = sendCommandString(command.toString()); - - GlobalEventBus.post(new Events.ServerEvents.OnCommand(command, new String[0], result)); - - return sendCommandString(command.toString()); - } - - /** - * Sends a command to the server. - * - * @param command the command to execute - * @param args command arguments. - * @return a Message indicating success or error - */ - public Message sendCommand(Command command, String... args) { - if (!isCommandValid(command)) { - throw new IllegalArgumentException("Invalid command: " + command); + private void sendCommandByString(String command, String... args) { + if (!ServerCommand.isValid(command)) { + return; } for (int i = 0; i < args.length; i++) { args[i] = args[i].trim(); if (args[i].isEmpty()) { - throw new IllegalArgumentException("Empty argument"); + throw new IllegalArgumentException("Empty argument"); // TODO: Error handling, just crashes atm. } } String[] fullCommand = new String[args.length + 1]; - fullCommand[0] = command.toString(); + fullCommand[0] = command; System.arraycopy(args, 0, fullCommand, 1, args.length); - Message result = sendCommandString(String.join(" ", fullCommand)); + this.commandQueue.add(Arrays.toString(fullCommand)); // TODO Dunno if correct - GlobalEventBus.post(new Events.ServerEvents.OnCommand(command, args, result)); + logger.info("Command {} added to the queue", Arrays.toString(fullCommand)); - return result; } +// /** +// * Sends a command to the server. +// * +// * @param command the command to execute +// * @return a Message indicating success or error +// */ +// public void sendCommand(ServerCommand command) { +// +// Message result = Message.OK; +// +// this.commandQueue.add(command.toString()); +// +// GlobalEventBus.post(new Events.ServerEvents.OnCommand(command, new String[0], result)); +// +// return result; +// } + @Override public String toString() { return String.format( @@ -161,18 +124,35 @@ public class Server extends Thread { } private void initEvents() { - GlobalEventBus.subscribeAndRegister(Events.ServerEvents.command.class, e -> this.sendCommand(e.command(), e.args())); - GlobalEventBus.subscribeAndRegister(Events.ServerEvents.changeServerIp.class, e -> this.setIp(e.ip())); - GlobalEventBus.subscribeAndRegister(Events.ServerEvents.changeServerPort.class, e -> this.setPort(e.port())); + GlobalEventBus.subscribeAndRegister(Events.ServerEvents.command.class, event + -> this.sendCommandByString(event.command(), event.args())); + GlobalEventBus.subscribeAndRegister(Events.ServerEvents.changeServerIp.class, event + -> this.setIp(event.ip())); + GlobalEventBus.subscribeAndRegister(Events.ServerEvents.changeServerPort.class, event + -> this.setPort(event.port())); } public void run() { + try { + TcpClient client = new TcpClient(this.getIp(), Integer.parseInt(this.getPort())); // TODO This is unsafe + theRemoteServerTimeline(client); + } catch (UnknownHostException | InterruptedException e) { // TODO Better error handling. + throw new RuntimeException(e); + } + } + + public void theRemoteServerTimeline(TcpClient client) throws InterruptedException { while (true) { - logger.info("Ik ben Bas, hallo"); - try { - sleep(1000); - } catch (InterruptedException e) { - throw new RuntimeException(e); + sleep(500); // 1s delay to not overload server. + if (!commandQueue.isEmpty()) { + String command = commandQueue.removeFirst(); + logger.info("Sending command: {}", command); + try { + client.sendMessage(command); // TODO: Will block. + client.readLine(); // TODO Does this need to wait? + } catch (Exception e) { + // TODO: Error handling. + } } } } diff --git a/src/main/java/org/toop/server/ServerCommand.java b/src/main/java/org/toop/server/ServerCommand.java new file mode 100644 index 0000000..d77da07 --- /dev/null +++ b/src/main/java/org/toop/server/ServerCommand.java @@ -0,0 +1,66 @@ +package org.toop.server; + +import java.util.EnumSet; + +public enum ServerCommand { + /** + * Login, "username" + */ + LOGIN, + /** + * Logout, "username" + */ + LOGOUT, + EXIT, + QUIT, + DISCONNECT, + BYE, + GET, + SUBSCRIBE, + MOVE, + CHALLENGE, + FORFEIT, + MESSAGE, + HELP; + + private static final EnumSet VALID_COMMANDS = EnumSet.of( + ServerCommand.LOGIN, ServerCommand.LOGOUT, ServerCommand.EXIT, + ServerCommand.QUIT, ServerCommand.DISCONNECT, ServerCommand.BYE, + ServerCommand.GET, ServerCommand.SUBSCRIBE, ServerCommand.MOVE, + ServerCommand.CHALLENGE, ServerCommand.FORFEIT, + ServerCommand.MESSAGE, ServerCommand.HELP + ); + + public static EnumSet getValidCommands() { + return VALID_COMMANDS; + } + + // TODO: Garbage code. + + /** + * @param command Checks if string is a valid command. + * @return returns a boolean if string is a valid command. + */ + public static boolean isValid(String command) { + try { + ServerCommand.valueOf(command.toUpperCase()); + return true; + } catch (IllegalArgumentException err) { + return false; + } + } + + // TODO: Return something better + /** + * @param command Converts a string into a ServerCommand. + * @return returns a ServerCommand enum. + */ + public static ServerCommand getCommand(String command) { + if (isValid(command)) { + ServerCommand.valueOf(command.toUpperCase()); + return ServerCommand.valueOf(command.toUpperCase()); + } + return null; + } + +} diff --git a/src/main/java/org/toop/server/backend/Local.java b/src/main/java/org/toop/server/backend/local/Local.java similarity index 81% rename from src/main/java/org/toop/server/backend/Local.java rename to src/main/java/org/toop/server/backend/local/Local.java index 65c9760..5646885 100644 --- a/src/main/java/org/toop/server/backend/Local.java +++ b/src/main/java/org/toop/server/backend/local/Local.java @@ -1,6 +1,7 @@ -package org.toop.server.backend; +package org.toop.server.backend.local; import org.toop.server.Server; +import org.toop.server.backend.IBackend; public class Local implements IBackend { @Override diff --git a/src/main/java/org/toop/server/backend/Remote.java b/src/main/java/org/toop/server/backend/remote/Remote.java similarity index 81% rename from src/main/java/org/toop/server/backend/Remote.java rename to src/main/java/org/toop/server/backend/remote/Remote.java index fa1d669..9bbe56a 100644 --- a/src/main/java/org/toop/server/backend/Remote.java +++ b/src/main/java/org/toop/server/backend/remote/Remote.java @@ -1,6 +1,7 @@ -package org.toop.server.backend; +package org.toop.server.backend.remote; import org.toop.server.Server; +import org.toop.server.backend.IBackend; public class Remote implements IBackend { @Override diff --git a/src/main/java/org/toop/server/backend/remote/TcpClient.java b/src/main/java/org/toop/server/backend/remote/TcpClient.java new file mode 100644 index 0000000..529475f --- /dev/null +++ b/src/main/java/org/toop/server/backend/remote/TcpClient.java @@ -0,0 +1,56 @@ +package org.toop.server.backend.remote; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +public class TcpClient { + + InetAddress serverAddress; + int serverPort; + Socket socket; + BufferedReader in; + PrintWriter out; + + public TcpClient(byte[] serverIp, int serverPort) throws IOException { + this.serverAddress = InetAddress.getByAddress(serverIp); + this.serverPort = serverPort; + this.socket = createSocket(); + this.in = createIn(); + this.out = createOut(); + } + + public TcpClient(String serverIp, int serverPort) throws UnknownHostException { + this.serverAddress = InetAddress.getByName(serverIp); + this.serverPort = serverPort; + } + + private Socket createSocket() throws IOException { + return new Socket(serverAddress, serverPort); + } + + private BufferedReader createIn() throws IOException { + return new BufferedReader(new InputStreamReader(this.socket.getInputStream())); + } + + private PrintWriter createOut() throws IOException { + return new PrintWriter(this.socket.getOutputStream(), true); + } + + public void sendMessage(String message) throws IOException { + this.out.write(message); + } + + public String readLine() throws IOException { + return this.in.readLine(); + } + + public void close() throws IOException { + this.socket.close(); + } + +} \ No newline at end of file diff --git a/src/test/java/ServerTest.java b/src/test/java/ServerTest.java index 60b0f28..e799314 100644 --- a/src/test/java/ServerTest.java +++ b/src/test/java/ServerTest.java @@ -1,7 +1,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.toop.server.Server; -import org.toop.server.backend.*; +import org.toop.server.backend.local.Local; +import org.toop.server.backend.remote.Remote; import static org.junit.jupiter.api.Assertions.*;