diff --git a/pom.xml b/pom.xml index 72f9e1c..27b396f 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.openautonomousconnection Protocol - 1.0.0-BETA.6.1 + 1.0.0-BETA.7.0 Open Autonomous Connection https://open-autonomous-connection.org/ @@ -119,7 +119,7 @@ dev.unlegitdqrk unlegitlibrary - 1.7.0 + 1.7.8 org.projectlombok @@ -164,6 +164,9 @@ maven-javadoc-plugin 3.6.3 + false + false + none en_US UTF-8 UTF-8 diff --git a/src/main/java/org/openautonomousconnection/protocol/ProtocolBridge.java b/src/main/java/org/openautonomousconnection/protocol/ProtocolBridge.java index 0d0c081..0dd9abc 100644 --- a/src/main/java/org/openautonomousconnection/protocol/ProtocolBridge.java +++ b/src/main/java/org/openautonomousconnection/protocol/ProtocolBridge.java @@ -1,5 +1,6 @@ package org.openautonomousconnection.protocol; +import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientAuthMode; import dev.unlegitdqrk.unlegitlibrary.utils.Logger; import lombok.Getter; import lombok.Setter; @@ -77,13 +78,17 @@ public final class ProtocolBridge { * @param logFolder The folder to store the log files * @throws Exception if an error occurs while initializing the ProtocolBridge */ - @ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.CLIENT) public ProtocolBridge(ProtocolCustomServer protocolServer, ProtocolValues protocolValues, ProtocolVersion protocolVersion, File logFolder) throws Exception { // Assign the parameters to the class fields this.protocolServer = protocolServer; this.protocolValues = protocolValues; this.protocolVersion = protocolVersion; + if (protocolServer instanceof ProtocolINSServer) { + protocolServer.attachBridge(this, null, false, ClientAuthMode.NONE); + } else + protocolServer.attachBridge(this, protocolValues.keyPass, protocolValues.ssl, protocolValues.authMode); + // Initialize the logger and protocol version initializeLogger(logFolder); initializeProtocolVersion(); @@ -91,8 +96,6 @@ public final class ProtocolBridge { // Register the appropriate listeners and packets registerListeners(); registerPackets(); - - protocolServer.attachBridge(this); } /** @@ -111,6 +114,8 @@ public final class ProtocolBridge { this.protocolValues = protocolValues; this.protocolVersion = protocolVersion; + protocolClient.attachBridge(this); + // Initialize the logger and protocol version initializeLogger(logFolder); initializeProtocolVersion(); @@ -118,8 +123,6 @@ public final class ProtocolBridge { // Register the appropriate listeners and packets registerListeners(); registerPackets(); - - protocolClient.attachBridge(this); } /** @@ -127,30 +130,17 @@ public final class ProtocolBridge { */ private void registerPackets() { // 1.0.0-BETA packets - AuthPacket v100bAuthPath = new AuthPacket(); - INSQueryPacket v100BINSQueryPacket = new INSQueryPacket(); - INSResponsePacket v100BINSResponsePacket = new INSResponsePacket(this); - WebRequestPacket v100BWebRequestPacket = new WebRequestPacket(); - WebResponsePacket v100BResponsePacket = new WebResponsePacket(); - WebStreamChunkPacket v100BStreamChunkPacket = new WebStreamChunkPacket(); - WebStreamStartPacket v100BStreamStartPacket = new WebStreamStartPacket(); - WebStreamEndPacket v100BStreamEndPacket = new WebStreamEndPacket(); - - if (isPacketSupported(v100bAuthPath)) protocolValues.packetHandler.registerPacket(v100bAuthPath); - if (isPacketSupported(v100BINSQueryPacket)) protocolValues.packetHandler.registerPacket(v100BINSQueryPacket); - if (isPacketSupported(v100BINSResponsePacket)) - protocolValues.packetHandler.registerPacket(v100BINSResponsePacket); - if (isPacketSupported(v100BWebRequestPacket)) - protocolValues.packetHandler.registerPacket(v100BWebRequestPacket); - if (isPacketSupported(v100BResponsePacket)) protocolValues.packetHandler.registerPacket(v100BResponsePacket); - if (isPacketSupported(v100BStreamChunkPacket)) - protocolValues.packetHandler.registerPacket(v100BStreamChunkPacket); - if (isPacketSupported(v100BStreamStartPacket)) - protocolValues.packetHandler.registerPacket(v100BStreamStartPacket); - if (isPacketSupported(v100BStreamEndPacket)) - protocolValues.packetHandler.registerPacket(v100BStreamEndPacket); + if (isPacketSupported(new AuthPacket(this))) protocolValues.packetHandler.registerPacket(() -> new AuthPacket(this)); + if (isPacketSupported(new INSQueryPacket())) protocolValues.packetHandler.registerPacket(INSQueryPacket::new); + if (isPacketSupported(new INSResponsePacket(this))) protocolValues.packetHandler.registerPacket(() -> new INSResponsePacket(this)); + if (isPacketSupported(new WebRequestPacket())) protocolValues.packetHandler.registerPacket(WebRequestPacket::new); + if (isPacketSupported(new WebResponsePacket())) protocolValues.packetHandler.registerPacket(WebResponsePacket::new); + if (isPacketSupported(new WebStreamChunkPacket())) protocolValues.packetHandler.registerPacket(WebStreamChunkPacket::new); + if (isPacketSupported(new WebStreamStartPacket())) protocolValues.packetHandler.registerPacket(WebStreamStartPacket::new); + if (isPacketSupported(new WebStreamEndPacket())) protocolValues.packetHandler.registerPacket(WebStreamEndPacket::new); } + /** * Register the appropriate listeners based on the current side * @@ -159,17 +149,13 @@ public final class ProtocolBridge { private void registerListeners() throws Exception { // Client Listeners if (isRunningAsClient()) { - ClientListener clientListener = new ClientListener(); - clientListener.setClient(protocolClient); - protocolValues.eventManager.registerListener(clientListener.getClass()); + protocolValues.eventManager.registerListener(new ClientListener(protocolClient)); protocolValues.eventManager.unregisterListener(CustomServerListener.class); } // Server Listeners if (isRunningAsServer()) { - CustomServerListener serverListener = new CustomServerListener(); - serverListener.setServer(protocolServer); - protocolValues.eventManager.registerListener(serverListener.getClass()); + protocolValues.eventManager.registerListener(new CustomServerListener(protocolServer)); protocolValues.eventManager.unregisterListener(ClientListener.class); } } diff --git a/src/main/java/org/openautonomousconnection/protocol/ProtocolValues.java b/src/main/java/org/openautonomousconnection/protocol/ProtocolValues.java index 23b6ae9..7f60394 100644 --- a/src/main/java/org/openautonomousconnection/protocol/ProtocolValues.java +++ b/src/main/java/org/openautonomousconnection/protocol/ProtocolValues.java @@ -2,6 +2,7 @@ package org.openautonomousconnection.protocol; import dev.unlegitdqrk.unlegitlibrary.event.EventManager; import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; +import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientAuthMode; import dev.unlegitdqrk.unlegitlibrary.utils.DefaultMethodsOverrider; /** @@ -9,7 +10,7 @@ import dev.unlegitdqrk.unlegitlibrary.utils.DefaultMethodsOverrider; */ public final class ProtocolValues extends DefaultMethodsOverrider { /** - * The protocol version to use. + * The packet handler to use. */ public PacketHandler packetHandler; @@ -18,4 +19,9 @@ public final class ProtocolValues extends DefaultMethodsOverrider { */ public EventManager eventManager; + public String keyPass = null; + + public boolean ssl = true; + public ClientAuthMode authMode = ClientAuthMode.NONE; + } diff --git a/src/main/java/org/openautonomousconnection/protocol/listeners/ClientListener.java b/src/main/java/org/openautonomousconnection/protocol/listeners/ClientListener.java index 3c70f4b..4395d1d 100644 --- a/src/main/java/org/openautonomousconnection/protocol/listeners/ClientListener.java +++ b/src/main/java/org/openautonomousconnection/protocol/listeners/ClientListener.java @@ -2,9 +2,8 @@ package org.openautonomousconnection.protocol.listeners; import dev.unlegitdqrk.unlegitlibrary.event.EventListener; import dev.unlegitdqrk.unlegitlibrary.event.Listener; -import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.state.connect.ClientConnectedEvent; -import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.state.disconnect.ClientFullyDisconnectedEvent; -import dev.unlegitdqrk.unlegitlibrary.network.system.utils.Transport; +import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.state.ClientConnectedEvent; +import dev.unlegitdqrk.unlegitlibrary.network.system.utils.TransportProtocol; import lombok.Getter; import org.openautonomousconnection.protocol.annotations.ProtocolInfo; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.AuthPacket; @@ -23,15 +22,14 @@ public final class ClientListener extends EventListener { * The reference to the ProtocolClient object */ @Getter - private ProtocolClient client; + private final ProtocolClient client; /** * Sets the client variable * * @param client The Instance of the ProtocolClient */ - public void setClient(ProtocolClient client) { - if (this.client != null) return; + public ClientListener(ProtocolClient client) { this.client = client; } @@ -44,23 +42,11 @@ public final class ClientListener extends EventListener { @Listener public void onConnect(ClientConnectedEvent event) { try { - if (event.getTransport() != Transport.TCP) return; - event.getClient().sendPacket(new AuthPacket(client.getProtocolBridge()), Transport.TCP); - } catch (IOException | ClassNotFoundException exception) { + event.getClient().sendPacket(new AuthPacket(client.getProtocolBridge()), TransportProtocol.TCP); + } catch (Exception exception) { client.getProtocolBridge().getLogger().exception("Failed to send auth packet", exception); event.getClient().disconnect(); } } - /** - * Handles the event when a client disconnects. - * Notifies the protocol client of the disconnection. - * - * @param event The client disconnected event. - */ - @Listener - public void onDisconnect(ClientFullyDisconnectedEvent event) { - client.onDisconnect(event); - } - } diff --git a/src/main/java/org/openautonomousconnection/protocol/listeners/CustomServerListener.java b/src/main/java/org/openautonomousconnection/protocol/listeners/CustomServerListener.java index 90220ce..0b3bff8 100644 --- a/src/main/java/org/openautonomousconnection/protocol/listeners/CustomServerListener.java +++ b/src/main/java/org/openautonomousconnection/protocol/listeners/CustomServerListener.java @@ -2,50 +2,42 @@ package org.openautonomousconnection.protocol.listeners; import dev.unlegitdqrk.unlegitlibrary.event.EventListener; import dev.unlegitdqrk.unlegitlibrary.event.Listener; -import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectionHandler; -import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.packets.receive.S_PacketReceivedEvent; -import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.state.connect.ConnectionHandlerConnectedEvent; -import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.state.disconnect.ConnectionHandlerDisconnectedEvent; -import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.state.disconnect.ConnectionHandlerFullyDisconnectedEvent; -import dev.unlegitdqrk.unlegitlibrary.network.system.utils.Transport; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.client.S_ClientConnectedEvent; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.client.S_ClientDisconnectedEvent; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.packets.S_PacketReadEvent; +import dev.unlegitdqrk.unlegitlibrary.network.system.utils.TransportProtocol; import lombok.Getter; -import org.openautonomousconnection.protocol.annotations.ProtocolInfo; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.INSQueryPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.INSResponsePacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.WebRequestPacket; import org.openautonomousconnection.protocol.side.ins.ProtocolINSServer; import org.openautonomousconnection.protocol.side.server.CustomConnectedClient; import org.openautonomousconnection.protocol.side.server.ProtocolCustomServer; -import org.openautonomousconnection.protocol.side.server.events.S_CustomClientDisconnectedEvent; import org.openautonomousconnection.protocol.side.web.ProtocolWebServer; -import org.openautonomousconnection.protocol.versions.ProtocolVersion; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; /** * Listener for web server connection events. */ -@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.WEB) public final class CustomServerListener extends EventListener { /** * The reference to the CustomProtocolServer object */ @Getter - private ProtocolCustomServer server; + private final ProtocolCustomServer server; /** * Sets the webServer variable * * @param server The Instance of the CustomProtocolServer */ - public void setServer(ProtocolCustomServer server) { - if (this.server != null) return; + public CustomServerListener(ProtocolCustomServer server) { this.server = server; } @@ -56,34 +48,21 @@ public final class CustomServerListener extends EventListener { * @param event The connection handler connected event. */ @Listener - public void onConnect(ConnectionHandlerConnectedEvent event) { - Class serverClass = server.getCustomClient(); + public void onConnect(S_ClientConnectedEvent event) { try { - CustomConnectedClient client = serverClass.getConstructor(ConnectionHandler.class, ProtocolCustomServer.class).newInstance(event.getConnectionHandler(), server); - server.getClients().add(client); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException | - NoSuchMethodException e) { - server.getProtocolBridge().getLogger().exception("Failed to instantiate connected client", e); + server.getClients().add(new CustomConnectedClient(event.getClient(), (ProtocolCustomServer) server)); + } catch (Exception e) { + server.getProtocolBridge().getLogger().exception("Failed to add client to server", e); + event.getClient().disconnect(); } } - /** - * Handles the event when a connection is disconnected. - * Removes the disconnected client from the protocol web server's client list. - * - * @param event The connection handler disconnected event. - */ @Listener - public void onDisconnect(ConnectionHandlerFullyDisconnectedEvent event) { - server.getClients().removeIf(client -> client.getConnection().getClientId().equals(client.getConnection().getClientId())); - } - - @Listener - public void onPacketWeb(S_PacketReceivedEvent event) { + public void onPacketWeb(S_PacketReadEvent event) { if (!server.getProtocolBridge().isRunningAsWebServer()) return; if (!(event.getPacket() instanceof WebRequestPacket packet)) return; - ((ProtocolWebServer) server).onWebRequest(server.getClientByID(event.getConnectionHandler().getClientId()), packet); + ((ProtocolWebServer) server).onWebRequest(server.getClientByID(event.getClient().getUniqueID()), packet); } /** @@ -103,7 +82,7 @@ public final class CustomServerListener extends EventListener { * @param event The packet event received by the network system. */ @Listener - public void onPacketINS(S_PacketReceivedEvent event) { + public void onPacketINS(S_PacketReadEvent event) { if (!(event.getPacket() instanceof INSQueryPacket q)) return; if (!server.getProtocolBridge().isRunningAsINSServer()) return; @@ -143,9 +122,9 @@ public final class CustomServerListener extends EventListener { INSResponsePacket response = new INSResponsePacket(status, resolved, q.getClientId(), insServer.getProtocolBridge()); try { - event.getConnectionHandler().sendPacket(response, Transport.TCP); + event.getClient().sendPacket(response, TransportProtocol.TCP); insServer.onResponseSent(q.getTLN(), q.getName(), q.getSub(), q.getType(), resolved); - } catch (IOException | ClassNotFoundException e) { + } catch (Exception e) { insServer.onResponseSentFailed(q.getTLN(), q.getName(), q.getSub(), q.getType(), resolved, e); } } diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/OACPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/OACPacket.java index a7df7df..e5502ae 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/OACPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/OACPacket.java @@ -1,14 +1,12 @@ package org.openautonomousconnection.protocol.packets; import dev.unlegitdqrk.unlegitlibrary.network.system.packets.Packet; -import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; import lombok.Getter; import org.openautonomousconnection.protocol.versions.ProtocolVersion; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.*; +import java.util.UUID; /** * Abstract class representing a packet in the Open Autonomous Connection (OAC) protocol. @@ -27,6 +25,13 @@ public abstract class OACPacket extends Packet { */ private INSResponseStatus responseCode = INSResponseStatus.RESPONSE_NOT_REQUIRED; + private final int id; + + @Override + public int getPacketID() { + return id; + } + /** * Constructor for OACPacket. * @@ -34,7 +39,7 @@ public abstract class OACPacket extends Packet { * @param protocolVersion The protocol version associated with this packet. */ public OACPacket(int id, ProtocolVersion protocolVersion) { - super(id); + this.id = id; this.protocolVersion = protocolVersion; } @@ -59,61 +64,54 @@ public abstract class OACPacket extends Packet { /** * Writes the packet data to the output stream. * - * @param packetHandler The packet handler managing the packet. - * @param objectOutputStream The output stream to write the packet data to. + * @param outputStream The output stream to write the packet data to. * @throws IOException If an I/O error occurs. - * @throws ClassNotFoundException If a class cannot be found during serialization. */ @Override - public final void write(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException { + public final void write(DataOutputStream outputStream) throws IOException { // Write the specific packet data - onWrite(packetHandler, objectOutputStream); + onWrite(outputStream); // Write the response code if the protocol version is not classic - if (protocolVersion != ProtocolVersion.PV_1_0_0_CLASSIC) objectOutputStream.writeObject(responseCode); + if (protocolVersion != ProtocolVersion.PV_1_0_0_CLASSIC) outputStream.writeUTF(responseCode.name()); } @Override - public final void read(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { + public final void read(DataInputStream inputStream, UUID clientID) throws IOException { // Read the specific packet data - onRead(packetHandler, objectInputStream); + onRead(inputStream, clientID); // Read the response code if the protocol version is not classic if (protocolVersion != ProtocolVersion.PV_1_0_0_CLASSIC) - responseCode = (INSResponseStatus) objectInputStream.readObject(); + responseCode = INSResponseStatus.valueOf(inputStream.readUTF()); else responseCode = INSResponseStatus.RESPONSE_NOT_REQUIRED; // Call the response code read handler - onResponseCodeRead(packetHandler, objectInputStream); + onResponseCodeRead(inputStream, clientID); } /** * Abstract method to be implemented by subclasses for writing specific packet data. * - * @param packetHandler The packet handler managing the packet. - * @param objectOutputStream The output stream to write the packet data to. + * @param outputStream The output stream to write the packet data to. * @throws IOException If an I/O error occurs. - * @throws ClassNotFoundException If a class cannot be found during serialization. */ - public abstract void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException; + public abstract void onWrite(DataOutputStream outputStream) throws IOException; /** * Abstract method to be implemented by subclasses for reading specific packet data. * - * @param packetHandler The packet handler managing the packet. - * @param objectInputStream The input stream to read the packet data from. + * @param inputStream The input stream to read the packet data from. * @throws IOException If an I/O error occurs. - * @throws ClassNotFoundException If a class cannot be found during deserialization. */ - public abstract void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException; + public abstract void onRead(DataInputStream inputStream, UUID clientID) throws IOException; /** * Method called after the response code has been read from the input stream. * Subclasses can override this method to handle any additional logic based on the response code. * - * @param packetHandler The packet handler managing the packet. - * @param objectInputStream The input stream from which the response code was read. + * @param inputStream The input stream from which the response code was read. */ - protected void onResponseCodeRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) { + protected void onResponseCodeRead(DataInputStream inputStream, UUID clientID) { } } diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/AuthPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/AuthPacket.java index aa30b99..49f165d 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/AuthPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/AuthPacket.java @@ -1,9 +1,8 @@ package org.openautonomousconnection.protocol.packets.v1_0_0.beta; import dev.unlegitdqrk.unlegitlibrary.file.FileUtils; -import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; -import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectionHandler; -import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientID; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectedClient; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.NetworkServer; import dev.unlegitdqrk.unlegitlibrary.network.utils.NetworkUtils; import org.openautonomousconnection.protocol.ProtocolBridge; import org.openautonomousconnection.protocol.packets.OACPacket; @@ -14,18 +13,16 @@ import org.openautonomousconnection.protocol.side.server.events.S_CustomClientCo import org.openautonomousconnection.protocol.versions.ProtocolVersion; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus; -import java.io.File; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.*; +import java.util.UUID; /** * Authentication packet used between client and INS/Web servers. - *

