From ebccdf5b360b7e61b6ad84dc5461dc99f4afb40c Mon Sep 17 00:00:00 2001 From: Finn Date: Fri, 12 Dec 2025 20:57:01 +0100 Subject: [PATCH] Added missing option to connect to WebServer --- pom.xml | 2 +- .../protocol/ProtocolBridge.java | 24 +- .../packets/v1_0_0/beta/AuthPacket.java | 77 ++--- .../v1_0_0/beta/WebStreamChunkPacket.java | 43 +++ .../v1_0_0/beta/WebStreamEndPacket.java | 35 +++ .../v1_0_0/beta/WebStreamStartPacket.java | 52 ++++ .../protocol/side/client/ProtocolClient.java | 294 +++++++++++++++--- .../ConnectedToProtocolWebServerEvent.java | 25 ++ .../protocol/side/web/ConnectedWebClient.java | 128 ++++---- .../protocol/side/web/ProtocolWebServer.java | 2 + ...vent.java => WebClientConnectedEvent.java} | 4 +- 11 files changed, 536 insertions(+), 150 deletions(-) create mode 100644 src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/WebStreamChunkPacket.java create mode 100644 src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/WebStreamEndPacket.java create mode 100644 src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/WebStreamStartPacket.java create mode 100644 src/main/java/org/openautonomousconnection/protocol/side/client/events/ConnectedToProtocolWebServerEvent.java rename src/main/java/org/openautonomousconnection/protocol/side/web/events/{ConnectedWebClientEvent.java => WebClientConnectedEvent.java} (84%) diff --git a/pom.xml b/pom.xml index 333132c..b6aa7eb 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.openautonomousconnection protocol - 1.0.0-BETA.3 + 1.0.0-BETA.4 Open Autonomous Connection https://open-autonomous-connection.org/ diff --git a/src/main/java/org/openautonomousconnection/protocol/ProtocolBridge.java b/src/main/java/org/openautonomousconnection/protocol/ProtocolBridge.java index 1186e84..6a80631 100644 --- a/src/main/java/org/openautonomousconnection/protocol/ProtocolBridge.java +++ b/src/main/java/org/openautonomousconnection/protocol/ProtocolBridge.java @@ -8,10 +8,7 @@ import org.openautonomousconnection.protocol.listeners.ClientListener; import org.openautonomousconnection.protocol.listeners.INSServerListener; import org.openautonomousconnection.protocol.listeners.WebServerListener; import org.openautonomousconnection.protocol.packets.OACPacket; -import org.openautonomousconnection.protocol.packets.v1_0_0.beta.AuthPacket; -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.UnsupportedClassicPacket; +import org.openautonomousconnection.protocol.packets.v1_0_0.beta.*; import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_DomainPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_MessagePacket; import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_PingPacket; @@ -196,14 +193,21 @@ public final class ProtocolBridge { UnsupportedClassicPacket v100bUnsupportedClassicPacket = new UnsupportedClassicPacket(); 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)) protocolSettings.packetHandler.registerPacket(v100bAuthPath); - if (isPacketSupported(v100bUnsupportedClassicPacket)) - protocolSettings.packetHandler.registerPacket(v100bUnsupportedClassicPacket); - if (isPacketSupported(v100BINSQueryPacket)) - protocolSettings.packetHandler.registerPacket(v100BINSQueryPacket); - if (isPacketSupported(v100BINSResponsePacket)) - protocolSettings.packetHandler.registerPacket(v100BINSResponsePacket); + if (isPacketSupported(v100bUnsupportedClassicPacket)) protocolSettings.packetHandler.registerPacket(v100bUnsupportedClassicPacket); + if (isPacketSupported(v100BINSQueryPacket)) protocolSettings.packetHandler.registerPacket(v100BINSQueryPacket); + if (isPacketSupported(v100BINSResponsePacket)) protocolSettings.packetHandler.registerPacket(v100BINSResponsePacket); + if (isPacketSupported(v100BWebRequestPacket)) protocolSettings.packetHandler.registerPacket(v100BWebRequestPacket); + if (isPacketSupported(v100BResponsePacket)) protocolSettings.packetHandler.registerPacket(v100BResponsePacket); + if (isPacketSupported(v100BStreamChunkPacket)) protocolSettings.packetHandler.registerPacket(v100BStreamChunkPacket); + if (isPacketSupported(v100BStreamStartPacket)) protocolSettings.packetHandler.registerPacket(v100BStreamStartPacket); + if (isPacketSupported(v100BStreamEndPacket)) protocolSettings.packetHandler.registerPacket(v100BStreamEndPacket); } /** 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 e2f93d0..5a1af5d 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 @@ -7,6 +7,7 @@ import dev.unlegitdqrk.unlegitlibrary.network.utils.NetworkUtils; import org.openautonomousconnection.protocol.ProtocolBridge; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.side.client.events.ConnectedToProtocolINSServerEvent; +import org.openautonomousconnection.protocol.side.client.events.ConnectedToProtocolWebServerEvent; import org.openautonomousconnection.protocol.side.ins.ConnectedProtocolClient; import org.openautonomousconnection.protocol.side.ins.events.ConnectedProtocolClientEvent; import org.openautonomousconnection.protocol.side.web.ConnectedWebClient; @@ -61,7 +62,8 @@ public final class AuthPacket extends OACPacket { */ @Override public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException { - if (protocolBridge.isRunningAsINSServer()) { + if (protocolBridge.isRunningAsWebServer()) objectOutputStream.writeObject(protocolBridge.getProtocolVersion()); + else if (protocolBridge.isRunningAsINSServer()) { objectOutputStream.writeObject(protocolBridge.getProtocolVersion()); // Read ca files @@ -131,42 +133,47 @@ public final class AuthPacket extends OACPacket { } else if (protocolBridge.isRunningAsClient()) { ProtocolVersion serverVersion = (ProtocolVersion) objectInputStream.readObject(); - if (!protocolBridge.isVersionSupported(serverVersion)) { - setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED); - protocolBridge.getProtocolClient().getClientINSConnection().disconnect(); - return; - } else setResponseCode(INSResponseStatus.RESPONSE_AUTH_SUCCESS); - - String caPrefix = objectInputStream.readUTF(); - - String caKey = objectInputStream.readUTF(); - String caPem = objectInputStream.readUTF(); - String caSrl = objectInputStream.readUTF(); - - if (caKey.equalsIgnoreCase("N/A") || caPem.equalsIgnoreCase("N/A") || caSrl.equalsIgnoreCase("N/A")) - setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED); - 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"); - - try { - if (!caPemFile.exists()) caPemFile.createNewFile(); - if (!caSrlFile.exists()) caSrlFile.createNewFile(); - if (!caKeyFile.exists()) caKeyFile.createNewFile(); - - FileUtils.writeFile(caPemFile, caPem); - FileUtils.writeFile(caSrlFile, caKey); - FileUtils.writeFile(caKeyFile, caSrl); - } catch (Exception exception) { - protocolBridge.getLogger().exception("Failed to create/save ca-files", exception); + try { + if (!protocolBridge.isVersionSupported(serverVersion)) { setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED); - } - } + protocolBridge.getProtocolClient().getClientINSConnection().disconnect(); + return; + } else setResponseCode(INSResponseStatus.RESPONSE_AUTH_SUCCESS); - protocolBridge.getProtocolClient().setServerVersion(serverVersion); - protocolBridge.getProtocolSettings().eventManager.executeEvent(new ConnectedToProtocolINSServerEvent(protocolBridge.getProtocolClient())); + String caPrefix = objectInputStream.readUTF(); + + String caKey = objectInputStream.readUTF(); + String caPem = objectInputStream.readUTF(); + String caSrl = objectInputStream.readUTF(); + + if (caKey.equalsIgnoreCase("N/A") || caPem.equalsIgnoreCase("N/A") || caSrl.equalsIgnoreCase("N/A")) + setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED); + 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"); + + try { + if (!caPemFile.exists()) caPemFile.createNewFile(); + if (!caSrlFile.exists()) caSrlFile.createNewFile(); + if (!caKeyFile.exists()) caKeyFile.createNewFile(); + + FileUtils.writeFile(caPemFile, caPem); + FileUtils.writeFile(caSrlFile, caKey); + FileUtils.writeFile(caKeyFile, caSrl); + } catch (Exception exception) { + protocolBridge.getLogger().exception("Failed to create/save ca-files", exception); + setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED); + } + } + + protocolBridge.getProtocolClient().setInsServerVersion(serverVersion); + protocolBridge.getProtocolSettings().eventManager.executeEvent(new ConnectedToProtocolINSServerEvent(protocolBridge.getProtocolClient())); + } catch (Exception ignored) { + protocolBridge.getProtocolClient().setWebServerVersion(serverVersion); + protocolBridge.getProtocolSettings().eventManager.executeEvent(new ConnectedToProtocolWebServerEvent(protocolBridge.getProtocolClient())); + } } } } diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/WebStreamChunkPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/WebStreamChunkPacket.java new file mode 100644 index 0000000..06f3ad3 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/WebStreamChunkPacket.java @@ -0,0 +1,43 @@ +package org.openautonomousconnection.protocol.packets.v1_0_0.beta; + +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; + +public final class WebStreamChunkPacket extends OACPacket { + + @Getter + private int seq; + @Getter + private byte[] data; + + public WebStreamChunkPacket() { + super(11, ProtocolVersion.PV_1_0_0_BETA); + } + + public WebStreamChunkPacket(int seq, byte[] data) { + super(11, 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 { + out.writeInt(seq); + out.writeInt(data.length); + out.write(data); + } + + @Override + public void onRead(PacketHandler handler, ObjectInputStream in) throws IOException { + seq = in.readInt(); + int len = in.readInt(); + if (len < 0) throw new IOException("Negative chunk length"); + data = in.readNBytes(len); + } +} diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/WebStreamEndPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/WebStreamEndPacket.java new file mode 100644 index 0000000..7ccf5ec --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/WebStreamEndPacket.java @@ -0,0 +1,35 @@ +package org.openautonomousconnection.protocol.packets.v1_0_0.beta; + +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; + +public final class WebStreamEndPacket extends OACPacket { + + @Getter + private boolean ok; + + public WebStreamEndPacket() { + super(12, ProtocolVersion.PV_1_0_0_BETA); + } + + public WebStreamEndPacket(boolean ok) { + super(12, ProtocolVersion.PV_1_0_0_BETA); + this.ok = ok; + } + + @Override + public void onWrite(PacketHandler handler, ObjectOutputStream out) throws IOException { + out.writeBoolean(ok); + } + + @Override + public void onRead(PacketHandler handler, ObjectInputStream in) throws IOException { + ok = in.readBoolean(); + } +} diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/WebStreamStartPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/WebStreamStartPacket.java new file mode 100644 index 0000000..9631c80 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/WebStreamStartPacket.java @@ -0,0 +1,52 @@ +package org.openautonomousconnection.protocol.packets.v1_0_0.beta; + +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.util.Map; + +public final class WebStreamStartPacket extends OACPacket { + + @Getter + private int statusCode; + @Getter + private String contentType; + @Getter + private Map headers; + @Getter + private long totalLength; + + public WebStreamStartPacket() { + super(10, ProtocolVersion.PV_1_0_0_BETA); + } + + public WebStreamStartPacket(int statusCode, String contentType, Map headers, long totalLength) { + super(10, ProtocolVersion.PV_1_0_0_BETA); + this.statusCode = statusCode; + this.contentType = contentType; + this.headers = headers; + this.totalLength = totalLength; + } + + @Override + public void onWrite(PacketHandler handler, ObjectOutputStream out) throws IOException { + out.writeInt(statusCode); + out.writeUTF(contentType != null ? contentType : "application/octet-stream"); + out.writeObject(headers); + out.writeLong(totalLength); + } + + @SuppressWarnings("unchecked") + @Override + public void onRead(PacketHandler handler, ObjectInputStream in) throws IOException, ClassNotFoundException { + statusCode = in.readInt(); + contentType = in.readUTF(); + headers = (Map) in.readObject(); + 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 532f31b..25fab66 100644 --- a/src/main/java/org/openautonomousconnection/protocol/side/client/ProtocolClient.java +++ b/src/main/java/org/openautonomousconnection/protocol/side/client/ProtocolClient.java @@ -30,6 +30,11 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider { */ private NetworkClient clientToINS; + /** + * Handles everything with WebServer-Connection. + */ + private NetworkClient clientToWeb; + /** * Manages the folder structure for client certificates. */ @@ -41,9 +46,13 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider { @Getter private ProtocolBridge protocolBridge; /** - * Stores the protocol version of the connected server. + * Stores the protocol version of the connected insserver. */ - private ProtocolVersion serverVersion = null; + private ProtocolVersion insServerVersion = null; + /** + * Stores the protocol version of the connected webserver. + */ + private ProtocolVersion webServerVersion = null; /** * Initializes the ProtocolClient, setting up certificate folders and the INS client connection. @@ -64,6 +73,53 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider { build(); } + /** + * Connects to a WebServer. + * + * @param host WebServer host + * @param port WebServer port + */ + public final void connectToWebServer(String host, int port) { + if (!protocolBridge.isRunningAsClient()) + throw new IllegalStateException("Not running as client"); + + if (clientToWeb != null && clientToWeb.isConnected()) + return; + + createWebClient(host, port); + } + + /** + * Gets the WebServer connection client. + * + * @return the NetworkClient handling the WebServer connection. + */ + public final NetworkClient getClientWebConnection() { + return clientToWeb; + } + + /** + * Initialize connection to WebServer + * + * @param host WebServer host + * @param port WebServer port + */ + private final void createWebClient(String host, int port) { + clientToWeb = new NetworkClient.ClientBuilder() + .setLogger(protocolBridge.getLogger()) + .setProxy(protocolBridge.getProxy()) + .setHost(host) + .setPort(port) + .setPacketHandler(protocolBridge.getProtocolSettings().packetHandler) + .setEventManager(protocolBridge.getProtocolSettings().eventManager) + .setRootCAFolder(folderStructure.publicCAFolder) + .setClientCertificatesFolder( + folderStructure.publicClientFolder, + folderStructure.privateClientFolder + ) + .build(); + } + /** * Injects the ProtocolBridge. * @param bridge the Bridge instance. @@ -125,148 +181,293 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider { * * @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; + public final ProtocolVersion getWebServerVersion() { + return webServerVersion == null ? ProtocolVersion.PV_1_0_0_CLASSIC : webServerVersion; } /** * Sets the protocol version of the connected server. * - * @param serverVersion the ProtocolVersion to set for the server. + * @param webServerVersion the ProtocolVersion to set for the server. */ - public final void setServerVersion(ProtocolVersion serverVersion) { - if (serverVersion == null) this.serverVersion = serverVersion; + public final void setWebServerVersion(ProtocolVersion webServerVersion) { + if (webServerVersion == null) this.webServerVersion = insServerVersion; } /** - * Handles INS disconnection events, resetting the server version and closing the web client connection if necessary. + * 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 getInsServerVersion() { + return insServerVersion == null ? ProtocolVersion.PV_1_0_0_CLASSIC : insServerVersion; + } + + /** + * Sets the protocol version of the connected server. + * + * @param insServerVersion the ProtocolVersion to set for the server. + */ + public final void setInsServerVersion(ProtocolVersion insServerVersion) { + if (insServerVersion == null) this.insServerVersion = insServerVersion; + } + + /** + * Handles disconnect events, resetting the server version and closing the web client connection if necessary. * * @param event the ClientDisconnectedEvent triggered on INS disconnection. */ - public final void onINSDisconnect(ClientDisconnectedEvent event) { + public final void onDisconnect(ClientDisconnectedEvent event) { // Reset server version on INS disconnect - serverVersion = null; + if (!clientToINS.isConnected()) { + insServerVersion = null; + disconnectFromWebServer(); + } + + if (!clientToWeb.isConnected()) webServerVersion = null; } /** - * Checks if the connected server is a stable server. + * Checks if the connected insserver is a stable server. * * @return true if the server is stable, false otherwise. */ - public final boolean isStableServer() { + public final boolean isINSStableServer() { // Check if the server version is stable - return !isBetaServer() && !isClassicServer(); + return !isINSBetaServer() && !isINSClassicServer(); } /** - * Checks if the connected server or its compatible versions support stable protocol. + * Checks if the connected insserver or its compatible versions support stable protocol. * * @return true if stable protocol is supported, false otherwise. */ - public final boolean supportServerStable() { + public final boolean supportINSServerStable() { boolean yes = false; - for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { + for (ProtocolVersion compatibleVersion : getWebServerVersion().getCompatibleVersions()) { // Check if compatible version is stable yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.STABLE; if (yes) break; } // Check if the server version is stable - return isStableServer() || yes; + return isINSStableServer() || yes; } /** - * Checks if the connected server is a beta server. + * Checks if the connected insserver is a beta server. * * @return true if the server is beta, false otherwise. */ - public final boolean isBetaServer() { + public final boolean isINSBetaServer() { // Check if the server version is beta - return getServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.BETA; + return getInsServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.BETA; } /** - * Checks if the connected server or its compatible versions support beta protocol. + * Checks if the connected insserver or its compatible versions support beta protocol. * * @return true if beta protocol is supported, false otherwise. */ - public final boolean supportServerBeta() { + public final boolean supportINSServerBeta() { boolean yes = false; - for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { + for (ProtocolVersion compatibleVersion : getInsServerVersion().getCompatibleVersions()) { // Check if compatible version is beta yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.BETA; if (yes) break; } // Check if the server version is beta - return isBetaServer() || yes; + return isINSBetaServer() || yes; } /** - * Checks if the connected server is a classic server. + * Checks if the connected insserver is a classic server. * * @return true if the server is classic, false otherwise. */ - public final boolean isClassicServer() { + public final boolean isINSClassicServer() { // Check if the server version is classic - return getServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; + return getInsServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; } /** - * Checks if the connected server or its compatible versions support classic protocol. + * Checks if the connected insserver or its compatible versions support classic protocol. * * @return true if classic protocol is supported, false otherwise. */ - public final boolean supportServerClassic() { + public final boolean supportINSServerClassic() { boolean yes = false; - for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { + for (ProtocolVersion compatibleVersion : getInsServerVersion().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; + return isINSClassicServer() || yes; } /** - * Checks if the connected server supports the protocol version of the given packet. + * 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 supportServerPacket(OACPacket packet) { + public final boolean supportINSServerPacket(OACPacket packet) { // Check if the server supports the protocol version of the packet - return supportServerVersion(packet.getProtocolVersion()); + return supportINSServerVersion(packet.getProtocolVersion()); } /** - * Checks if the connected server or its compatible versions support the specified protocol version. + * 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 supportServerVersion(ProtocolVersion targetVersion) { + public final boolean supportINSServerVersion(ProtocolVersion targetVersion) { // Directly check if the server version matches or is in the list of compatible versions - return getServerVersion() == targetVersion || getServerVersion().getCompatibleVersions().contains(targetVersion); + return getInsServerVersion() == targetVersion || getInsServerVersion().getCompatibleVersions().contains(targetVersion); } /** - * Checks if the connected server or its compatible versions support the specified protocol. + * 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 supportServerProtocol(ProtocolVersion.Protocol protocol) { + public final boolean supportINSServerProtocol(ProtocolVersion.Protocol protocol) { boolean yes = false; - for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { + for (ProtocolVersion compatibleVersion : getInsServerVersion().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; + return getInsServerVersion().getSupportedProtocols().contains(protocol) || yes; + } + + //fwfwef + /** + * Checks if the connected webserver is a stable server. + * + * @return true if the server is stable, false otherwise. + */ + public final boolean isWebStableServer() { + // Check if the server version is stable + return !isWebBetaServer() && !isWebClassicServer(); + } + + /** + * Checks if the connected webserver or its compatible versions support stable protocol. + * + * @return true if stable protocol is supported, false otherwise. + */ + public final boolean supportWebServerStable() { + boolean yes = false; + for (ProtocolVersion compatibleVersion : getWebServerVersion().getCompatibleVersions()) { + // Check if compatible version is stable + yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.STABLE; + if (yes) break; + } + + // Check if the server version is stable + return isWebBetaServer() || yes; + } + + /** + * Checks if the connected webserver is a beta server. + * + * @return true if the server is beta, false otherwise. + */ + public final boolean isWebBetaServer() { + // Check if the server version is beta + return getWebServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.BETA; + } + + /** + * Checks if the connected webserver or its compatible versions support beta protocol. + * + * @return true if beta protocol is supported, false otherwise. + */ + public final boolean supportWebServerBeta() { + boolean yes = false; + for (ProtocolVersion compatibleVersion : getWebServerVersion().getCompatibleVersions()) { + // Check if compatible version is beta + yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.BETA; + if (yes) break; + } + + // Check if the server version is beta + return isWebStableServer() || yes; + } + + /** + * Checks if the connected webserver is a classic server. + * + * @return true if the server is classic, false otherwise. + */ + public final boolean isWebClassicServer() { + // Check if the server version is classic + return getWebServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; + } + + /** + * Checks if the connected webserver or its compatible versions support classic protocol. + * + * @return true if classic protocol is supported, false otherwise. + */ + public final boolean supportWebServerClassic() { + boolean yes = false; + for (ProtocolVersion compatibleVersion : getWebServerVersion().getCompatibleVersions()) { + // Check if compatible version is classic + yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; + if (yes) break; + } + + // Check if the server version is classic + return isWebClassicServer() || yes; + } + + /** + * Checks if the connected webserver 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 supportWebServerPacket(OACPacket packet) { + // Check if the server supports the protocol version of the packet + return supportWebServerVersion(packet.getProtocolVersion()); + } + + /** + * Checks if the connected webserver 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 supportWebServerVersion(ProtocolVersion targetVersion) { + // Directly check if the server version matches or is in the list of compatible versions + return getWebServerVersion() == targetVersion || getWebServerVersion().getCompatibleVersions().contains(targetVersion); + } + + /** + * Checks if the connected webserver 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 supportWebServerProtocol(ProtocolVersion.Protocol protocol) { + boolean yes = false; + for (ProtocolVersion compatibleVersion : getWebServerVersion().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 getWebServerVersion().getSupportedProtocols().contains(protocol) || yes; } /** @@ -289,6 +490,17 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider { onQuerySent(tln, name, sub, type); } + /** + * Disconnects from the WebServer. + */ + public final void disconnectFromWebServer() { + if (clientToWeb != null) { + clientToWeb.disconnect(); + clientToWeb = null; + } + } + + /** * Called when the client receives an INS response from the server. *

