Refactored servercommands, added tcp client, added command queue.

This commit is contained in:
lieght
2025-09-13 13:51:55 +02:00
parent c6bdbae46c
commit 3619791233
7 changed files with 190 additions and 84 deletions

View File

@@ -1,6 +1,7 @@
package org.toop.eventbus; package org.toop.eventbus;
import org.toop.server.Server; import org.toop.server.Server;
import org.toop.server.ServerCommand;
/** /**
* Events that are used in the GlobalEventBus class. * Events that are used in the GlobalEventBus class.
@@ -12,12 +13,12 @@ public class Events implements IEvents {
/** /**
* Triggers sending a command to a server. * 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. * 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. * Triggers on changing the server backend.

View File

@@ -3,11 +3,17 @@ package org.toop.server;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.Main; import org.toop.Main;
import org.toop.eventbus.EventRegistry;
import org.toop.eventbus.Events; import org.toop.eventbus.Events;
import org.toop.eventbus.GlobalEventBus; import org.toop.eventbus.GlobalEventBus;
import org.toop.server.backend.*; 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 { public class Server extends Thread {
@@ -18,35 +24,6 @@ public class Server extends Thread {
REMOTE, 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<Command> 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 { public enum Message {
OK, OK,
ERR, ERR,
@@ -56,12 +33,14 @@ public class Server extends Thread {
String ip; String ip;
String port; String port;
IBackend backend; IBackend backend;
List<String> commandQueue;
public Server(ServerBackend set_backend, String set_ip, String set_port) { public Server(ServerBackend set_backend, String set_ip, String set_port) {
ip = set_ip; ip = set_ip;
port = set_port; port = set_port;
setBackend(set_backend); setBackend(set_backend);
this.initEvents(); this.initEvents();
this.commandQueue = new LinkedList<>();
} }
public IBackend getBackend() { public IBackend getBackend() {
@@ -97,61 +76,45 @@ public class Server extends Thread {
GlobalEventBus.post(new Events.ServerEvents.OnChangingServerPort(port)); GlobalEventBus.post(new Events.ServerEvents.OnChangingServerPort(port));
} }
private Message sendCommandString(String sentence) { private void sendCommandByString(String command, String... args) {
return Message.OK; if (!ServerCommand.isValid(command)) {
} return;
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);
} }
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
args[i] = args[i].trim(); args[i] = args[i].trim();
if (args[i].isEmpty()) { 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]; String[] fullCommand = new String[args.length + 1];
fullCommand[0] = command.toString(); fullCommand[0] = command;
System.arraycopy(args, 0, fullCommand, 1, args.length); 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 @Override
public String toString() { public String toString() {
return String.format( return String.format(
@@ -161,20 +124,37 @@ public class Server extends Thread {
} }
private void initEvents() { private void initEvents() {
GlobalEventBus.subscribeAndRegister(Events.ServerEvents.command.class, e -> this.sendCommand(e.command(), e.args())); GlobalEventBus.subscribeAndRegister(Events.ServerEvents.command.class, event
GlobalEventBus.subscribeAndRegister(Events.ServerEvents.changeServerIp.class, e -> this.setIp(e.ip())); -> this.sendCommandByString(event.command(), event.args()));
GlobalEventBus.subscribeAndRegister(Events.ServerEvents.changeServerPort.class, e -> this.setPort(e.port())); 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() { public void run() {
while (true) {
logger.info("Ik ben Bas, hallo");
try { try {
sleep(1000); TcpClient client = new TcpClient(this.getIp(), Integer.parseInt(this.getPort())); // TODO This is unsafe
} catch (InterruptedException e) { theRemoteServerTimeline(client);
} catch (UnknownHostException | InterruptedException e) { // TODO Better error handling.
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public void theRemoteServerTimeline(TcpClient client) throws InterruptedException {
while (true) {
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.
}
}
}
} }
public static void start(String backend, String ip, String port) { public static void start(String backend, String ip, String port) {

View File

@@ -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<ServerCommand> 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<ServerCommand> 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;
}
}

View File

@@ -1,6 +1,7 @@
package org.toop.server.backend; package org.toop.server.backend.local;
import org.toop.server.Server; import org.toop.server.Server;
import org.toop.server.backend.IBackend;
public class Local implements IBackend { public class Local implements IBackend {
@Override @Override

View File

@@ -1,6 +1,7 @@
package org.toop.server.backend; package org.toop.server.backend.remote;
import org.toop.server.Server; import org.toop.server.Server;
import org.toop.server.backend.IBackend;
public class Remote implements IBackend { public class Remote implements IBackend {
@Override @Override

View File

@@ -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();
}
}

View File

@@ -1,7 +1,8 @@
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.toop.server.Server; 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.*; import static org.junit.jupiter.api.Assertions.*;