- * Responsibilities: + * + *

Responsibilities: *

    - *
  • Client → Server: Sends client ID and protocol version
  • - *
  • Server → Client: Sends CA key, CA certificate and CA serial files
  • + *
  • Client → Server: Sends client connection id and protocol version
  • + *
  • INS Server → Client: Sends CA key, CA certificate and CA serial files
  • *
  • Performs version compatibility validation
  • *
  • Triggers authentication callbacks on both sides
  • *
@@ -45,95 +42,122 @@ public final class AuthPacket extends OACPacket { } /** - * Registration constructor + * Registration constructor. */ public AuthPacket() { - super(4, ProtocolVersion.PV_1_0_0_BETA); + super(8, ProtocolVersion.PV_1_0_0_BETA); } - /** - * Writes authentication data to the output stream. - *

- * Behavior differs based on the running side: - *

    - *
  • INS Server → sends CA bundle to the client
  • - *
  • Client → sends client ID + protocol version
  • - *
- */ @Override - public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException { - if (protocolBridge.isRunningAsWebServer()) objectOutputStream.writeObject(protocolBridge.getProtocolVersion()); - else if (protocolBridge.isRunningAsINSServer()) { - objectOutputStream.writeObject(protocolBridge.getProtocolVersion()); + public void onWrite(DataOutputStream objectOutputStream) throws IOException { + if (protocolBridge.isRunningAsWebServer()) { + objectOutputStream.writeUTF(protocolBridge.getProtocolVersion().name()); + return; + } + + if (protocolBridge.isRunningAsINSServer()) { + objectOutputStream.writeUTF(protocolBridge.getProtocolVersion().name()); - // Read ca files String caKey = "N/A"; String caPem = "N/A"; String caSrl = "N/A"; + try { - objectOutputStream.writeUTF(protocolBridge.getProtocolServer().getFolderStructure().getCaPrefix() + NetworkUtils.getPublicIPAddress()); + String caPrefix = protocolBridge.getProtocolServer().getFolderStructure().getCaPrefix() + + NetworkUtils.getPublicIPAddress(); + + objectOutputStream.writeUTF(caPrefix); caKey = FileUtils.readFileFull(new File( protocolBridge.getProtocolServer().getFolderStructure().privateCAFolder, - protocolBridge.getProtocolServer().getFolderStructure().getCaPrefix() + NetworkUtils.getPublicIPAddress() + ".key")); + caPrefix + ".key")); caPem = FileUtils.readFileFull(new File( protocolBridge.getProtocolServer().getFolderStructure().publicCAFolder, - protocolBridge.getProtocolServer().getFolderStructure().getCaPrefix() + NetworkUtils.getPublicIPAddress() + ".pem")); + caPrefix + ".pem")); caSrl = FileUtils.readFileFull(new File( protocolBridge.getProtocolServer().getFolderStructure().publicCAFolder, - protocolBridge.getProtocolServer().getFolderStructure().getCaPrefix() + NetworkUtils.getPublicIPAddress() + ".srl")); + caPrefix + ".srl")); } catch (Exception exception) { protocolBridge.getLogger().exception("Failed to read ca-files", exception); setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED); } - // Send ca data objectOutputStream.writeUTF(caKey); objectOutputStream.writeUTF(caPem); objectOutputStream.writeUTF(caSrl); - } else if (protocolBridge.isRunningAsClient()) { - objectOutputStream.writeObject(protocolBridge.getProtocolClient().getClientINSConnection().getClientId()); - objectOutputStream.writeObject(protocolBridge.getProtocolVersion()); + return; + } + + if (protocolBridge.isRunningAsClient()) { + // FIX: Send the connection id of the connection this auth is meant for. + // If we are connecting/authing against INS, use INS connectionId. + // Otherwise use Server connectionId. + UUID clientConnectionId = null; + + if (protocolBridge.getProtocolClient() != null) { + if (protocolBridge.getProtocolClient().getClientINSConnection() != null + && (protocolBridge.getProtocolClient().getClientServerConnection() == null)) { + clientConnectionId = protocolBridge.getProtocolClient().getClientINSConnection().getUniqueID(); + } else if (protocolBridge.getProtocolClient().getClientServerConnection() != null) { + clientConnectionId = protocolBridge.getProtocolClient().getClientServerConnection().getUniqueID(); + } else if (protocolBridge.getProtocolClient().getClientINSConnection() != null) { + clientConnectionId = protocolBridge.getProtocolClient().getClientINSConnection().getUniqueID(); + } + } + + objectOutputStream.writeUTF(clientConnectionId.toString()); + objectOutputStream.writeUTF(protocolBridge.getProtocolVersion().name()); } } - /** - * Reads authentication data and updates protocol state. - *

- * Behavior: - *

    - *
  • Server validates version and registers new connected client
  • - *
  • Client saves received CA files and completes TLS initialization
  • - *
- */ @Override - public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { + public void onRead(DataInputStream objectInputStream, UUID id) throws IOException { if (protocolBridge.isRunningAsServer()) { - ClientID clientID = (ClientID) objectInputStream.readObject(); - ProtocolVersion clientVersion = (ProtocolVersion) objectInputStream.readObject(); - ConnectionHandler connectionHandler = protocolBridge.getProtocolServer().getNetwork().getConnectionHandlerByClientId(clientID); + UUID clientID = UUID.fromString(objectInputStream.readUTF()); + ProtocolVersion clientVersion = ProtocolVersion.valueOf(objectInputStream.readUTF()); + + ConnectedClient connectionHandler = getConnection(protocolBridge.getProtocolServer().getNetwork(), clientID); + if (connectionHandler == null) { + setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED); + return; + } if (!protocolBridge.isVersionSupported(clientVersion)) { setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED); - connectionHandler.disconnect(); + try { + connectionHandler.disconnect(); + } catch (Exception ignored) { + } return; - } else setResponseCode(INSResponseStatus.RESPONSE_AUTH_SUCCESS); + } + setResponseCode(INSResponseStatus.RESPONSE_AUTH_SUCCESS); CustomConnectedClient client = protocolBridge.getProtocolServer().getClientByID(clientID); - client.setClientVersion(clientVersion); - protocolBridge.getProtocolValues().eventManager.executeEvent(new S_CustomClientConnectedEvent(client)); - } else if (protocolBridge.isRunningAsClient()) { - ProtocolVersion serverVersion = (ProtocolVersion) objectInputStream.readObject(); + if (client != null) { + client.setClientVersion(clientVersion); + protocolBridge.getProtocolValues().eventManager.executeEvent(new S_CustomClientConnectedEvent(client)); + } + + return; + } + + if (protocolBridge.isRunningAsClient()) { + ProtocolVersion serverVersion = ProtocolVersion.valueOf(objectInputStream.readUTF()); try { if (!protocolBridge.isVersionSupported(serverVersion)) { setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED); - protocolBridge.getProtocolClient().getClientINSConnection().disconnect(); + if (protocolBridge.getProtocolClient() != null + && protocolBridge.getProtocolClient().getClientINSConnection() != null) { + protocolBridge.getProtocolClient().getClientINSConnection().disconnect(); + } return; - } else setResponseCode(INSResponseStatus.RESPONSE_AUTH_SUCCESS); + } + + setResponseCode(INSResponseStatus.RESPONSE_AUTH_SUCCESS); String caPrefix = objectInputStream.readUTF(); @@ -141,10 +165,9 @@ public final class AuthPacket extends OACPacket { String caPem = objectInputStream.readUTF(); String caSrl = objectInputStream.readUTF(); - if (caKey.equalsIgnoreCase("N/A") || caPem.equalsIgnoreCase("N/A") || caSrl.equalsIgnoreCase("N/A")) + if (caKey.equalsIgnoreCase("N/A") || caPem.equalsIgnoreCase("N/A") || caSrl.equalsIgnoreCase("N/A")) { setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED); - else { - + } else { File caPemFile = new File(protocolBridge.getProtocolClient().getFolderStructure().publicCAFolder, caPrefix + ".pem"); File caSrlFile = new File(protocolBridge.getProtocolClient().getFolderStructure().publicCAFolder, caPrefix + ".srl"); File caKeyFile = new File(protocolBridge.getProtocolClient().getFolderStructure().privateCAFolder, caPrefix + ".key"); @@ -154,9 +177,10 @@ public final class AuthPacket extends OACPacket { if (!caSrlFile.exists()) caSrlFile.createNewFile(); if (!caKeyFile.exists()) caKeyFile.createNewFile(); + // FIX: Correct file assignments. FileUtils.writeFile(caPemFile, caPem); - FileUtils.writeFile(caSrlFile, caKey); - FileUtils.writeFile(caKeyFile, caSrl); + FileUtils.writeFile(caSrlFile, caSrl); + FileUtils.writeFile(caKeyFile, caKey); } catch (Exception exception) { protocolBridge.getLogger().exception("Failed to create/save ca-files", exception); setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED); @@ -164,11 +188,27 @@ public final class AuthPacket extends OACPacket { } protocolBridge.getProtocolClient().setInsVersion(serverVersion); - protocolBridge.getProtocolValues().eventManager.executeEvent(new ConnectedToProtocolINSServerEvent(protocolBridge.getProtocolClient())); + protocolBridge.getProtocolValues().eventManager.executeEvent( + new ConnectedToProtocolINSServerEvent(protocolBridge.getProtocolClient()) + ); } catch (Exception ignored) { protocolBridge.getProtocolClient().setServerVersion(serverVersion); - protocolBridge.getProtocolValues().eventManager.executeEvent(new ConnectedToProtocolServerEvent(protocolBridge.getProtocolClient())); + protocolBridge.getProtocolValues().eventManager.executeEvent( + new ConnectedToProtocolServerEvent(protocolBridge.getProtocolClient()) + ); } } } + + private ConnectedClient getConnection(NetworkServer server, UUID connectionId) { + if (server == null || connectionId == null) return null; + + for (ConnectedClient connection : server.getConnectedClients()) { + if (connection != null && connection.getUniqueID().equals(connectionId)) { + return connection; + } + } + + return null; + } } diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/INSQueryPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/INSQueryPacket.java index 62015e0..6e67f8d 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/INSQueryPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/INSQueryPacket.java @@ -1,15 +1,12 @@ package org.openautonomousconnection.protocol.packets.v1_0_0.beta; -import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; -import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientID; import lombok.Getter; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.versions.ProtocolVersion; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecordType; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.*; +import java.util.UUID; /** * Packet used by clients to query INS records from an INS server. @@ -34,7 +31,7 @@ public final class INSQueryPacket extends OACPacket { @Getter private INSRecordType type; @Getter - private ClientID clientId; + private UUID clientId; /** * Creates a new INS query packet with all required parameters. @@ -45,8 +42,8 @@ public final class INSQueryPacket extends OACPacket { * @param type Record type requested. * @param clientId Sender client ID for routing. */ - public INSQueryPacket(String tln, String name, String sub, INSRecordType type, ClientID clientId) { - super(5, ProtocolVersion.PV_1_0_0_BETA); + public INSQueryPacket(String tln, String name, String sub, INSRecordType type, UUID clientId) { + super(7, ProtocolVersion.PV_1_0_0_BETA); this.TLN = tln; this.name = name; this.sub = sub; @@ -58,36 +55,36 @@ public final class INSQueryPacket extends OACPacket { * Registration constructor */ public INSQueryPacket() { - super(5, ProtocolVersion.PV_1_0_0_BETA); + super(7, ProtocolVersion.PV_1_0_0_BETA); } /** * Serializes the INS query into the stream. */ @Override - public void onWrite(PacketHandler handler, ObjectOutputStream out) throws IOException { + public void onWrite(DataOutputStream out) throws IOException { out.writeUTF(TLN); out.writeUTF(name); out.writeBoolean(sub != null); if (sub != null) out.writeUTF(sub); - out.writeObject(type); - out.writeObject(clientId); + out.writeUTF(type.name()); + out.writeUTF(clientId.toString()); } /** * Deserializes the INS query from the stream. */ @Override - public void onRead(PacketHandler handler, ObjectInputStream in) throws IOException, ClassNotFoundException { + public void onRead(DataInputStream in, UUID clientID) throws IOException { TLN = in.readUTF(); name = in.readUTF(); boolean hasSub = in.readBoolean(); sub = hasSub ? in.readUTF() : null; - type = (INSRecordType) in.readObject(); - clientId = (ClientID) in.readObject(); + type = INSRecordType.valueOf(in.readUTF()); + clientId = UUID.fromString(in.readUTF()); } } diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/INSResponsePacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/INSResponsePacket.java index aae57ce..40dc1cd 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/INSResponsePacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/INSResponsePacket.java @@ -1,7 +1,5 @@ package org.openautonomousconnection.protocol.packets.v1_0_0.beta; -import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; -import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientID; import lombok.Getter; import org.openautonomousconnection.protocol.ProtocolBridge; import org.openautonomousconnection.protocol.packets.OACPacket; @@ -9,11 +7,10 @@ import org.openautonomousconnection.protocol.versions.ProtocolVersion; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.*; import java.util.ArrayList; import java.util.List; +import java.util.UUID; /** * Response packet returned by an INS server after resolving a query. @@ -36,7 +33,7 @@ public final class INSResponsePacket extends OACPacket { @Getter private List records; @Getter - private ClientID clientId; + private UUID clientId; /** * Creates a populated response packet. @@ -46,7 +43,7 @@ public final class INSResponsePacket extends OACPacket { * @param clientId ID of requesting client. * @param bridge Protocol runtime context. */ - public INSResponsePacket(INSResponseStatus status, List records, ClientID clientId, ProtocolBridge bridge) { + public INSResponsePacket(INSResponseStatus status, List records, UUID clientId, ProtocolBridge bridge) { super(6, ProtocolVersion.PV_1_0_0_BETA); this.status = status; this.records = records; @@ -68,32 +65,32 @@ public final class INSResponsePacket extends OACPacket { * Serializes the response status, records and client ID. */ @Override - public void onWrite(PacketHandler handler, ObjectOutputStream out) throws IOException { - out.writeObject(status); + public void onWrite(DataOutputStream out) throws IOException { + out.writeUTF(status.name()); out.writeInt(records.size()); for (INSRecord rec : records) { - out.writeObject(rec); + writeObject(out, rec); } - out.writeObject(clientId); + out.writeUTF(clientId.toString()); } /** * Deserializes the response, reconstructing the record list. */ @Override - public void onRead(PacketHandler handler, ObjectInputStream in) throws IOException, ClassNotFoundException { - status = (INSResponseStatus) in.readObject(); + public void onRead(DataInputStream in, UUID clientID) throws IOException { + status = INSResponseStatus.valueOf(in.readUTF()); int size = in.readInt(); records = new ArrayList<>(size); for (int i = 0; i < size; i++) { - records.add((INSRecord) in.readObject()); + records.add((INSRecord) readObject(in)); } - clientId = (ClientID) in.readObject(); + clientId = UUID.fromString(in.readUTF()); } /** @@ -102,7 +99,7 @@ public final class INSResponsePacket extends OACPacket { * If running on a client, forwards the result to the client-side API. */ @Override - protected void onResponseCodeRead(PacketHandler handler, ObjectInputStream in) { + protected void onResponseCodeRead(DataInputStream in, UUID clientID) { if (bridge.isRunningAsClient()) { bridge.getProtocolClient().onResponse(status, records); } diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/WebRequestPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/WebRequestPacket.java index e15590a..5c18378 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/WebRequestPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/WebRequestPacket.java @@ -1,15 +1,13 @@ package org.openautonomousconnection.protocol.packets.v1_0_0.beta.web; -import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; import lombok.Getter; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.versions.ProtocolVersion; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.WebRequestMethod; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.*; import java.util.Map; +import java.util.UUID; public final class WebRequestPacket extends OACPacket { @@ -26,11 +24,11 @@ public final class WebRequestPacket extends OACPacket { private byte[] body; public WebRequestPacket() { - super(8, ProtocolVersion.PV_1_0_0_BETA); + super(10, ProtocolVersion.PV_1_0_0_BETA); } public WebRequestPacket(String path, WebRequestMethod method, Map headers, byte[] body) { - super(8, ProtocolVersion.PV_1_0_0_BETA); + super(10, ProtocolVersion.PV_1_0_0_BETA); this.path = path; this.method = method; this.headers = headers; @@ -38,10 +36,10 @@ public final class WebRequestPacket extends OACPacket { } @Override - public void onWrite(PacketHandler handler, ObjectOutputStream out) throws IOException { + public void onWrite(DataOutputStream out) throws IOException { out.writeUTF(path != null ? path : "/"); out.writeUTF(method != null ? method.name() : WebRequestMethod.GET.name()); - out.writeObject(headers); + writeMap(out, headers); if (body == null) body = new byte[0]; out.writeInt(body.length); @@ -50,10 +48,10 @@ public final class WebRequestPacket extends OACPacket { @SuppressWarnings("unchecked") @Override - public void onRead(PacketHandler handler, ObjectInputStream in) throws IOException, ClassNotFoundException { + public void onRead(DataInputStream in, UUID clientID) throws IOException { this.path = in.readUTF(); this.method = WebRequestMethod.valueOf(in.readUTF()); - this.headers = (Map) in.readObject(); + this.headers = (Map) readMap(in); int len = in.readInt(); if (len < 0) { diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/WebResponsePacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/WebResponsePacket.java index 1c674d3..69df58e 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/WebResponsePacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/WebResponsePacket.java @@ -1,14 +1,12 @@ package org.openautonomousconnection.protocol.packets.v1_0_0.beta.web; -import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; import lombok.Getter; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.versions.ProtocolVersion; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.*; import java.util.Map; +import java.util.UUID; public final class WebResponsePacket extends OACPacket { @@ -37,10 +35,10 @@ public final class WebResponsePacket extends OACPacket { } @Override - public void onWrite(PacketHandler handler, ObjectOutputStream out) throws IOException { + public void onWrite(DataOutputStream out) throws IOException { out.writeInt(statusCode); out.writeUTF(contentType != null ? contentType : "text/plain"); - out.writeObject(headers); + writeMap(out, headers); if (body == null) body = new byte[0]; out.writeInt(body.length); @@ -48,10 +46,10 @@ public final class WebResponsePacket extends OACPacket { } @Override - public void onRead(PacketHandler handler, ObjectInputStream in) throws IOException, ClassNotFoundException { + public void onRead(DataInputStream in, UUID clientID) throws IOException { this.statusCode = in.readInt(); this.contentType = in.readUTF(); - this.headers = (Map) in.readObject(); + this.headers = (Map) readMap(in); int len = in.readInt(); if (len < 0) { diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/stream/WebStreamChunkPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/stream/WebStreamChunkPacket.java index f960dc1..193f957 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/stream/WebStreamChunkPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/stream/WebStreamChunkPacket.java @@ -1,13 +1,11 @@ package org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.stream; -import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; import lombok.Getter; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.versions.ProtocolVersion; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.*; +import java.util.UUID; public final class WebStreamChunkPacket extends OACPacket { @@ -17,24 +15,24 @@ public final class WebStreamChunkPacket extends OACPacket { private byte[] data; public WebStreamChunkPacket() { - super(11, ProtocolVersion.PV_1_0_0_BETA); + super(13, ProtocolVersion.PV_1_0_0_BETA); } public WebStreamChunkPacket(int seq, byte[] data) { - super(11, ProtocolVersion.PV_1_0_0_BETA); + super(13, ProtocolVersion.PV_1_0_0_BETA); this.seq = seq; this.data = (data != null) ? data : new byte[0]; } @Override - public void onWrite(PacketHandler handler, ObjectOutputStream out) throws IOException { + public void onWrite(DataOutputStream out) throws IOException { out.writeInt(seq); out.writeInt(data.length); out.write(data); } @Override - public void onRead(PacketHandler handler, ObjectInputStream in) throws IOException { + public void onRead(DataInputStream in, UUID clientID) throws IOException { seq = in.readInt(); int len = in.readInt(); if (len < 0) throw new IOException("Negative chunk length"); diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/stream/WebStreamEndPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/stream/WebStreamEndPacket.java index b611f2c..4953246 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/stream/WebStreamEndPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/stream/WebStreamEndPacket.java @@ -1,13 +1,11 @@ package org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.stream; -import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; import lombok.Getter; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.versions.ProtocolVersion; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.*; +import java.util.UUID; public final class WebStreamEndPacket extends OACPacket { @@ -24,12 +22,12 @@ public final class WebStreamEndPacket extends OACPacket { } @Override - public void onWrite(PacketHandler handler, ObjectOutputStream out) throws IOException { + public void onWrite(DataOutputStream out) throws IOException { out.writeBoolean(ok); } @Override - public void onRead(PacketHandler handler, ObjectInputStream in) throws IOException { + public void onRead(DataInputStream in, UUID clientID) throws IOException { ok = in.readBoolean(); } } diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/stream/WebStreamStartPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/stream/WebStreamStartPacket.java index 8115b29..5bd569e 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/stream/WebStreamStartPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/web/stream/WebStreamStartPacket.java @@ -1,14 +1,12 @@ package org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.stream; -import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; import lombok.Getter; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.versions.ProtocolVersion; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.*; import java.util.Map; +import java.util.UUID; public final class WebStreamStartPacket extends OACPacket { @@ -22,11 +20,11 @@ public final class WebStreamStartPacket extends OACPacket { private long totalLength; public WebStreamStartPacket() { - super(10, ProtocolVersion.PV_1_0_0_BETA); + super(11, ProtocolVersion.PV_1_0_0_BETA); } public WebStreamStartPacket(int statusCode, String contentType, Map headers, long totalLength) { - super(10, ProtocolVersion.PV_1_0_0_BETA); + super(11, ProtocolVersion.PV_1_0_0_BETA); this.statusCode = statusCode; this.contentType = contentType; this.headers = headers; @@ -34,19 +32,19 @@ public final class WebStreamStartPacket extends OACPacket { } @Override - public void onWrite(PacketHandler handler, ObjectOutputStream out) throws IOException { + public void onWrite(DataOutputStream out) throws IOException { out.writeInt(statusCode); out.writeUTF(contentType != null ? contentType : "application/octet-stream"); - out.writeObject(headers); + writeMap(out, headers); out.writeLong(totalLength); } @SuppressWarnings("unchecked") @Override - public void onRead(PacketHandler handler, ObjectInputStream in) throws IOException, ClassNotFoundException { + public void onRead(DataInputStream in, UUID clientID) throws IOException { statusCode = in.readInt(); contentType = in.readUTF(); - headers = (Map) in.readObject(); + headers = (Map) readMap(in); totalLength = in.readLong(); } } diff --git a/src/main/java/org/openautonomousconnection/protocol/side/client/ProtocolClient.java b/src/main/java/org/openautonomousconnection/protocol/side/client/ProtocolClient.java index ca0a374..83a2101 100644 --- a/src/main/java/org/openautonomousconnection/protocol/side/client/ProtocolClient.java +++ b/src/main/java/org/openautonomousconnection/protocol/side/client/ProtocolClient.java @@ -1,9 +1,13 @@ package org.openautonomousconnection.protocol.side.client; +import dev.unlegitdqrk.unlegitlibrary.event.EventListener; +import dev.unlegitdqrk.unlegitlibrary.event.Listener; +import dev.unlegitdqrk.unlegitlibrary.file.FileUtils; import dev.unlegitdqrk.unlegitlibrary.network.system.client.NetworkClient; -import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.state.disconnect.ClientFullyDisconnectedEvent; -import dev.unlegitdqrk.unlegitlibrary.network.system.utils.Transport; +import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.state.ClientDisconnectedEvent; +import dev.unlegitdqrk.unlegitlibrary.network.system.utils.TransportProtocol; import dev.unlegitdqrk.unlegitlibrary.network.utils.NetworkUtils; +import dev.unlegitdqrk.unlegitlibrary.network.utils.PemUtils; import dev.unlegitdqrk.unlegitlibrary.utils.DefaultMethodsOverrider; import lombok.Getter; import org.openautonomousconnection.protocol.ProtocolBridge; @@ -15,543 +19,321 @@ import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecordType; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.security.*; import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * Abstract class defining the client-side protocol operations and interactions with INS and servers. */ @ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.CLIENT) -public abstract class ProtocolClient extends DefaultMethodsOverrider { - /** - * Manages the folder structure for client certificates. - */ +public abstract class ProtocolClient extends EventListener { + @Getter private final ClientCertificateFolderStructure folderStructure; - /** - * Handles everything with INS-Connection. - */ + private NetworkClient clientToINS; - /** - * Handles everything with Server-Connection. - */ private NetworkClient clientToServer; - /** - * The reference to the ProtocolBridge Object - */ + @Getter private ProtocolBridge protocolBridge; - /** - * Stores the protocol version of the connected insserver. - */ + private ProtocolVersion insVersion = null; - /** - * Stores the protocol version of the connected server. - */ private ProtocolVersion serverVersion = null; - /** - * Initializes the ProtocolClient, setting up certificate folders and the INS client connection. - */ public ProtocolClient() { - // Initialize and verify certificate folders and files folderStructure = new ClientCertificateFolderStructure(); } - /** - * Connects to a INS Server. - * - * @param host Server host - * @param tcpPort TCP port - * @param udpPort UDP port - */ - public final void buildINSConnection(String host, int tcpPort, int udpPort) { + public final void buildINSConnection(String host, int tcpPort, int udpPort) throws NoSuchAlgorithmException, KeyManagementException { if (!protocolBridge.isRunningAsClient()) throw new IllegalStateException("Not running as client"); if (clientToINS != null && - (clientToINS.isFullyConnected() || clientToINS.isTcpConnected() || clientToINS.isUdpConnected())) + (clientToINS.isConnected() || clientToINS.isTCPConnected() || clientToINS.isUDPConnected())) return; - createINSConnection(host, tcpPort, udpPort); + clientToINS = new NetworkClient.Builder().sslEnabled(false). + packetHandler(protocolBridge.getProtocolValues().packetHandler) + .eventManager(protocolBridge.getProtocolValues().eventManager) + .build(); } - /** - * Initialize connection to INS server - */ - private void createINSConnection(String host, int tcpPort, int udpPort) { - clientToINS = new NetworkClient.ClientBuilder().setLogger(protocolBridge.getLogger()).setProxy(protocolBridge.getProxy()). - setHost(host).setTcpPort(tcpPort).setUdpPort(udpPort). - setPacketHandler(protocolBridge.getProtocolValues().packetHandler).setEventManager(protocolBridge.getProtocolValues().eventManager). - setRootCAFolder(folderStructure.publicCAFolder).setClientCertificatesFolder(folderStructure.publicClientFolder, folderStructure.privateClientFolder). - build(); - } - - /** - * Connects to a Server. - * - * @param host Server host - * @param tcpPort TCP port - * @param udpPort UDP port - */ - public final void buildServerConnection(String host, int tcpPort, int udpPort) { + public final void buildServerConnection(String keyPassword, boolean ssl) throws Exception { if (!protocolBridge.isRunningAsClient()) throw new IllegalStateException("Not running as client"); if (clientToServer != null && - (clientToServer.isFullyConnected() || clientToServer.isTcpConnected() || clientToServer.isUdpConnected())) + (clientToServer.isConnected() || clientToServer.isTCPConnected() || clientToServer.isUDPConnected())) return; - createServerConnection(host, tcpPort, udpPort); + if (ssl) { + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + + int caIndex = 0; + for (File caPem : FileUtils.listFiles(folderStructure.publicCAFolder, ".pem", ".crt", ".cer")) { + if (caPem.getName().endsWith(".srl")) continue; + X509Certificate caCert = PemUtils.loadCertificate(caPem); + trustStore.setCertificateEntry("root-ca-" + (caIndex++), caCert); + } + + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, null); + char[] keyPass = new char[0]; + if (keyPassword != null) keyPass = keyPassword.toCharArray(); + + Map keyFiles = new HashMap<>(); + Map certFiles = new HashMap<>(); + + for (File f : FileUtils.listFiles(folderStructure.privateClientFolder, ".key", ".pem")) { + if (f.getName().endsWith(".srl")) continue; + String base = FileUtils.stripExt(f.getName()); + if (f.getName().endsWith(".key")) keyFiles.put(base, f); + if (f.getName().endsWith(".pem")) certFiles.put(base, f); + } + + int clientIndex = 0; + for (String base : keyFiles.keySet()) { + File keyFile = keyFiles.get(base); + File certFile = certFiles.get(base); + if (certFile == null) { + File alt = new File(folderStructure.publicClientFolder, base + ".pem"); + if (alt.exists()) certFile = alt; + } + if (certFile == null) continue; + + PrivateKey key = PemUtils.loadPrivateKey(keyFile); + X509Certificate cert = PemUtils.loadCertificate(certFile); + + String alias = "client-" + (clientIndex++); + keyStore.setKeyEntry(alias, key, keyPass, new X509Certificate[]{cert}); + } + + clientToServer = new NetworkClient.Builder().sslEnabled(ssl). + packetHandler(protocolBridge.getProtocolValues().packetHandler) + .eventManager(protocolBridge.getProtocolValues().eventManager) + .keyStore(keyStore, keyPass) + .trustStore(trustStore) + .build(); + } else { + clientToServer = new NetworkClient.Builder().sslEnabled(ssl). + packetHandler(protocolBridge.getProtocolValues().packetHandler) + .eventManager(protocolBridge.getProtocolValues().eventManager) + .build(); + } } - /** - * Gets the Server connection client. - * - * @return the NetworkClient handling the Server connection. - */ public final NetworkClient getClientServerConnection() { return clientToServer; } - /** - * Initialize connection to Server - * - * @param host Server host - * @param tcpPort Server port - * @param udpPort Server port - */ - private final void createServerConnection(String host, int tcpPort, int udpPort) { - clientToServer = new NetworkClient.ClientBuilder() - .setLogger(protocolBridge.getLogger()) - .setProxy(protocolBridge.getProxy()) - .setHost(host) - .setTcpPort(tcpPort) - .setUdpPort(udpPort) - .setPacketHandler(protocolBridge.getProtocolValues().packetHandler) - .setEventManager(protocolBridge.getProtocolValues().eventManager) - .setRootCAFolder(folderStructure.publicCAFolder) - .setClientCertificatesFolder( - folderStructure.publicClientFolder, - folderStructure.privateClientFolder - ) - .build(); - } - - /** - * Injects the ProtocolBridge. - * - * @param bridge the Bridge instance. - * @throws IOException when NetworkServer failed to create. - */ - public final void attachBridge(ProtocolBridge bridge) throws IOException { + public final void attachBridge(ProtocolBridge bridge) throws Exception { if (this.protocolBridge != null) throw new IllegalStateException("ProtocolBridge already attached!"); - this.protocolBridge = bridge; + protocolBridge.getProtocolValues().eventManager.registerListener(this.getClass()); } - /** - * Gets the INS connection client. - * - * @return the NetworkClient handling the INS connection. - */ public final NetworkClient getClientINSConnection() { return clientToINS; } - /** - * Checks if the required certificate files exist in the specified folder. - * - * @param folder the folder to check for certificate files. - * @param prefix the prefix of the certificate files. - * @param extension the extension of the certificate files. - * @throws CertificateException if any required certificate file is missing or invalid. - * @throws IOException if there are I/O issues during the check. - */ - private final void checkFileExists(File folder, String prefix, String extension) throws CertificateException, IOException { + private void checkFileExists(File folder, String prefix, String extension) throws CertificateException, IOException { boolean found = false; - // Check if folder exists if (folder == null) throw new FileNotFoundException("Folder does not exist"); - // List files in the folder File[] files = folder.listFiles(); - // Check if folder is empty if (files == null || files.length == 0) throw new FileNotFoundException("Folder " + folder.getAbsolutePath() + " is empty"); - // Validate each file in the folder for (File file : files) { if (!file.getName().startsWith(prefix)) throw new CertificateException(file.getAbsolutePath() + " is not valid"); - // Check for specific files if (!found) found = file.getName().equalsIgnoreCase(prefix + NetworkUtils.getPublicIPAddress() + extension); } - // If the specific file is not found, throw an exception if (!found) throw new CertificateException("Missing " + prefix + NetworkUtils.getPublicIPAddress() + extension); } - /** - * Gets the protocol version of the connected server. - * - * @return the ProtocolVersion of the server, or PV_1_0_0_CLASSIC if not set. - */ public final ProtocolVersion getServerVersion() { return serverVersion == null ? ProtocolVersion.PV_1_0_0_CLASSIC : serverVersion; } - /** - * Sets the protocol version of the connected server. - * - * @param serverVersion the ProtocolVersion to set for the server. - */ public final void setServerVersion(ProtocolVersion serverVersion) { if (serverVersion == null) this.serverVersion = serverVersion; } - /** - * Gets the protocol version of the connected server. - * - * @return the ProtocolVersion of the server, or PV_1_0_0_CLASSIC if not set. - */ public final ProtocolVersion getInsVersion() { return insVersion == null ? ProtocolVersion.PV_1_0_0_CLASSIC : insVersion; } - /** - * Sets the protocol version of the connected server. - * - * @param insVersion the ProtocolVersion to set for the server. - */ public final void setInsVersion(ProtocolVersion insVersion) { if (insVersion == null) this.insVersion = insVersion; } - /** - * Handles disconnect events, resetting the server version and closing the server client connection if necessary. - * - * @param event the ClientDisconnectedEvent triggered on INS disconnection. - */ - public final void onDisconnect(ClientFullyDisconnectedEvent event) { - // Reset server version on INS disconnect - if (!clientToINS.isFullyConnected() && clientToINS != null) { + @Listener + public final void onDisconnect(ClientDisconnectedEvent event) { + if (clientToINS != null && !clientToINS.isConnected()) { insVersion = null; clientToINS = null; disconnectFromServer(); } - if (!clientToServer.isFullyConnected() && clientToServer != null) { + if (clientToServer != null && !clientToServer.isConnected()) { serverVersion = null; clientToServer = null; } } - /** - * Checks if the connected insserver is a stable server. - * - * @return true if the server is stable, false otherwise. - */ public final boolean isINSStableServer() { - // Check if the server version is stable return !isINSBetaServer() && !isINSClassicServer(); } - /** - * Checks if the connected insserver or its compatible versions support stable protocol. - * - * @return true if stable protocol is supported, false otherwise. - */ public final boolean supportINSServerStable() { boolean yes = false; for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { - // Check if compatible version is stable yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.STABLE; if (yes) break; } - - // Check if the server version is stable return isINSStableServer() || yes; } - /** - * Checks if the connected insserver is a beta server. - * - * @return true if the server is beta, false otherwise. - */ public final boolean isINSBetaServer() { - // Check if the server version is beta return getInsVersion().getProtocolType() == ProtocolVersion.ProtocolType.BETA; } - /** - * Checks if the connected insserver or its compatible versions support beta protocol. - * - * @return true if beta protocol is supported, false otherwise. - */ public final boolean supportINSServerBeta() { boolean yes = false; for (ProtocolVersion compatibleVersion : getInsVersion().getCompatibleVersions()) { - // Check if compatible version is beta yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.BETA; if (yes) break; } - - // Check if the server version is beta return isINSBetaServer() || yes; } - /** - * Checks if the connected insserver is a classic server. - * - * @return true if the server is classic, false otherwise. - */ public final boolean isINSClassicServer() { - // Check if the server version is classic return getInsVersion().getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; } - /** - * Checks if the connected insserver or its compatible versions support classic protocol. - * - * @return true if classic protocol is supported, false otherwise. - */ public final boolean supportINSServerClassic() { boolean yes = false; for (ProtocolVersion compatibleVersion : getInsVersion().getCompatibleVersions()) { - // Check if compatible version is classic yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; if (yes) break; } - - // Check if the server version is classic return isINSClassicServer() || yes; } - /** - * Checks if the connected insserver supports the protocol version of the given packet. - * - * @param packet the OACPacket to check against the server's supported protocol version. - * @return true if the server supports the packet's protocol version, false otherwise. - */ public final boolean supportINSServerPacket(OACPacket packet) { - // Check if the server supports the protocol version of the packet return supportINSServerVersion(packet.getProtocolVersion()); } - /** - * Checks if the connected insserver or its compatible versions support the specified protocol version. - * - * @param targetVersion the ProtocolVersion to check for support. - * @return true if the server or its compatible versions support the target version, false otherwise. - */ public final boolean supportINSServerVersion(ProtocolVersion targetVersion) { - // Directly check if the server version matches or is in the list of compatible versions return getInsVersion() == targetVersion || getInsVersion().getCompatibleVersions().contains(targetVersion); } - /** - * Checks if the connected insserver or its compatible versions support the specified protocol. - * - * @param protocol the Protocol to check for support. - * @return true if the server or its compatible versions support the protocol, false otherwise. - */ public final boolean supportINSServerProtocol(ProtocolVersion.Protocol protocol) { boolean yes = false; for (ProtocolVersion compatibleVersion : getInsVersion().getCompatibleVersions()) { - // Check if compatible version supports the protocol yes = compatibleVersion.getSupportedProtocols().contains(protocol); if (yes) break; } - - // Check if the server version supports the protocol return getInsVersion().getSupportedProtocols().contains(protocol) || yes; } - //fwfwef - - /** - * Checks if the connected server is a stable server. - * - * @return true if the server is stable, false otherwise. - */ public final boolean isStableServer() { - // Check if the server version is stable return !isBetaServer() && !isClassicServer(); } - /** - * Checks if the connected server or its compatible versions support stable protocol. - * - * @return true if stable protocol is supported, false otherwise. - */ public final boolean supportServerStable() { boolean yes = false; for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { - // Check if compatible version is stable yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.STABLE; if (yes) break; } - - // Check if the server version is stable return isBetaServer() || yes; } - /** - * Checks if the connected server is a beta server. - * - * @return true if the server is beta, false otherwise. - */ public final boolean isBetaServer() { - // Check if the server version is beta return getServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.BETA; } - /** - * Checks if the connected server or its compatible versions support beta protocol. - * - * @return true if beta protocol is supported, false otherwise. - */ public final boolean supportServerBeta() { boolean yes = false; for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { - // Check if compatible version is beta yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.BETA; if (yes) break; } - - // Check if the server version is beta return isStableServer() || yes; } - /** - * Checks if the connected server is a classic server. - * - * @return true if the server is classic, false otherwise. - */ public final boolean isClassicServer() { - // Check if the server version is classic return getServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; } - /** - * Checks if the connected server or its compatible versions support classic protocol. - * - * @return true if classic protocol is supported, false otherwise. - */ public final boolean supportServerClassic() { boolean yes = false; for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { - // Check if compatible version is classic yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; if (yes) break; } - - // Check if the server version is classic return isClassicServer() || yes; } - /** - * Checks if the connected server supports the protocol version of the given packet. - * - * @param packet the OACPacket to check against the server's supported protocol version. - * @return true if the server supports the packet's protocol version, false otherwise. - */ public final boolean supportServerPacket(OACPacket packet) { - // Check if the server supports the protocol version of the packet return supportServerVersion(packet.getProtocolVersion()); } - /** - * Checks if the connected server or its compatible versions support the specified protocol version. - * - * @param targetVersion the ProtocolVersion to check for support. - * @return true if the server or its compatible versions support the target version, false otherwise. - */ public final boolean supportServerVersion(ProtocolVersion targetVersion) { - // Directly check if the server version matches or is in the list of compatible versions return getServerVersion() == targetVersion || getServerVersion().getCompatibleVersions().contains(targetVersion); } - /** - * Checks if the connected server or its compatible versions support the specified protocol. - * - * @param protocol the Protocol to check for support. - * @return true if the server or its compatible versions support the protocol, false otherwise. - */ public final boolean supportServerProtocol(ProtocolVersion.Protocol protocol) { boolean yes = false; for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { - // Check if compatible version supports the protocol yes = compatibleVersion.getSupportedProtocols().contains(protocol); if (yes) break; } - - // Check if the server version supports the protocol return getServerVersion().getSupportedProtocols().contains(protocol) || yes; } - /** - * Sends an INS query to the INS server. - *

- * The client requests a specific record type for a given TLN, name and optional subname. - * After sending the packet, {@link #onQuerySent(String, String, String, INSRecordType)} is invoked. - * - * @param tln The TLN. - * @param name The InfoName. - * @param sub Optional subname or {@code null}. - * @param type The requested record type. - * @throws IOException If sending the packet fails. - * @throws ClassNotFoundException If packet serialization fails. - */ - public final void sendINSQuery(String tln, String name, String sub, INSRecordType type) throws IOException, ClassNotFoundException { + public final void sendINSQuery(String tln, String name, String sub, INSRecordType type) throws Exception { if (!protocolBridge.isRunningAsClient()) return; - getClientINSConnection().sendPacket(new INSQueryPacket(tln, name, sub, type, getClientINSConnection().getClientId()), Transport.TCP); + getClientINSConnection().sendPacket( + new INSQueryPacket(tln, name, sub, type, getClientINSConnection().getUniqueID()), + TransportProtocol.TCP + ); onQuerySent(tln, name, sub, type); } - /** - * Disconnects from the Server. - */ public final void disconnectFromServer() { if (clientToServer != null) { + protocolBridge.getProtocolValues().eventManager.unregisterListener(this.getClass()); clientToServer.disconnect(); clientToServer = null; } } - - /** - * Called when the client receives an INS response from the server. - *

- * - * @param status The response status from the server. - * @param records The list of records returned by the server. - */ public void onResponse(INSResponseStatus status, List records) { } - /** - * Called after a query was sent to the INS server. - *

- * - * @param tln The TLN requested. - * @param name The InfoName. - * @param sub Optional subname. - * @param type The requested record type. - */ public void onQuerySent(String tln, String name, String sub, INSRecordType type) { } - /** - * Manages the folder structure for client certificates. - */ public static final class ClientCertificateFolderStructure { public final File certificatesFolder; diff --git a/src/main/java/org/openautonomousconnection/protocol/side/client/ProtocolWebClient.java b/src/main/java/org/openautonomousconnection/protocol/side/client/ProtocolWebClient.java deleted file mode 100644 index 3654853..0000000 --- a/src/main/java/org/openautonomousconnection/protocol/side/client/ProtocolWebClient.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.openautonomousconnection.protocol.side.client; - -import org.openautonomousconnection.protocol.annotations.ProtocolInfo; -import org.openautonomousconnection.protocol.versions.ProtocolVersion; - -/** - * Abstract class defining the client-side protocol operations and interactions with INS and servers. - */ -@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.CLIENT) -public class ProtocolWebClient extends ProtocolClient { -} diff --git a/src/main/java/org/openautonomousconnection/protocol/side/ins/ConnectedProtocolClient.java b/src/main/java/org/openautonomousconnection/protocol/side/ins/ConnectedProtocolClient.java deleted file mode 100644 index a4e6304..0000000 --- a/src/main/java/org/openautonomousconnection/protocol/side/ins/ConnectedProtocolClient.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.openautonomousconnection.protocol.side.ins; - -import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectionHandler; -import org.openautonomousconnection.protocol.annotations.ProtocolInfo; -import org.openautonomousconnection.protocol.side.server.CustomConnectedClient; -import org.openautonomousconnection.protocol.versions.ProtocolVersion; - -/** - * Represents a connected protocol client on the INS server side. - */ -@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.INS) -public final class ConnectedProtocolClient extends CustomConnectedClient { - - public ConnectedProtocolClient(ConnectionHandler connectionHandler, ProtocolINSServer protocolINSServer) { - super(connectionHandler, protocolINSServer); - } -} diff --git a/src/main/java/org/openautonomousconnection/protocol/side/ins/ProtocolINSServer.java b/src/main/java/org/openautonomousconnection/protocol/side/ins/ProtocolINSServer.java index 1142a30..e22c9d8 100644 --- a/src/main/java/org/openautonomousconnection/protocol/side/ins/ProtocolINSServer.java +++ b/src/main/java/org/openautonomousconnection/protocol/side/ins/ProtocolINSServer.java @@ -1,7 +1,8 @@ package org.openautonomousconnection.protocol.side.ins; import dev.unlegitdqrk.unlegitlibrary.file.ConfigurationManager; -import dev.unlegitdqrk.unlegitlibrary.network.system.utils.TransportPolicy; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.NetworkServer; +import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientAuthMode; import lombok.Getter; import org.openautonomousconnection.protocol.annotations.ProtocolInfo; import org.openautonomousconnection.protocol.side.server.ProtocolCustomServer; @@ -9,6 +10,8 @@ import org.openautonomousconnection.protocol.versions.ProtocolVersion; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecordType; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLServerSocketFactory; import java.io.File; import java.io.IOException; import java.security.cert.CertificateException; @@ -25,17 +28,22 @@ public abstract class ProtocolINSServer extends ProtocolCustomServer { * * @return The INS information site URL. */ - @Getter private final String insInfoSite; + public final String getInsInfoSite() { + return insInfoSite; + } /** * Gets the INS registration site URL from the configuration. * * @return The INS registration site URL. */ - @Getter private String insFrontendSite; + public final String getInsFrontendSite() { + return insFrontendSite; + } + /** * Constructs a ProtocolINSServer with the specified configuration file. * @@ -44,11 +52,14 @@ public abstract class ProtocolINSServer extends ProtocolCustomServer { * @throws IOException If an I/O error occurs. * @throws CertificateException If a certificate error occurs. */ - public ProtocolINSServer(String insInfoSite, String insFrontendSite, int tcpPort, int udpPort) throws Exception { - super("ins", "ins", tcpPort, udpPort); + public ProtocolINSServer(String insInfoSite, String insFrontendSite) throws Exception { + super("ins", "ins"); this.insInfoSite = insInfoSite; this.insFrontendSite = insFrontendSite; - setCustomClient(ConnectedProtocolClient.class); + } + + public void start(int tcpPort) throws IOException, InterruptedException { + getNetwork().start(tcpPort, -1); } /** diff --git a/src/main/java/org/openautonomousconnection/protocol/side/server/CustomConnectedClient.java b/src/main/java/org/openautonomousconnection/protocol/side/server/CustomConnectedClient.java index c6dbc5d..6017358 100644 --- a/src/main/java/org/openautonomousconnection/protocol/side/server/CustomConnectedClient.java +++ b/src/main/java/org/openautonomousconnection/protocol/side/server/CustomConnectedClient.java @@ -1,14 +1,19 @@ package org.openautonomousconnection.protocol.side.server; -import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectionHandler; +import dev.unlegitdqrk.unlegitlibrary.event.EventListener; +import dev.unlegitdqrk.unlegitlibrary.event.EventManager; +import dev.unlegitdqrk.unlegitlibrary.event.EventPriority; +import dev.unlegitdqrk.unlegitlibrary.event.Listener; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectedClient; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.client.S_ClientDisconnectedEvent; import lombok.Getter; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.versions.ProtocolVersion; -public abstract class CustomConnectedClient { +public class CustomConnectedClient extends EventListener { @Getter - private final ConnectionHandler connection; + private final ConnectedClient connection; @Getter private final ProtocolCustomServer server; @@ -18,16 +23,15 @@ public abstract class CustomConnectedClient { @Getter private boolean clientVersionLoaded = false; - public CustomConnectedClient(ConnectionHandler connection, ProtocolCustomServer protocolServer) { + public CustomConnectedClient(ConnectedClient connection, ProtocolCustomServer protocolServer) throws Exception { this.connection = connection; this.server = protocolServer; + server.getProtocolBridge().getProtocolValues().eventManager.registerListener(this.getClass()); } public synchronized void disconnect() { - try { - server.clientDisconnected(this); - } catch (Exception ignored) { - } + server.getProtocolBridge().getProtocolValues().eventManager.unregisterListener(this.getClass()); + try { connection.disconnect(); } catch (Exception ignored) { @@ -36,6 +40,13 @@ public abstract class CustomConnectedClient { clientVersion = null; } + @Listener(priority = EventPriority.HIGH) + public void onDisconnect(S_ClientDisconnectedEvent event) { + if (event.getClient().getUniqueID().equals(this.connection.getUniqueID())) { + clientVersion = null; + } + } + /** * Gets the protocol version of the connected client. diff --git a/src/main/java/org/openautonomousconnection/protocol/side/server/ProtocolCustomServer.java b/src/main/java/org/openautonomousconnection/protocol/side/server/ProtocolCustomServer.java index c2c178c..d4dc218 100644 --- a/src/main/java/org/openautonomousconnection/protocol/side/server/ProtocolCustomServer.java +++ b/src/main/java/org/openautonomousconnection/protocol/side/server/ProtocolCustomServer.java @@ -1,28 +1,42 @@ package org.openautonomousconnection.protocol.side.server; +import dev.unlegitdqrk.unlegitlibrary.event.EventListener; +import dev.unlegitdqrk.unlegitlibrary.event.EventPriority; +import dev.unlegitdqrk.unlegitlibrary.event.Listener; +import dev.unlegitdqrk.unlegitlibrary.file.FileUtils; +import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.state.ClientDisconnectedEvent; import dev.unlegitdqrk.unlegitlibrary.network.system.server.NetworkServer; -import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientID; -import dev.unlegitdqrk.unlegitlibrary.network.system.utils.TransportPolicy; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.state.ServerStoppedEvent; +import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientAuthMode; import dev.unlegitdqrk.unlegitlibrary.network.utils.NetworkUtils; +import dev.unlegitdqrk.unlegitlibrary.network.utils.PemUtils; import lombok.Getter; -import lombok.Setter; import org.openautonomousconnection.protocol.ProtocolBridge; +import org.openautonomousconnection.protocol.side.server.events.S_CustomClientDisconnectedEvent; +import org.openautonomousconnection.protocol.side.web.managers.AuthManager; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.security.KeyStore; +import java.security.PrivateKey; import java.security.cert.CertificateException; -import java.util.ArrayList; -import java.util.List; +import java.security.cert.X509Certificate; +import java.util.*; -public abstract class ProtocolCustomServer { +public abstract class ProtocolCustomServer extends EventListener { /** * Structure for server. */ - @Getter private final ServerCertificateFolderStructure folderStructure; + public final ServerCertificateFolderStructure getFolderStructure() { + return folderStructure; + } + /** * Certificate files for SSL. */ @@ -35,43 +49,43 @@ public abstract class ProtocolCustomServer { /** * The reference to the ProtocolBridge Object */ - @Getter private ProtocolBridge protocolBridge; + public final ProtocolBridge getProtocolBridge() { + return protocolBridge; + } + /** * List of connected web clients. */ - @Getter - private List clients; + private final List clients; - @Setter - @Getter - private Class customClient; + public final List getClients() { + return clients; + } /** * The network server handling pipeline connections. */ - @Getter private NetworkServer network; - @Getter - private int tcpPort; + public final NetworkServer getNetwork() { + return network; + } - @Getter - private int udpPort; + protected final void setNetwork(NetworkServer network) { + this.network = network; + } /** * Initializes the web server with the given configuration, authentication, and rules files. * * @throws Exception If an error occurs during initialization. */ - public ProtocolCustomServer(String caPrefix, String certPrefix, int tcpPort, int udpPort) throws Exception { + public ProtocolCustomServer(String caPrefix, String certPrefix) throws Exception { // Initialize the list of connected clients this.clients = new ArrayList<>(); - this.tcpPort = tcpPort; - this.udpPort = udpPort; - // Set up folder structure for certificates folderStructure = new ServerCertificateFolderStructure(caPrefix, certPrefix); @@ -90,36 +104,95 @@ public abstract class ProtocolCustomServer { * @param bridge the Bridge instance. * @throws IOException when NetworkServer failed to create. */ - public final void attachBridge(ProtocolBridge bridge) throws IOException { + public final void attachBridge(ProtocolBridge bridge, String keyPassword, boolean ssl, ClientAuthMode authMode) throws Exception { if (this.protocolBridge != null) throw new IllegalStateException("ProtocolBridge already attached!"); - this.protocolBridge = bridge; - createNetworkServer(); + if (ssl) { + char[] keyPass = new char[0]; + if (keyPassword != null) keyPass = keyPassword.toCharArray(); + + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + + int caIndex = 0; + for (File caPem : FileUtils.listFiles(folderStructure.publicCAFolder, ".pem", ".crt", ".cer")) { + if (caPem.getName().endsWith(".srl")) continue; + if (!caPem.getName().startsWith(folderStructure.getCaPrefix())) continue; + + X509Certificate caCert = PemUtils.loadCertificate(caPem); + trustStore.setCertificateEntry("root-ca-" + (caIndex++), caCert); + } + + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, null); + + Map keyFiles = new HashMap<>(); + Map certFiles = new HashMap<>(); + + for (File f : FileUtils.listFiles(folderStructure.privateServerFolder, ".key", ".pem")) { + if (f.getName().endsWith(".srl")) continue; + if (!f.getName().startsWith(folderStructure.getCertPrefix())) continue; + + String base = FileUtils.stripExt(f.getName()); + if (f.getName().endsWith(".key")) keyFiles.put(base, f); + if (f.getName().endsWith(".pem")) certFiles.put(base, f); + } + + int serverIndex = 0; + for (String base : keyFiles.keySet()) { + File keyFile = keyFiles.get(base); + File certFile = certFiles.get(base); + if (certFile == null) { + File alt = new File(folderStructure.publicServerFolder, base + ".pem"); + if (alt.exists()) certFile = alt; + } + if (certFile == null) continue; + + PrivateKey key = PemUtils.loadPrivateKey(keyFile); + X509Certificate cert = PemUtils.loadCertificate(certFile); + + String alias = "server-" + (serverIndex++); + keyStore.setKeyEntry(alias, key, keyPass, new X509Certificate[]{cert}); + } + + bridge.getProtocolValues().eventManager.registerListener(this.getClass()); + + network = new NetworkServer.Builder() + .packetHandler(bridge.getProtocolValues().packetHandler) + .eventManager(bridge.getProtocolValues().eventManager) + .sslEnabled(true) + .clientAuthMode(authMode) + .keyStore(keyStore, keyPass) + .trustStore(trustStore) + .build(); + } else { + network = new NetworkServer.Builder() + .packetHandler(bridge.getProtocolValues().packetHandler) + .eventManager(bridge.getProtocolValues().eventManager) + .sslEnabled(false) + .clientAuthMode(ClientAuthMode.NONE) + .build(); + } } - /** - * Initialize the pipeline server - */ - private void createNetworkServer() { - network = new NetworkServer.ServerBuilder(). - setTcpPort(tcpPort).setUdpPort(udpPort).setTransportPolicy(TransportPolicy.bothRequired()). - setTimeout(0). - setPacketHandler(protocolBridge.getProtocolValues().packetHandler). - setEventManager(protocolBridge.getProtocolValues().eventManager).setLogger(protocolBridge.getLogger()). - setServerCertificate(certFile, keyFile).setRootCAFolder(folderStructure.publicCAFolder). - build(); + @Listener + public void onStop(ServerStoppedEvent event) { + if (event.getServer() == network) { + protocolBridge.getProtocolValues().eventManager.unregisterListener(this.getClass()); + } } + /** * Retrieves a connected web client by its client ID. * * @param clientID The client ID to search for. * @return The connected web client with the specified ID, or null if not found. */ - public final T getClientByID(ClientID clientID) { + public final T getClientByID(UUID clientID) { for (CustomConnectedClient client : clients) - if (client.getConnection().getClientId() == clientID) return (T) client; + if (client.getConnection().getUniqueID().equals(clientID)) return (T) client; return null; } @@ -156,15 +229,14 @@ public abstract class ProtocolCustomServer { if (!found) throw new CertificateException("Missing " + prefix + NetworkUtils.getPublicIPAddress() + extension); } - public final void clientDisconnected(CustomConnectedClient client) { - clients.remove(client); - onDisconnect(client); - } - - /** - * Optional callback when the connection closes. - */ - public void onDisconnect(CustomConnectedClient client) { + @Listener(priority = EventPriority.NORMAL) + public final void clientDisconnected(ClientDisconnectedEvent event) { + for (CustomConnectedClient client : new ArrayList<>(clients)) { + if (client.getConnection().getUniqueID().equals(event.getClient().getUniqueID())) { + protocolBridge.getProtocolValues().eventManager.executeEvent(new S_CustomClientDisconnectedEvent(client)); + clients.remove(client); + } + } } /** diff --git a/src/main/java/org/openautonomousconnection/protocol/side/web/ConnectedWebClient.java b/src/main/java/org/openautonomousconnection/protocol/side/web/ConnectedWebClient.java deleted file mode 100644 index ba8265d..0000000 --- a/src/main/java/org/openautonomousconnection/protocol/side/web/ConnectedWebClient.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.openautonomousconnection.protocol.side.web; - -import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectionHandler; -import lombok.Getter; -import org.openautonomousconnection.protocol.side.server.CustomConnectedClient; - -/** - * A connected web client using pure protocol packets. - */ -public final class ConnectedWebClient extends CustomConnectedClient { - - public ConnectedWebClient(ConnectionHandler pipelineConnection, ProtocolWebServer webServer) { - super(pipelineConnection, webServer); - } -} diff --git a/src/main/java/org/openautonomousconnection/protocol/side/web/ProtocolWebServer.java b/src/main/java/org/openautonomousconnection/protocol/side/web/ProtocolWebServer.java index 4a08682..2f18f7d 100644 --- a/src/main/java/org/openautonomousconnection/protocol/side/web/ProtocolWebServer.java +++ b/src/main/java/org/openautonomousconnection/protocol/side/web/ProtocolWebServer.java @@ -1,12 +1,13 @@ package org.openautonomousconnection.protocol.side.web; import dev.unlegitdqrk.unlegitlibrary.file.FileUtils; -import dev.unlegitdqrk.unlegitlibrary.network.system.utils.TransportPolicy; +import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientAuthMode; import dev.unlegitdqrk.unlegitlibrary.string.RandomString; import lombok.Getter; import org.openautonomousconnection.protocol.annotations.ProtocolInfo; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.WebRequestPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.WebResponsePacket; +import org.openautonomousconnection.protocol.side.server.CustomConnectedClient; import org.openautonomousconnection.protocol.side.server.ProtocolCustomServer; import org.openautonomousconnection.protocol.side.web.managers.AuthManager; import org.openautonomousconnection.protocol.side.web.managers.RuleManager; @@ -23,31 +24,47 @@ public abstract class ProtocolWebServer extends ProtocolCustomServer { /** * Folder for web content. */ - @Getter private final File contentFolder; + public final File getContentFolder() { + return contentFolder; + } + /** * Folder for error pages. */ - @Getter private final File errorsFolder; + + public final File getErrorsFolder() { + return errorsFolder; + } + /** * A unique secret for session management. */ - @Getter - private String uniqueSessionString; + private final String uniqueSessionString; + + public final String getUniqueSessionString() { + return uniqueSessionString; + } /** * The expiration time of a Session in minutes */ - @Getter - private int sessionExpire; + private final int sessionExpire; + + public final int getSessionExpire() { + return sessionExpire; + } /** * The max upload size in MB */ - @Getter - private int maxUploadSize; + private final int maxUploadSize; + + public final int getMaxUploadSize() { + return maxUploadSize; + } /** * Initializes the web server with the given configuration, authentication, and rules files. @@ -58,9 +75,8 @@ public abstract class ProtocolWebServer extends ProtocolCustomServer { * @param uploadSize The max upload size in MB * @throws Exception If an error occurs during initialization. */ - public ProtocolWebServer(File authFile, File rulesFile, int tcpPort, int udpPort, - int sessionExpire, int uploadSize) throws Exception { - super("server", "server", tcpPort, udpPort); + public ProtocolWebServer(File authFile, File rulesFile, int sessionExpire, int uploadSize) throws Exception { + super("server", "server"); this.sessionExpire = sessionExpire; this.maxUploadSize = uploadSize; @@ -108,8 +124,6 @@ public abstract class ProtocolWebServer extends ProtocolCustomServer { AuthManager.loadAuthFile(authFile); RuleManager.loadRules(rulesFile); - - setCustomClient(ConnectedWebClient.class); } /** @@ -119,5 +133,5 @@ public abstract class ProtocolWebServer extends ProtocolCustomServer { * @param request The full decoded request packet. * @return The response packet that should be sent back to the client. */ - public abstract WebResponsePacket onWebRequest(ConnectedWebClient client, WebRequestPacket request); + public abstract WebResponsePacket onWebRequest(CustomConnectedClient client, WebRequestPacket request); }