diff --git a/src/main/java/org/openautonomousconnection/protocol/side/client/events/ConnectedToProtocolWebServerEvent.java b/src/main/java/org/openautonomousconnection/protocol/side/client/events/ConnectedToProtocolWebServerEvent.java new file mode 100644 index 0000000..2fea6a2 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/side/client/events/ConnectedToProtocolWebServerEvent.java @@ -0,0 +1,25 @@ +package org.openautonomousconnection.protocol.side.client.events; + +import dev.unlegitdqrk.unlegitlibrary.event.impl.Event; +import lombok.Getter; +import org.openautonomousconnection.protocol.annotations.ProtocolInfo; +import org.openautonomousconnection.protocol.side.client.ProtocolClient; +import org.openautonomousconnection.protocol.versions.ProtocolVersion; + +/** + * Event triggered when a client successfully connects to a INS protocol server. + */ +@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.INS) +public final class ConnectedToProtocolWebServerEvent extends Event { + + /** + * Reference to the ProtocolClient object. + */ + @Getter + private final ProtocolClient client; + + public ConnectedToProtocolWebServerEvent(ProtocolClient client) { + this.client = 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 index 87839c9..aa0d556 100644 --- a/src/main/java/org/openautonomousconnection/protocol/side/web/ConnectedWebClient.java +++ b/src/main/java/org/openautonomousconnection/protocol/side/web/ConnectedWebClient.java @@ -1,11 +1,13 @@ package org.openautonomousconnection.protocol.side.web; import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectionHandler; -import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; import lombok.Getter; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebRequestPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebResponsePacket; +import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebStreamChunkPacket; +import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebStreamEndPacket; +import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebStreamStartPacket; import org.openautonomousconnection.protocol.versions.ProtocolVersion; import javax.net.ssl.SSLSocket; @@ -14,8 +16,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** - * A connected web client using pure OAC packets. - * No HTTP, no GET/POST, no header parsing. + * A connected web client using pure protocol packets. */ public final class ConnectedWebClient { @@ -28,13 +29,11 @@ public final class ConnectedWebClient { @Getter private ProtocolWebServer server; - /** - * The protocol version of the connected client. - */ + private ObjectOutputStream out; + private ObjectInputStream in; + private ProtocolVersion clientVersion = null; - /** - * Indicates if the client version has been loaded. - */ + @Getter private boolean clientVersionLoaded = false; @@ -44,46 +43,6 @@ public final class ConnectedWebClient { this.pipelineConnection = pipelineConnection; } - public void attachWebServer(SSLSocket socket, ProtocolWebServer server) { - if (this.webSocket != null) return; - - this.webSocket = socket; - this.server = server; - - this.receiveThread = new Thread(this::receiveLoop, "OAC-WebClient-Receiver"); - this.receiveThread.start(); - } - - private void receiveLoop() { - try { - ObjectInputStream in = new ObjectInputStream(webSocket.getInputStream()); - ObjectOutputStream out = new ObjectOutputStream(webSocket.getOutputStream()); - - PacketHandler handler = server.getProtocolBridge().getProtocolSettings().packetHandler; - - while (!webSocket.isClosed() && pipelineConnection.isConnected()) { - - Object obj = in.readObject(); - if (!(obj instanceof OACPacket packet)) continue; - - if (packet instanceof WebRequestPacket requestPacket) { - - WebResponsePacket response = - server.onWebRequest(this, requestPacket); - - if (response != null) { - out.writeObject(response); - out.flush(); - } - } - } - - } catch (Exception ignored) { - } finally { - disconnect(); - } - } - public boolean isConnected() { return webSocket != null && webSocket.isConnected() && @@ -91,25 +50,72 @@ public final class ConnectedWebClient { pipelineConnection.isConnected(); } + public void attachWebServer(SSLSocket socket, ProtocolWebServer server) throws IOException { + if (this.webSocket != null) return; + + this.webSocket = socket; + this.server = server; + + // IMPORTANT: ObjectOutputStream first, flush, then ObjectInputStream + this.out = new ObjectOutputStream(webSocket.getOutputStream()); + this.out.flush(); + this.in = new ObjectInputStream(webSocket.getInputStream()); + + this.receiveThread = new Thread(this::receiveLoop, "OAC-WebClient-Receiver"); + this.receiveThread.start(); + } + + private void receiveLoop() { + try { + while (isConnected()) { + Object obj = in.readObject(); + if (!(obj instanceof OACPacket packet)) continue; + + if (packet instanceof WebRequestPacket req) { + // server decides whether it returns normal response or does streaming itself + WebResponsePacket resp = server.onWebRequest(this, req); + if (resp != null) send(resp); + } + } + } catch (Exception ignored) { + } finally { + disconnect(); + } + } + + public synchronized void send(Object packet) throws IOException { + if (!isConnected()) return; + out.writeObject(packet); + out.flush(); + } + + public synchronized void streamStart(WebStreamStartPacket start) throws IOException { + send(start); + } + + public synchronized void streamChunk(WebStreamChunkPacket chunk) throws IOException { + send(chunk); + } + + public synchronized void streamEnd(WebStreamEndPacket end) throws IOException { + send(end); + } + public synchronized void disconnect() { - try { - server.onDisconnect(this); - clientVersionLoaded = false; - clientVersion = null; - } catch (Exception ignored) {} + try { server.onDisconnect(this); } catch (Exception ignored) {} - try { - pipelineConnection.disconnect(); - } catch (Exception ignored) {} + try { pipelineConnection.disconnect(); } catch (Exception ignored) {} - try { - if (webSocket != null) webSocket.close(); - } catch (IOException ignored) {} + try { if (in != null) in.close(); } catch (Exception ignored) {} + try { if (out != null) out.close(); } catch (Exception ignored) {} + try { if (webSocket != null) webSocket.close(); } catch (Exception ignored) {} + in = null; + out = null; webSocket = null; } - /** +/** * Gets the protocol version of the connected client. * * @return The protocol version of the client, defaults to PV_1_0_0_CLASSIC if not set. 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 a50d39b..b6427b9 100644 --- a/src/main/java/org/openautonomousconnection/protocol/side/web/ProtocolWebServer.java +++ b/src/main/java/org/openautonomousconnection/protocol/side/web/ProtocolWebServer.java @@ -10,6 +10,7 @@ import org.openautonomousconnection.protocol.ProtocolBridge; import org.openautonomousconnection.protocol.annotations.ProtocolInfo; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebRequestPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebResponsePacket; +import org.openautonomousconnection.protocol.side.web.events.WebClientConnectedEvent; import org.openautonomousconnection.protocol.side.web.managers.AuthManager; import org.openautonomousconnection.protocol.side.web.managers.RuleManager; import org.openautonomousconnection.protocol.versions.ProtocolVersion; @@ -252,6 +253,7 @@ public abstract class ProtocolWebServer { if (connectedWebClient.getPipelineConnection().getClientID() != -1 && connectedWebClient.isClientVersionLoaded()) { // Assign socket to an existing connected client connectedWebClient.attachWebServer(client, this); + protocolBridge.getProtocolSettings().eventManager.executeEvent(new WebClientConnectedEvent(connectedWebClient)); } } } catch (IOException e) { diff --git a/src/main/java/org/openautonomousconnection/protocol/side/web/events/ConnectedWebClientEvent.java b/src/main/java/org/openautonomousconnection/protocol/side/web/events/WebClientConnectedEvent.java similarity index 84% rename from src/main/java/org/openautonomousconnection/protocol/side/web/events/ConnectedWebClientEvent.java rename to src/main/java/org/openautonomousconnection/protocol/side/web/events/WebClientConnectedEvent.java index 6a2cfd4..567e0e8 100644 --- a/src/main/java/org/openautonomousconnection/protocol/side/web/events/ConnectedWebClientEvent.java +++ b/src/main/java/org/openautonomousconnection/protocol/side/web/events/WebClientConnectedEvent.java @@ -10,7 +10,7 @@ import org.openautonomousconnection.protocol.versions.ProtocolVersion; * Event triggered when a web client connects to the web server. */ @ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.WEB) -public final class ConnectedWebClientEvent extends Event { +public final class WebClientConnectedEvent extends Event { /** * The connected web client. @@ -18,7 +18,7 @@ public final class ConnectedWebClientEvent extends Event { @Getter private final ConnectedWebClient webClient; - public ConnectedWebClientEvent(ConnectedWebClient webClient) { + public WebClientConnectedEvent(ConnectedWebClient webClient) { this.webClient = webClient; } }