From 1dbfad794727ea4ac902553e87d5bc61b8802814 Mon Sep 17 00:00:00 2001 From: Finn Date: Thu, 25 Sep 2025 23:40:24 +0200 Subject: [PATCH] - Started with Web Protocol --- pom.xml | 32 ++ .../protocol/ProtocolBridge.java | 63 ++- .../UnsupportedProtocolException.java | 24 + .../protocol/listeners/ClientListener.java | 2 +- ...erListener.java => DNSServerListener.java} | 8 +- .../protocol/listeners/WebServerListener.java | 23 + .../packets/v1_0_0/beta/AuthPacket.java | 46 +- .../v1_0_0/beta/GetDestinationPacket.java | 25 +- .../v1_0_0/beta/UnsupportedClassicPacket.java | 13 +- .../v1_0_0/beta/ValidateDomainPacket.java | 16 +- .../v1_0_0/classic/Classic_DomainPacket.java | 21 +- .../v1_0_0/classic/Classic_MessagePacket.java | 13 +- .../v1_0_0/classic/Classic_PingPacket.java | 22 +- .../protocol/side/client/ProtocolClient.java | 74 ++- .../protocol/side/client/WebClient.java | 136 +++++ .../ConnectedProtocolClient.java | 28 +- .../ProtocolDNSServer.java} | 10 +- .../events/ConnectedProtocolClientEvent.java | 15 + .../events/ProtocolClientConnected.java | 15 - .../protocol/side/web/ConnectedWebClient.java | 464 ++++++++++++++++++ .../protocol/side/web/ProtocolWebServer.java | 235 +++++++++ .../web/events/ConnectedWebClientEvent.java | 15 + .../side/web/managers/AuthManager.java | 48 ++ .../side/web/managers/RuleManager.java | 40 ++ .../side/web/managers/SessionManager.java | 79 +++ .../protocol/versions/ProtocolVersion.java | 39 +- .../protocol/versions/v1_0_0/beta/Domain.java | 10 +- .../v1_0_0/classic/ClassicHandlerClient.java | 10 + .../v1_0_0/classic/ClassicHandlerServer.java | 2 +- .../classic/Classic_ClientListener.java | 2 +- 30 files changed, 1389 insertions(+), 141 deletions(-) create mode 100644 src/main/java/org/openautonomousconnection/protocol/exceptions/UnsupportedProtocolException.java rename src/main/java/org/openautonomousconnection/protocol/listeners/{ServerListener.java => DNSServerListener.java} (60%) create mode 100644 src/main/java/org/openautonomousconnection/protocol/listeners/WebServerListener.java create mode 100644 src/main/java/org/openautonomousconnection/protocol/side/client/WebClient.java rename src/main/java/org/openautonomousconnection/protocol/side/{server => dns}/ConnectedProtocolClient.java (69%) rename src/main/java/org/openautonomousconnection/protocol/side/{server/ProtocolServer.java => dns/ProtocolDNSServer.java} (92%) create mode 100644 src/main/java/org/openautonomousconnection/protocol/side/dns/events/ConnectedProtocolClientEvent.java delete mode 100644 src/main/java/org/openautonomousconnection/protocol/side/server/events/ProtocolClientConnected.java create mode 100644 src/main/java/org/openautonomousconnection/protocol/side/web/ConnectedWebClient.java create mode 100644 src/main/java/org/openautonomousconnection/protocol/side/web/ProtocolWebServer.java create mode 100644 src/main/java/org/openautonomousconnection/protocol/side/web/events/ConnectedWebClientEvent.java create mode 100644 src/main/java/org/openautonomousconnection/protocol/side/web/managers/AuthManager.java create mode 100644 src/main/java/org/openautonomousconnection/protocol/side/web/managers/RuleManager.java create mode 100644 src/main/java/org/openautonomousconnection/protocol/side/web/managers/SessionManager.java diff --git a/pom.xml b/pom.xml index a4885e0..9c7d897 100644 --- a/pom.xml +++ b/pom.xml @@ -95,5 +95,37 @@ 1.18.38 provided + + com.google.code.gson + gson + 2.13.2 + + + org.apache.commons + commons-fileupload2-jakarta-servlet6 + 2.0.0-M4 + + + org.apache.commons + commons-fileupload2 + 2.0.0-M4 + pom + + + org.apache.commons + commons-fileupload2-core + 2.0.0-M4 + + + commons-io + commons-io + 2.20.0 + + + jakarta.servlet + jakarta.servlet-api + 6.1.0 + provided + \ No newline at end of file diff --git a/src/main/java/org/openautonomousconnection/protocol/ProtocolBridge.java b/src/main/java/org/openautonomousconnection/protocol/ProtocolBridge.java index ce7af43..6666294 100644 --- a/src/main/java/org/openautonomousconnection/protocol/ProtocolBridge.java +++ b/src/main/java/org/openautonomousconnection/protocol/ProtocolBridge.java @@ -1,7 +1,8 @@ package org.openautonomousconnection.protocol; import org.openautonomousconnection.protocol.listeners.ClientListener; -import org.openautonomousconnection.protocol.listeners.ServerListener; +import org.openautonomousconnection.protocol.listeners.DNSServerListener; +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.GetDestinationPacket; @@ -9,7 +10,8 @@ import org.openautonomousconnection.protocol.packets.v1_0_0.beta.UnsupportedClas import org.openautonomousconnection.protocol.packets.v1_0_0.beta.ValidateDomainPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_DomainPacket; import org.openautonomousconnection.protocol.side.client.ProtocolClient; -import org.openautonomousconnection.protocol.side.server.ProtocolServer; +import org.openautonomousconnection.protocol.side.dns.ProtocolDNSServer; +import org.openautonomousconnection.protocol.side.web.ProtocolWebServer; import org.openautonomousconnection.protocol.versions.ProtocolVersion; import org.openautonomousconnection.protocol.versions.v1_0_0.classic.ClassicHandlerClient; import org.openautonomousconnection.protocol.versions.v1_0_0.classic.ClassicHandlerServer; @@ -33,18 +35,20 @@ public class ProtocolBridge { @Getter private final Logger logger; @Getter - private ProtocolServer protocolServer; + private ProtocolDNSServer protocolDNSServer; @Getter private ProtocolClient protocolClient; @Getter + private ProtocolWebServer protocolWebServer; + @Getter @Setter private ClassicHandlerServer classicHandlerServer; @Getter @Setter private ClassicHandlerClient classicHandlerClient; - public ProtocolBridge(ProtocolServer protocolServer, ProtocolSettings protocolSettings, ProtocolVersion protocolVersion, File logFolder) throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException { - this.protocolServer = protocolServer; + public ProtocolBridge(ProtocolDNSServer protocolDNSServer, ProtocolSettings protocolSettings, ProtocolVersion protocolVersion, File logFolder) throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException { + this.protocolDNSServer = protocolDNSServer; this.protocolSettings = protocolSettings; this.protocolVersion = protocolVersion; @@ -58,7 +62,7 @@ public class ProtocolBridge { } this.logger = tmpLogger; - protocolSettings.eventManager.registerListener(new ServerListener()); + protocolSettings.eventManager.registerListener(new DNSServerListener()); protocolSettings.eventManager.unregisterListener(new ClientListener()); if (!validateProtocolSide()) { @@ -88,7 +92,7 @@ public class ProtocolBridge { this.logger = tmpLogger; protocolSettings.eventManager.registerListener(new ClientListener()); - protocolSettings.eventManager.unregisterListener(new ServerListener()); + protocolSettings.eventManager.unregisterListener(new DNSServerListener()); if (!validateProtocolSide()) { this.logger.error("Invalid protocol version '" + protocolVersion.toString() + "'!"); @@ -126,11 +130,11 @@ public class ProtocolBridge { protocolSettings.packetHandler.registerPacket(v100bGetDestinationPacket); } - public boolean isPacketSupported(OACPacket packet) { + public final boolean isPacketSupported(OACPacket packet) { return isVersionSupported(packet.getProtocolVersion()); } - public boolean isClassicSupported() { + public final boolean isClassicSupported() { boolean yes = false; for (ProtocolVersion compatibleVersion : protocolVersion.getCompatibleVersions()) { yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; @@ -140,20 +144,47 @@ public class ProtocolBridge { return protocolVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC || yes; } - public boolean isRunningAsServer() { - return protocolServer != null; + public final boolean isProtocolSupported(ProtocolVersion.Protocol protocol) { + boolean yes = false; + for (ProtocolVersion compatibleVersion : protocolVersion.getCompatibleVersions()) { + yes = compatibleVersion.getSupportedProtocols().contains(protocol); + if (yes) break; + } + + return protocolVersion.getSupportedProtocols().contains(protocol) || yes; } - public boolean isRunningAsClient() { + public final boolean isRunningAsDNSServer() { + return protocolDNSServer != null; + } + + public final boolean isRunningAsClient() { return protocolClient != null; } - private boolean validateProtocolSide() { - return (isRunningAsServer() && protocolVersion.getProtocolSide() != ProtocolVersion.ProtocolSide.CLIENT) || - (isRunningAsClient() && protocolVersion.getProtocolSide() != ProtocolVersion.ProtocolSide.SERVER); + public final boolean isRunningAsWebServer() { + return protocolWebServer != null; } - public boolean isVersionSupported(ProtocolVersion targetVersion) { + private boolean validateProtocolSide() { + return + (isRunningAsClient() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT) || + (isRunningAsClient() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_WEB) || + (isRunningAsClient() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_DNS) || + (isRunningAsClient() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL) || + + (isRunningAsWebServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.WEB) || + (isRunningAsWebServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_WEB) || + (isRunningAsWebServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.WEB_DNS) || + (isRunningAsWebServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL) || + + (isRunningAsDNSServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.DNS) || + (isRunningAsDNSServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.WEB_DNS) || + (isRunningAsDNSServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_DNS) || + (isRunningAsDNSServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL); + } + + public final boolean isVersionSupported(ProtocolVersion targetVersion) { return protocolVersion == targetVersion || protocolVersion.getCompatibleVersions().contains(targetVersion); } } diff --git a/src/main/java/org/openautonomousconnection/protocol/exceptions/UnsupportedProtocolException.java b/src/main/java/org/openautonomousconnection/protocol/exceptions/UnsupportedProtocolException.java new file mode 100644 index 0000000..427f89a --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/exceptions/UnsupportedProtocolException.java @@ -0,0 +1,24 @@ +package org.openautonomousconnection.protocol.exceptions; + +public class UnsupportedProtocolException extends RuntimeException { + + public UnsupportedProtocolException() { + this("Selected protocol is not supported!"); + } + + public UnsupportedProtocolException(String message) { + super(message); + } + + public UnsupportedProtocolException(String message, Throwable cause) { + super(message, cause); + } + + public UnsupportedProtocolException(Throwable cause) { + super(cause); + } + + public UnsupportedProtocolException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/src/main/java/org/openautonomousconnection/protocol/listeners/ClientListener.java b/src/main/java/org/openautonomousconnection/protocol/listeners/ClientListener.java index 34a3dd3..9e3226d 100644 --- a/src/main/java/org/openautonomousconnection/protocol/listeners/ClientListener.java +++ b/src/main/java/org/openautonomousconnection/protocol/listeners/ClientListener.java @@ -23,7 +23,7 @@ public class ClientListener extends EventListener { @Listener public void onDisconnect(ClientDisconnectedEvent event) { - ProtocolBridge.getInstance().getProtocolClient().onDisconnect(event); + ProtocolBridge.getInstance().getProtocolClient().onDNSDisconnect(event); } } diff --git a/src/main/java/org/openautonomousconnection/protocol/listeners/ServerListener.java b/src/main/java/org/openautonomousconnection/protocol/listeners/DNSServerListener.java similarity index 60% rename from src/main/java/org/openautonomousconnection/protocol/listeners/ServerListener.java rename to src/main/java/org/openautonomousconnection/protocol/listeners/DNSServerListener.java index ae3072f..48f6930 100644 --- a/src/main/java/org/openautonomousconnection/protocol/listeners/ServerListener.java +++ b/src/main/java/org/openautonomousconnection/protocol/listeners/DNSServerListener.java @@ -1,22 +1,22 @@ package org.openautonomousconnection.protocol.listeners; import org.openautonomousconnection.protocol.ProtocolBridge; -import org.openautonomousconnection.protocol.side.server.ConnectedProtocolClient; +import org.openautonomousconnection.protocol.side.dns.ConnectedProtocolClient; import dev.unlegitdqrk.unlegitlibrary.event.EventListener; import dev.unlegitdqrk.unlegitlibrary.event.Listener; import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.ConnectionHandlerConnectedEvent; import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.ConnectionHandlerDisconnectedEvent; -public class ServerListener extends EventListener { +public class DNSServerListener extends EventListener { @Listener public void onConnect(ConnectionHandlerConnectedEvent event) { - ProtocolBridge.getInstance().getProtocolServer().getClients().add(new ConnectedProtocolClient(event.connectionHandler)); + ProtocolBridge.getInstance().getProtocolDNSServer().getClients().add(new ConnectedProtocolClient(event.connectionHandler)); } @Listener public void onDisconnect(ConnectionHandlerDisconnectedEvent event) { - ProtocolBridge.getInstance().getProtocolServer().getClients().removeIf(client -> client.getConnectionHandler().getClientID() == -1); + ProtocolBridge.getInstance().getProtocolDNSServer().getClients().removeIf(client -> client.getConnectionHandler().getClientID() == -1); } } diff --git a/src/main/java/org/openautonomousconnection/protocol/listeners/WebServerListener.java b/src/main/java/org/openautonomousconnection/protocol/listeners/WebServerListener.java new file mode 100644 index 0000000..07ceec3 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/listeners/WebServerListener.java @@ -0,0 +1,23 @@ +package org.openautonomousconnection.protocol.listeners; + +import dev.unlegitdqrk.unlegitlibrary.event.EventListener; +import dev.unlegitdqrk.unlegitlibrary.event.Listener; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.ConnectionHandlerConnectedEvent; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.ConnectionHandlerDisconnectedEvent; +import org.openautonomousconnection.protocol.ProtocolBridge; +import org.openautonomousconnection.protocol.side.dns.ConnectedProtocolClient; +import org.openautonomousconnection.protocol.side.web.ConnectedWebClient; + +public class WebServerListener extends EventListener { + + @Listener + public void onConnect(ConnectionHandlerConnectedEvent event) { + ProtocolBridge.getInstance().getProtocolWebServer().getClients().add(new ConnectedWebClient(event.connectionHandler)); + } + + @Listener + public void onDisconnect(ConnectionHandlerDisconnectedEvent event) { + ProtocolBridge.getInstance().getProtocolWebServer().getClients().removeIf(client -> client.getPipelineConnection().getClientID() == -1); + } + +} \ No newline at end of file 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 572527e..7a95064 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 @@ -3,8 +3,10 @@ package org.openautonomousconnection.protocol.packets.v1_0_0.beta; import org.openautonomousconnection.protocol.ProtocolBridge; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.side.client.events.ConnectedToProtocolServer; -import org.openautonomousconnection.protocol.side.server.ConnectedProtocolClient; -import org.openautonomousconnection.protocol.side.server.events.ProtocolClientConnected; +import org.openautonomousconnection.protocol.side.dns.ConnectedProtocolClient; +import org.openautonomousconnection.protocol.side.dns.events.ConnectedProtocolClientEvent; +import org.openautonomousconnection.protocol.side.web.ConnectedWebClient; +import org.openautonomousconnection.protocol.side.web.events.ConnectedWebClientEvent; import org.openautonomousconnection.protocol.versions.ProtocolVersion; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode; import dev.unlegitdqrk.unlegitlibrary.file.FileUtils; @@ -19,6 +21,7 @@ import java.io.ObjectOutputStream; public class AuthPacket extends OACPacket { + // Registration Constructor public AuthPacket() { super(4, ProtocolVersion.PV_1_0_0_BETA); } @@ -36,7 +39,7 @@ public class AuthPacket extends OACPacket { @Override public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException { - if (ProtocolBridge.getInstance().isRunningAsServer()) { + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) { objectOutputStream.writeObject(ProtocolBridge.getInstance().getProtocolVersion()); // Read ca files @@ -44,19 +47,19 @@ public class AuthPacket extends OACPacket { String caPem = "N/A"; String caSrl = "N/A"; try { - objectOutputStream.writeUTF(ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress()); + objectOutputStream.writeUTF(ProtocolBridge.getInstance().getProtocolDNSServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress()); caKey = FileUtils.readFileFull(new File( - ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().privateCAFolder, - ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress() + ".key")); + ProtocolBridge.getInstance().getProtocolDNSServer().getFolderStructure().privateCAFolder, + ProtocolBridge.getInstance().getProtocolDNSServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress() + ".key")); caPem = FileUtils.readFileFull(new File( - ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().publicCAFolder, - ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress() + ".pem")); + ProtocolBridge.getInstance().getProtocolDNSServer().getFolderStructure().publicCAFolder, + ProtocolBridge.getInstance().getProtocolDNSServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress() + ".pem")); caSrl = FileUtils.readFileFull(new File( - ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().publicCAFolder, - ProtocolBridge.getInstance().getProtocolServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress() + ".srl")); + ProtocolBridge.getInstance().getProtocolDNSServer().getFolderStructure().publicCAFolder, + ProtocolBridge.getInstance().getProtocolDNSServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress() + ".srl")); } catch (Exception exception) { ProtocolBridge.getInstance().getLogger().exception("Failed to read ca-files", exception); setResponseCode(DNSResponseCode.RESPONSE_AUTH_FAILED); @@ -66,18 +69,18 @@ public class AuthPacket extends OACPacket { objectOutputStream.writeUTF(caKey); objectOutputStream.writeUTF(caPem); objectOutputStream.writeUTF(caSrl); - } else { - objectOutputStream.writeInt(ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().getClientID()); + } else if (ProtocolBridge.getInstance().isRunningAsClient()) { + objectOutputStream.writeInt(ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getClientID()); objectOutputStream.writeObject(ProtocolBridge.getInstance().getProtocolVersion()); } } @Override public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { - if (ProtocolBridge.getInstance().isRunningAsServer()) { + if (ProtocolBridge.getInstance().isRunningAsDNSServer() || ProtocolBridge.getInstance().isRunningAsWebServer()) { int clientID = objectInputStream.readInt(); ProtocolVersion clientVersion = (ProtocolVersion) objectInputStream.readObject(); - ConnectionHandler connectionHandler = ProtocolBridge.getInstance().getProtocolServer().getNetworkServer().getConnectionHandlerByID(clientID); + ConnectionHandler connectionHandler = ProtocolBridge.getInstance().getProtocolDNSServer().getNetworkServer().getConnectionHandlerByID(clientID); if (!ProtocolBridge.getInstance().isVersionSupported(clientVersion)) { setResponseCode(DNSResponseCode.RESPONSE_AUTH_FAILED); @@ -86,15 +89,20 @@ public class AuthPacket extends OACPacket { } else setResponseCode(DNSResponseCode.RESPONSE_AUTH_SUCCESS); - ConnectedProtocolClient client = ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID); - client.setClientVersion(clientVersion); - ProtocolBridge.getInstance().getProtocolSettings().eventManager.executeEvent(new ProtocolClientConnected(client)); - } else { + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) { + ConnectedProtocolClient client = ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID); + client.setClientVersion(clientVersion); + ProtocolBridge.getInstance().getProtocolSettings().eventManager.executeEvent(new ConnectedProtocolClientEvent(client)); + } else { + ConnectedWebClient client = ProtocolBridge.getInstance().getProtocolWebServer().getClientByID(clientID); + client.setClientVersion(clientVersion); + } + } else if (ProtocolBridge.getInstance().isRunningAsClient()) { ProtocolVersion serverVersion = (ProtocolVersion) objectInputStream.readObject(); if (!ProtocolBridge.getInstance().isVersionSupported(serverVersion)) { setResponseCode(DNSResponseCode.RESPONSE_AUTH_FAILED); - ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().disconnect(); + ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().disconnect(); return; } else setResponseCode(DNSResponseCode.RESPONSE_AUTH_SUCCESS); diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/GetDestinationPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/GetDestinationPacket.java index 226f29b..e450886 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/GetDestinationPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/GetDestinationPacket.java @@ -17,6 +17,7 @@ public class GetDestinationPacket extends OACPacket { private DNSResponseCode validationResponse; private String destination; + // DNS-Server Constructor public GetDestinationPacket(Domain domain, DNSResponseCode validationResponse, String destination) { this(); this.domain = domain; @@ -24,6 +25,15 @@ public class GetDestinationPacket extends OACPacket { this.destination = destination; } + // Client Constructor + public GetDestinationPacket(Domain domain, DNSResponseCode validationResponse) { + this(); + this.domain = domain; + this.validationResponse = validationResponse; + this.destination = destination; + } + + // Registration Constructor public GetDestinationPacket() { super(6, ProtocolVersion.PV_1_0_0_BETA); } @@ -33,10 +43,10 @@ public class GetDestinationPacket extends OACPacket { if (ProtocolBridge.getInstance().isRunningAsClient()) { if (validationResponse != DNSResponseCode.RESPONSE_DOMAIN_FULLY_EXIST) return; - objectOutputStream.writeInt(ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().getClientID()); + objectOutputStream.writeInt(ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getClientID()); objectOutputStream.writeObject(domain); objectOutputStream.writeObject(validationResponse); - } else { + } else if (ProtocolBridge.getInstance().isRunningAsDNSServer()) { objectOutputStream.writeObject(domain); objectOutputStream.writeObject(validationResponse); objectOutputStream.writeUTF(destination); @@ -45,11 +55,11 @@ public class GetDestinationPacket extends OACPacket { @Override public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { - if (ProtocolBridge.getInstance().isRunningAsServer()) { + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) { clientID = objectInputStream.readInt(); domain = (Domain) objectInputStream.readObject(); validationResponse = (DNSResponseCode) objectInputStream.readObject(); - } else { + } else if (ProtocolBridge.getInstance().isRunningAsClient()) { domain = (Domain) objectInputStream.readObject(); validationResponse = (DNSResponseCode) objectInputStream.readObject(); destination = objectInputStream.readUTF(); @@ -62,13 +72,14 @@ public class GetDestinationPacket extends OACPacket { protected void onResponseCodeRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) { super.onResponseCodeRead(packetHandler, objectInputStream); - if (ProtocolBridge.getInstance().isRunningAsServer()) { + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) { if (validationResponse != DNSResponseCode.RESPONSE_DOMAIN_FULLY_EXIST) return; destination = domain.getDestination(); + try { - ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID).getConnectionHandler().sendPacket(new GetDestinationPacket(domain, validationResponse, destination)); + ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID).getConnectionHandler().sendPacket(new GetDestinationPacket(domain, validationResponse, destination)); } catch (IOException | ClassNotFoundException exception) { - ProtocolBridge.getInstance().getProtocolServer().getDomainDestinationFailed(ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID), domain, validationResponse, exception); + ProtocolBridge.getInstance().getProtocolDNSServer().domainDestinationPacketFailedSend(ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID), domain, validationResponse, exception); } } } diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/UnsupportedClassicPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/UnsupportedClassicPacket.java index 9a02a08..497e136 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/UnsupportedClassicPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/UnsupportedClassicPacket.java @@ -14,12 +14,14 @@ public class UnsupportedClassicPacket extends OACPacket { private Class unsupportedClassicPacket; private Object[] content; + // Constructor with more information public UnsupportedClassicPacket(Class unsupportedClassicPacket, Object[] content) { this(); this.unsupportedClassicPacket = unsupportedClassicPacket; this.content = content; } + // Registration Constructor public UnsupportedClassicPacket() { super(5, ProtocolVersion.PV_1_0_0_BETA); } @@ -27,7 +29,8 @@ public class UnsupportedClassicPacket extends OACPacket { @Override public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException { if (ProtocolBridge.getInstance().isRunningAsClient()) - objectOutputStream.writeInt(ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().getClientID()); + objectOutputStream.writeInt(ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getClientID()); + objectOutputStream.writeUTF(unsupportedClassicPacket.getName()); objectOutputStream.writeInt(content.length); for (Object o : content) objectOutputStream.writeObject(o); @@ -37,7 +40,7 @@ public class UnsupportedClassicPacket extends OACPacket { @Override public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { int clientID = 0; - if (ProtocolBridge.getInstance().isRunningAsServer()) clientID = objectInputStream.readInt(); + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) clientID = objectInputStream.readInt(); String className = objectInputStream.readUTF(); int size = objectInputStream.readInt(); content = new Object[size]; @@ -46,8 +49,8 @@ public class UnsupportedClassicPacket extends OACPacket { content[i] = objectInputStream.readObject(); } - if (ProtocolBridge.getInstance().isRunningAsServer()) - ProtocolBridge.getInstance().getClassicHandlerServer().unsupportedClassicPacket(className, content, ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID)); - else ProtocolBridge.getInstance().getClassicHandlerClient().unsupportedClassicPacket(className, content); + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) + ProtocolBridge.getInstance().getClassicHandlerServer().unsupportedClassicPacket(className, content, ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID)); + else if (ProtocolBridge.getInstance().isRunningAsClient()) ProtocolBridge.getInstance().getClassicHandlerClient().unsupportedClassicPacket(className, content); } } diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/ValidateDomainPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/ValidateDomainPacket.java index 85f4289..297dd0b 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/ValidateDomainPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/beta/ValidateDomainPacket.java @@ -26,15 +26,15 @@ public class ValidateDomainPacket extends OACPacket { @Override public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException { if (ProtocolBridge.getInstance().isRunningAsClient()) - objectOutputStream.writeInt(ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().getClientID()); - else setResponseCode(ProtocolBridge.getInstance().getProtocolServer().validateDomain(domain)); + objectOutputStream.writeInt(ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getClientID()); + else if (ProtocolBridge.getInstance().isRunningAsDNSServer()) setResponseCode(ProtocolBridge.getInstance().getProtocolDNSServer().validateDomain(domain)); objectOutputStream.writeObject(domain); } @Override public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { - if (ProtocolBridge.getInstance().isRunningAsServer()) clientID = objectInputStream.readInt(); + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) clientID = objectInputStream.readInt(); domain = (Domain) objectInputStream.readObject(); } @@ -42,16 +42,14 @@ public class ValidateDomainPacket extends OACPacket { protected void onResponseCodeRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) { super.onResponseCodeRead(packetHandler, objectInputStream); - if (ProtocolBridge.getInstance().isRunningAsServer()) { + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) { try { - ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID).getConnectionHandler().sendPacket(new ValidateDomainPacket(domain)); + ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID).getConnectionHandler().sendPacket(new ValidateDomainPacket(domain)); } catch (IOException | ClassNotFoundException e) { - ProtocolBridge.getInstance().getProtocolServer().validationFailed(domain, ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID), e); + ProtocolBridge.getInstance().getProtocolDNSServer().validationPacketSendFailed(domain, ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID), e); } return; - } - - ProtocolBridge.getInstance().getProtocolClient().validationCompleted(domain, getResponseCode()); + } else if (ProtocolBridge.getInstance().isRunningAsClient()) ProtocolBridge.getInstance().getProtocolClient().validationCompleted(domain, getResponseCode()); } } diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/classic/Classic_DomainPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/classic/Classic_DomainPacket.java index de05797..aeb788d 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/classic/Classic_DomainPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/classic/Classic_DomainPacket.java @@ -28,18 +28,19 @@ public class Classic_DomainPacket extends OACPacket { this.domain = domain; } + // Registration constructor public Classic_DomainPacket() { super(2, ProtocolVersion.PV_1_0_0_CLASSIC); } @Override public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException { - if (ProtocolBridge.getInstance().isRunningAsServer()) { + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) { objectOutputStream.writeInt(clientID); objectOutputStream.writeObject(requestDomain); objectOutputStream.writeObject(domain); - } else { - clientID = ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().getClientID(); + } else if (ProtocolBridge.getInstance().isRunningAsClient()) { + clientID = ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getClientID(); objectOutputStream.writeInt(clientID); objectOutputStream.writeObject(requestDomain); } @@ -49,7 +50,7 @@ public class Classic_DomainPacket extends OACPacket { @Override public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { - if (ProtocolBridge.getInstance().isRunningAsServer()) { + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) { clientID = objectInputStream.readInt(); requestDomain = (Classic_RequestDomain) objectInputStream.readObject(); Classic_ProtocolVersion protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject(); @@ -60,19 +61,19 @@ public class Classic_DomainPacket extends OACPacket { exception.printStackTrace(); } - ProtocolBridge.getInstance().getProtocolServer().getNetworkServer().getEventManager().executeEvent(new Classic_DomainPacketReceivedEvent(protocolVersion, domain, requestDomain, clientID)); + ProtocolBridge.getInstance().getProtocolDNSServer().getNetworkServer().getEventManager().executeEvent(new Classic_DomainPacketReceivedEvent(protocolVersion, domain, requestDomain, clientID)); - if (ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID).clientSupportClassic()) - ProtocolBridge.getInstance().getProtocolServer().getNetworkServer().getConnectionHandlerByID(clientID).sendPacket(new Classic_DomainPacket(clientID, requestDomain, domain)); + if (ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID).supportClientClassic()) + ProtocolBridge.getInstance().getProtocolDNSServer().getNetworkServer().getConnectionHandlerByID(clientID).sendPacket(new Classic_DomainPacket(clientID, requestDomain, domain)); else - ProtocolBridge.getInstance().getProtocolServer().getNetworkServer().getConnectionHandlerByID(clientID).sendPacket(new UnsupportedClassicPacket(Classic_PingPacket.class, new Object[]{clientID, requestDomain, domain})); - } else { + ProtocolBridge.getInstance().getProtocolDNSServer().getNetworkServer().getConnectionHandlerByID(clientID).sendPacket(new UnsupportedClassicPacket(Classic_PingPacket.class, new Object[]{clientID, requestDomain, domain})); + } else if (ProtocolBridge.getInstance().isRunningAsClient()) { clientID = objectInputStream.readInt(); requestDomain = (Classic_RequestDomain) objectInputStream.readObject(); domain = (Classic_Domain) objectInputStream.readObject(); Classic_ProtocolVersion protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject(); - ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().getEventManager().executeEvent(new Classic_DomainPacketReceivedEvent(protocolVersion, domain, requestDomain, clientID)); + ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getEventManager().executeEvent(new Classic_DomainPacketReceivedEvent(protocolVersion, domain, requestDomain, clientID)); } } } diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/classic/Classic_MessagePacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/classic/Classic_MessagePacket.java index 54ff343..06b91e6 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/classic/Classic_MessagePacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/classic/Classic_MessagePacket.java @@ -14,6 +14,7 @@ public class Classic_MessagePacket extends OACPacket { private String message; private int clientID; + // Constructor with message and client id public Classic_MessagePacket(String message, int toClient) { this(); this.message = message; @@ -26,9 +27,9 @@ public class Classic_MessagePacket extends OACPacket { @Override public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException { - if (ProtocolBridge.getInstance().isRunningAsServer()) objectOutputStream.writeInt(clientID); - else { - clientID = ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().getClientID(); + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) objectOutputStream.writeInt(clientID); + else if (ProtocolBridge.getInstance().isRunningAsClient()) { + clientID = ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getClientID(); objectOutputStream.writeInt(clientID); } @@ -38,13 +39,13 @@ public class Classic_MessagePacket extends OACPacket { @Override public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { - if (ProtocolBridge.getInstance().isRunningAsServer()) { + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) { clientID = objectInputStream.readInt(); String message = objectInputStream.readUTF(); Classic_ProtocolVersion protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject(); - ProtocolBridge.getInstance().getClassicHandlerServer().handleMessage(ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID), message, protocolVersion); - } else { + ProtocolBridge.getInstance().getClassicHandlerServer().handleMessage(ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID), message, protocolVersion); + } else if (ProtocolBridge.getInstance().isRunningAsClient()) { clientID = objectInputStream.readInt(); String message = objectInputStream.readUTF(); Classic_ProtocolVersion protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject(); diff --git a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/classic/Classic_PingPacket.java b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/classic/Classic_PingPacket.java index d1cd609..1a967c0 100644 --- a/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/classic/Classic_PingPacket.java +++ b/src/main/java/org/openautonomousconnection/protocol/packets/v1_0_0/classic/Classic_PingPacket.java @@ -4,6 +4,7 @@ import org.openautonomousconnection.protocol.ProtocolBridge; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.UnsupportedClassicPacket; import org.openautonomousconnection.protocol.versions.ProtocolVersion; +import org.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode; import org.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_Domain; import org.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_PingPacketReceivedEvent; import org.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_ProtocolVersion; @@ -37,13 +38,13 @@ public class Classic_PingPacket extends OACPacket { @Override public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException { - if (ProtocolBridge.getInstance().isRunningAsServer()) { + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) { objectOutputStream.writeInt(clientID); objectOutputStream.writeObject(requestDomain); objectOutputStream.writeObject(domain); objectOutputStream.writeBoolean(reachable); - } else { - clientID = ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().getClientID(); + } else if (ProtocolBridge.getInstance().isRunningAsClient()) { + clientID = ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getClientID(); objectOutputStream.writeInt(clientID); objectOutputStream.writeObject(requestDomain); } @@ -53,7 +54,7 @@ public class Classic_PingPacket extends OACPacket { @Override public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { - if (ProtocolBridge.getInstance().isRunningAsServer()) { + if (ProtocolBridge.getInstance().isRunningAsDNSServer()) { clientID = objectInputStream.readInt(); requestDomain = (Classic_RequestDomain) objectInputStream.readObject(); protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject(); @@ -65,19 +66,20 @@ public class Classic_PingPacket extends OACPacket { } reachable = domain != null; - ProtocolBridge.getInstance().getProtocolServer().getNetworkServer().getEventManager().executeEvent(new Classic_PingPacketReceivedEvent(protocolVersion, domain, requestDomain, reachable, clientID)); - if (ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID).clientSupportClassic()) - ProtocolBridge.getInstance().getProtocolServer().getNetworkServer().getConnectionHandlerByID(clientID).sendPacket(new Classic_PingPacket(requestDomain, domain, reachable)); + ProtocolBridge.getInstance().getProtocolDNSServer().getNetworkServer().getEventManager().executeEvent(new Classic_PingPacketReceivedEvent(protocolVersion, domain, requestDomain, reachable, clientID)); + if (ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID).supportClientClassic()) + ProtocolBridge.getInstance().getProtocolDNSServer().getNetworkServer().getConnectionHandlerByID(clientID).sendPacket(new Classic_PingPacket(requestDomain, domain, reachable)); else - ProtocolBridge.getInstance().getProtocolServer().getNetworkServer().getConnectionHandlerByID(clientID).sendPacket(new UnsupportedClassicPacket(Classic_PingPacket.class, new Object[]{requestDomain, domain, reachable})); - } else { + ProtocolBridge.getInstance().getProtocolDNSServer().getNetworkServer().getConnectionHandlerByID(clientID).sendPacket(new UnsupportedClassicPacket(Classic_PingPacket.class, new Object[]{requestDomain, domain, reachable})); + } else if (ProtocolBridge.getInstance().isRunningAsClient()) { clientID = objectInputStream.readInt(); requestDomain = (Classic_RequestDomain) objectInputStream.readObject(); domain = (Classic_Domain) objectInputStream.readObject(); boolean reachable = objectInputStream.readBoolean(); Classic_ProtocolVersion protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject(); - ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().getEventManager().executeEvent(new Classic_PingPacketReceivedEvent(protocolVersion, domain, requestDomain, reachable, clientID)); + ProtocolBridge.getInstance().getProtocolClient().validationCompleted(domain.getDomain(), reachable ? DNSResponseCode.RESPONSE_DOMAIN_FULLY_EXIST : DNSResponseCode.RESPONSE_DOMAIN_FULLY_NOT_EXIST); + ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getEventManager().executeEvent(new Classic_PingPacketReceivedEvent(protocolVersion, domain, requestDomain, reachable, clientID)); } } } 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 1d6937b..f9a9e6f 100644 --- a/src/main/java/org/openautonomousconnection/protocol/side/client/ProtocolClient.java +++ b/src/main/java/org/openautonomousconnection/protocol/side/client/ProtocolClient.java @@ -1,8 +1,12 @@ package org.openautonomousconnection.protocol.side.client; import org.openautonomousconnection.protocol.ProtocolBridge; +import org.openautonomousconnection.protocol.exceptions.UnsupportedProtocolException; import org.openautonomousconnection.protocol.packets.OACPacket; +import org.openautonomousconnection.protocol.packets.v1_0_0.beta.GetDestinationPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.ValidateDomainPacket; +import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_DomainPacket; +import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_PingPacket; import org.openautonomousconnection.protocol.versions.ProtocolVersion; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain; @@ -11,10 +15,14 @@ import dev.unlegitdqrk.unlegitlibrary.network.system.client.NetworkClient; import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.ClientDisconnectedEvent; import dev.unlegitdqrk.unlegitlibrary.network.utils.NetworkUtils; import dev.unlegitdqrk.unlegitlibrary.utils.DefaultMethodsOverrider; +import org.openautonomousconnection.protocol.versions.v1_0_0.classic.ClassicConverter; +import org.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_Domain; +import org.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_RequestDomain; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.net.ConnectException; import java.security.cert.CertificateException; public abstract class ProtocolClient extends DefaultMethodsOverrider { @@ -55,22 +63,41 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider { } } - @Getter - private final NetworkClient networkClient; + private final NetworkClient clientToDNS; // Handles everything with DNS-Connection + private WebClient webClient; + private ProtocolVersion serverVersion = null; @Getter private final ClientCertificateFolderStructure folderStructure; + public final NetworkClient getClientDNSConnection() { + return clientToDNS; + } + public ProtocolClient() throws CertificateException, IOException { folderStructure = new ClientCertificateFolderStructure(); - networkClient = new NetworkClient.ClientBuilder().setLogger(ProtocolBridge.getInstance().getLogger()). + clientToDNS = new NetworkClient.ClientBuilder().setLogger(ProtocolBridge.getInstance().getLogger()). setHost(ProtocolBridge.getInstance().getProtocolSettings().host).setPort(ProtocolBridge.getInstance().getProtocolSettings().port). setPacketHandler(ProtocolBridge.getInstance().getProtocolSettings().packetHandler).setEventManager(ProtocolBridge.getInstance().getProtocolSettings().eventManager). setRootCAFolder(folderStructure.publicCAFolder).setClientCertificatesFolder(folderStructure.publicClientFolder, folderStructure.privateClientFolder). build(); } + public final void createWebConnection(Domain domain, int pipelinePort, int webPort) throws Exception { + if (!ProtocolBridge.getInstance().isProtocolSupported(ProtocolVersion.Protocol.OAC)) throw new UnsupportedProtocolException(); + + if (webClient != null) { + try { + webClient.closeConnection(); + } catch (IOException e) { + ProtocolBridge.getInstance().getLogger().exception("Failed to close connection to web server", e); + } + } + + webClient = new WebClient(domain, pipelinePort, webPort); + } + private final void checkFileExists(File folder, String prefix, String extension) throws CertificateException, IOException { boolean found = false; if (folder == null) throw new FileNotFoundException("Folder does not exist"); @@ -94,15 +121,22 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider { if (serverVersion == null) this.serverVersion = serverVersion; } - public final void onDisconnect(ClientDisconnectedEvent event) { + public final void onDNSDisconnect(ClientDisconnectedEvent event) { serverVersion = null; + if (webClient != null) { + try { + webClient.closeConnection(); + } catch (IOException e) { + ProtocolBridge.getInstance().getLogger().exception("Failed to close connection to web server", e); + } + } } public final boolean isStableServer() { return !isBetaServer() && !isClassicServer(); } - public final boolean serverSupportStable() { + public final boolean supportServerStable() { boolean yes = false; for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.STABLE; @@ -116,7 +150,7 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider { return getServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.BETA; } - public final boolean serverSupportBeta() { + public final boolean supportServerBeta() { boolean yes = false; for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.BETA; @@ -130,7 +164,7 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider { return getServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; } - public final boolean serverSupportClassic() { + public final boolean supportServerClassic() { boolean yes = false; for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; @@ -140,16 +174,34 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider { return isClassicServer() || yes; } - public final boolean isPacketSupported(OACPacket packet) { - return isVersionSupported(packet.getProtocolVersion()); + public final boolean supportServerPacket(OACPacket packet) { + return supportServerVersion(packet.getProtocolVersion()); } - public final boolean isVersionSupported(ProtocolVersion targetVersion) { + public final boolean supportServerVersion(ProtocolVersion targetVersion) { return getServerVersion() == targetVersion || getServerVersion().getCompatibleVersions().contains(targetVersion); } + public final boolean supportServerProtocol(ProtocolVersion.Protocol protocol) { + boolean yes = false; + for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) { + yes = compatibleVersion.getSupportedProtocols().contains(protocol); + if (yes) break; + } + + return getServerVersion().getSupportedProtocols().contains(protocol) || yes; + } + public final void validateDomain(Domain domain) throws IOException, ClassNotFoundException { - networkClient.sendPacket(new ValidateDomainPacket(domain)); + Classic_PingPacket cPingPacket = new Classic_PingPacket(new Classic_RequestDomain(domain.getName(), domain.getTopLevelName(), domain.getPath()), null, false); + if (ProtocolBridge.getInstance().isPacketSupported(cPingPacket)) clientToDNS.sendPacket(cPingPacket); + clientToDNS.sendPacket(new ValidateDomainPacket(domain)); + } + + public final void requestDestination(Domain domain, DNSResponseCode responseCode) throws IOException, ClassNotFoundException { + Classic_DomainPacket cDomainPacket = new Classic_DomainPacket(0, new Classic_RequestDomain(domain.getName(), domain.getTopLevelName(), domain.getPath()), null); + if (ProtocolBridge.getInstance().isPacketSupported(cDomainPacket)) clientToDNS.sendPacket(cDomainPacket); + clientToDNS.sendPacket(new GetDestinationPacket(domain, responseCode)); } public abstract void validationCompleted(Domain domain, DNSResponseCode responseCode); diff --git a/src/main/java/org/openautonomousconnection/protocol/side/client/WebClient.java b/src/main/java/org/openautonomousconnection/protocol/side/client/WebClient.java new file mode 100644 index 0000000..fea7d43 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/side/client/WebClient.java @@ -0,0 +1,136 @@ +package org.openautonomousconnection.protocol.side.client; + +import dev.unlegitdqrk.unlegitlibrary.network.system.client.NetworkClient; +import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.*; +import dev.unlegitdqrk.unlegitlibrary.network.system.packets.Packet; +import lombok.Getter; +import org.openautonomousconnection.protocol.ProtocolBridge; +import org.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain; + +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.ConnectException; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; + +public final class WebClient { + private final NetworkClient clientToWebPipeline; // Handles everything with Pipeline-Connection + private SSLSocket clientToWebServer; // Handles everything with Web-Connection + + private final Thread receiveThread = new Thread(this::receive); + private ObjectOutputStream outputStream; + private ObjectInputStream inputStream; + + public final NetworkClient getClientPipelineConnection() { + return clientToWebPipeline; + } + + public final SSLSocket getClientWebConnection() { + return clientToWebServer; + } + + public WebClient(Domain domain, int pipelinePort, int webPort) throws Exception { + clientToWebPipeline = new NetworkClient.ClientBuilder().setLogger(ProtocolBridge.getInstance().getLogger()). + setHost(domain.getDestination()).setPort(pipelinePort). + setPacketHandler(ProtocolBridge.getInstance().getProtocolSettings().packetHandler).setEventManager(ProtocolBridge.getInstance().getProtocolSettings().eventManager). + setRootCAFolder(ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().publicCAFolder).setClientCertificatesFolder(ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().publicClientFolder, ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().privateClientFolder). + build(); + + clientToWebPipeline.connect(); + + while (!clientToWebPipeline.isConnected()) if (clientToWebPipeline.isConnected()) break; + + SSLSocketFactory sslSocketFactory = NetworkClient.ClientBuilder.createSSLSocketFactory(ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().publicCAFolder, ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().publicClientFolder, ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().privateClientFolder); + Proxy proxy = clientToWebPipeline.getProxy(); + SSLSocket tempSocket; + if (sslSocketFactory == null) { + throw new ConnectException("SSL socket factory not set. Client certificate required!"); + } else { + if (proxy != null) { + Socket rawSocket = new Socket(proxy); + rawSocket.connect(new InetSocketAddress(domain.getDestination(), webPort), 0); + tempSocket = (SSLSocket)sslSocketFactory.createSocket(rawSocket, domain.getDestination(), webPort, true); + } else { + tempSocket = (SSLSocket)sslSocketFactory.createSocket(domain.getDestination(), webPort); + } + + clientToWebServer = tempSocket; + SSLParameters sslParameters = clientToWebPipeline.getSocket().getSSLParameters(); + + if (sslParameters != null) { + clientToWebServer.setSSLParameters(sslParameters); + } else { + SSLParameters defaultParams = clientToWebServer.getSSLParameters(); + defaultParams.setProtocols(new String[]{"TLSv1.3"}); + clientToWebServer.setSSLParameters(defaultParams); + } + + clientToWebServer.setTcpNoDelay(true); + clientToWebServer.setSoTimeout(0); + + try { + this.clientToWebServer.startHandshake(); + } catch (Exception handshakeEx) { + throw new ConnectException("Handshake failed: " + handshakeEx.getMessage()); + } + + this.outputStream = new ObjectOutputStream(clientToWebServer.getOutputStream()); + this.inputStream = new ObjectInputStream(clientToWebServer.getInputStream()); + this.receiveThread.start(); + } + } + + public final boolean isConnected() { + return this.clientToWebServer != null && this.clientToWebServer.isConnected() && !this.clientToWebServer.isClosed() + && this.receiveThread.isAlive() && !this.receiveThread.isInterrupted() && + ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().isConnected() && clientToWebPipeline.isConnected(); + } + + private void receive() { + try { + while(this.isConnected()) { + Object received = this.inputStream.readObject(); + } + } catch (Exception var2) { + try { + this.closeConnection(); + } catch (IOException exception) { + ProtocolBridge.getInstance().getLogger().exception("Failed to close connection to web server", var2); + } + } + } + + public synchronized final boolean closeConnection() throws IOException { + if (!this.isConnected()) { + return false; + } else { + clientToWebPipeline.disconnect(); + + try { + this.receiveThread.interrupt(); + if (this.outputStream != null) { + this.outputStream.close(); + } + + if (this.inputStream != null) { + this.inputStream.close(); + } + + if (this.clientToWebServer != null) { + this.clientToWebServer.close(); + } + } finally { + this.clientToWebServer = null; + this.outputStream = null; + this.inputStream = null; + } + + return true; + } + } +} diff --git a/src/main/java/org/openautonomousconnection/protocol/side/server/ConnectedProtocolClient.java b/src/main/java/org/openautonomousconnection/protocol/side/dns/ConnectedProtocolClient.java similarity index 69% rename from src/main/java/org/openautonomousconnection/protocol/side/server/ConnectedProtocolClient.java rename to src/main/java/org/openautonomousconnection/protocol/side/dns/ConnectedProtocolClient.java index ec7d611..4fb4888 100644 --- a/src/main/java/org/openautonomousconnection/protocol/side/server/ConnectedProtocolClient.java +++ b/src/main/java/org/openautonomousconnection/protocol/side/dns/ConnectedProtocolClient.java @@ -1,11 +1,11 @@ -package org.openautonomousconnection.protocol.side.server; +package org.openautonomousconnection.protocol.side.dns; import org.openautonomousconnection.protocol.packets.OACPacket; import org.openautonomousconnection.protocol.versions.ProtocolVersion; import lombok.Getter; import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectionHandler; -public class ConnectedProtocolClient { +public final class ConnectedProtocolClient { @Getter private final ConnectionHandler connectionHandler; @@ -20,7 +20,7 @@ public class ConnectedProtocolClient { return clientVersion == null ? ProtocolVersion.PV_1_0_0_CLASSIC : clientVersion; } - public void setClientVersion(ProtocolVersion clientVersion) { + public final void setClientVersion(ProtocolVersion clientVersion) { if (clientVersion == null) this.clientVersion = clientVersion; } @@ -28,7 +28,7 @@ public class ConnectedProtocolClient { return !isBetaClient() && !isClassicClient(); } - public boolean clientSupportStable() { + public boolean supportClientStable() { boolean yes = false; for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) { yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.STABLE; @@ -42,7 +42,7 @@ public class ConnectedProtocolClient { return getClientVersion().getProtocolType() == ProtocolVersion.ProtocolType.BETA; } - public boolean clientSupportBeta() { + public boolean supportClientBeta() { boolean yes = false; for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) { yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.BETA; @@ -56,7 +56,7 @@ public class ConnectedProtocolClient { return getClientVersion().getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; } - public boolean clientSupportClassic() { + public boolean supportClientClassic() { boolean yes = false; for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) { yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; @@ -66,11 +66,21 @@ public class ConnectedProtocolClient { return isClassicClient() || yes; } - public boolean isPacketSupported(OACPacket packet) { - return isVersionSupported(packet.getProtocolVersion()); + public boolean supportClientPacket(OACPacket packet) { + return supportClientVersion(packet.getProtocolVersion()); } - public boolean isVersionSupported(ProtocolVersion targetVersion) { + public boolean supportClientVersion(ProtocolVersion targetVersion) { return getClientVersion() == targetVersion || getClientVersion().getCompatibleVersions().contains(targetVersion); } + + public final boolean supportClientProtocol(ProtocolVersion.Protocol protocol) { + boolean yes = false; + for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) { + yes = compatibleVersion.getSupportedProtocols().contains(protocol); + if (yes) break; + } + + return getClientVersion().getSupportedProtocols().contains(protocol) || yes; + } } diff --git a/src/main/java/org/openautonomousconnection/protocol/side/server/ProtocolServer.java b/src/main/java/org/openautonomousconnection/protocol/side/dns/ProtocolDNSServer.java similarity index 92% rename from src/main/java/org/openautonomousconnection/protocol/side/server/ProtocolServer.java rename to src/main/java/org/openautonomousconnection/protocol/side/dns/ProtocolDNSServer.java index 52f14ef..dcb2c3a 100644 --- a/src/main/java/org/openautonomousconnection/protocol/side/server/ProtocolServer.java +++ b/src/main/java/org/openautonomousconnection/protocol/side/dns/ProtocolDNSServer.java @@ -1,4 +1,4 @@ -package org.openautonomousconnection.protocol.side.server; +package org.openautonomousconnection.protocol.side.dns; import org.openautonomousconnection.protocol.ProtocolBridge; import org.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode; @@ -16,7 +16,7 @@ import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; -public abstract class ProtocolServer extends DefaultMethodsOverrider { +public abstract class ProtocolDNSServer extends DefaultMethodsOverrider { public final class ServerCertificateFolderStructure { public final File certificatesFolder; @@ -68,7 +68,7 @@ public abstract class ProtocolServer extends DefaultMethodsOverrider { private final ConfigurationManager configurationManager; - public ProtocolServer(File configFile) throws IOException, CertificateException { + public ProtocolDNSServer(File configFile) throws IOException, CertificateException { if (!configFile.exists()) configFile.createNewFile(); configurationManager = new ConfigurationManager(configFile); @@ -146,7 +146,7 @@ public abstract class ProtocolServer extends DefaultMethodsOverrider { public abstract DNSResponseCode validateDomain(Domain requestedDomain); - public abstract void validationFailed(Domain domain, ConnectedProtocolClient client, Exception exception); + public abstract void validationPacketSendFailed(Domain domain, ConnectedProtocolClient client, Exception exception); - public abstract void getDomainDestinationFailed(ConnectedProtocolClient client, Domain domain, DNSResponseCode validationResponse, Exception exception); + public abstract void domainDestinationPacketFailedSend(ConnectedProtocolClient client, Domain domain, DNSResponseCode validationResponse, Exception exception); } diff --git a/src/main/java/org/openautonomousconnection/protocol/side/dns/events/ConnectedProtocolClientEvent.java b/src/main/java/org/openautonomousconnection/protocol/side/dns/events/ConnectedProtocolClientEvent.java new file mode 100644 index 0000000..e9b0d74 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/side/dns/events/ConnectedProtocolClientEvent.java @@ -0,0 +1,15 @@ +package org.openautonomousconnection.protocol.side.dns.events; + +import org.openautonomousconnection.protocol.side.dns.ConnectedProtocolClient; +import lombok.Getter; +import dev.unlegitdqrk.unlegitlibrary.event.impl.Event; + +public final class ConnectedProtocolClientEvent extends Event { + + @Getter + private final ConnectedProtocolClient protocolClient; + + public ConnectedProtocolClientEvent(ConnectedProtocolClient protocolClient) { + this.protocolClient = protocolClient; + } +} diff --git a/src/main/java/org/openautonomousconnection/protocol/side/server/events/ProtocolClientConnected.java b/src/main/java/org/openautonomousconnection/protocol/side/server/events/ProtocolClientConnected.java deleted file mode 100644 index 706d9eb..0000000 --- a/src/main/java/org/openautonomousconnection/protocol/side/server/events/ProtocolClientConnected.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.openautonomousconnection.protocol.side.server.events; - -import org.openautonomousconnection.protocol.side.server.ConnectedProtocolClient; -import lombok.Getter; -import dev.unlegitdqrk.unlegitlibrary.event.impl.Event; - -public class ProtocolClientConnected extends Event { - - @Getter - private final ConnectedProtocolClient protocolClient; - - public ProtocolClientConnected(ConnectedProtocolClient protocolClient) { - this.protocolClient = protocolClient; - } -} diff --git a/src/main/java/org/openautonomousconnection/protocol/side/web/ConnectedWebClient.java b/src/main/java/org/openautonomousconnection/protocol/side/web/ConnectedWebClient.java new file mode 100644 index 0000000..a8a8ed6 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/side/web/ConnectedWebClient.java @@ -0,0 +1,464 @@ +package org.openautonomousconnection.protocol.side.web; + +import dev.unlegitdqrk.unlegitlibrary.network.system.packets.Packet; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectionHandler; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.NetworkServer; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.ConnectionHandlerDisconnectedEvent; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.S_PacketReceivedEvent; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.S_PacketReceivedFailedEvent; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.events.S_UnknownObjectReceivedEvent; +import lombok.Getter; +import org.openautonomousconnection.protocol.ProtocolBridge; +import org.openautonomousconnection.protocol.packets.OACPacket; +import org.openautonomousconnection.protocol.side.web.managers.AuthManager; +import org.openautonomousconnection.protocol.side.web.managers.RuleManager; +import org.openautonomousconnection.protocol.side.web.managers.SessionManager; +import org.openautonomousconnection.protocol.versions.ProtocolVersion; + +import javax.net.ssl.SSLSocket; +import java.io.*; +import java.net.SocketException; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.Map; + +public final class ConnectedWebClient { + + @Getter + private final ConnectionHandler pipelineConnection; + + @Getter + private SSLSocket webSocket; + private ObjectOutputStream outputStream; + private ObjectInputStream inputStream; + private final Thread receiveThread = new Thread(this::receive); + + private ProtocolVersion clientVersion = null; + + public ConnectedWebClient(ConnectionHandler pipelineConnection) { + this.pipelineConnection = pipelineConnection; + } + + public void setWebSocket(SSLSocket webSocket) { + if (webSocket != null) this.webSocket = webSocket; + this.receiveThread.start(); + } + + public boolean isConnected() { + return this.webSocket != null && this.webSocket.isConnected() && !this.webSocket.isClosed() && this.receiveThread.isAlive() && pipelineConnection.isConnected(); + } + + + public synchronized boolean disconnect() { + if (!this.isConnected()) { + return false; + } else { + pipelineConnection.disconnect(); + + if (this.receiveThread.isAlive()) { + this.receiveThread.interrupt(); + } + + try { + this.outputStream.close(); + this.inputStream.close(); + this.webSocket.close(); + } catch (IOException var2) { + } + + this.webSocket = null; + this.outputStream = null; + this.inputStream = null; + return true; + } + } + + @Getter + private boolean clientVersionLoaded = false; + + public ProtocolVersion getClientVersion() { + return clientVersion == null ? ProtocolVersion.PV_1_0_0_CLASSIC : clientVersion; + } + + public final void setClientVersion(ProtocolVersion clientVersion) { + if (!clientVersionLoaded) clientVersionLoaded = true; + if (clientVersion == null) this.clientVersion = clientVersion; + } + + public boolean isStableClient() { + return !isBetaClient() && !isClassicClient(); + } + + public boolean supportClientStable() { + boolean yes = false; + for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) { + yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.STABLE; + if (yes) break; + } + + return isStableClient() || yes; + } + + public boolean isBetaClient() { + return getClientVersion().getProtocolType() == ProtocolVersion.ProtocolType.BETA; + } + + public boolean supportClientBeta() { + boolean yes = false; + for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) { + yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.BETA; + if (yes) break; + } + + return isBetaClient() || yes; + } + + public boolean isClassicClient() { + return getClientVersion().getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; + } + + public boolean supportClientClassic() { + boolean yes = false; + for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) { + yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC; + if (yes) break; + } + + return isClassicClient() || yes; + } + + public boolean supportClientPacket(OACPacket packet) { + return supportClientVersion(packet.getProtocolVersion()); + } + + public boolean supportClientVersion(ProtocolVersion targetVersion) { + return getClientVersion() == targetVersion || getClientVersion().getCompatibleVersions().contains(targetVersion); + } + + public final boolean supportClientProtocol(ProtocolVersion.Protocol protocol) { + boolean yes = false; + for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) { + yes = compatibleVersion.getSupportedProtocols().contains(protocol); + if (yes) break; + } + + return getClientVersion().getSupportedProtocols().contains(protocol) || yes; + } + + private void receive() { + try { + while(this.isConnected()) { + Object received = this.inputStream.readObject(); + + try (InputStream in = webSocket.getInputStream(); OutputStream out = webSocket.getOutputStream()) { + BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); + String line; + String path = "/main.html"; + Map headers = new HashMap<>(); + while ((line = reader.readLine()) != null && !line.isEmpty()) { + if (line.toLowerCase().startsWith("get") || line.toLowerCase().startsWith("post")) { + path = line.split(" ")[1]; + } + if (line.contains(":")) { + String[] parts = line.split(":", 2); + headers.put(parts[0].trim().toLowerCase(), parts[1].trim()); + } + } + + path = URLDecoder.decode(path, StandardCharsets.UTF_8); + path = normalizePath(path); + + File file = new File(ProtocolBridge.getInstance().getProtocolWebServer().getContentFolder(), path); + + String sessionId = null; + if (headers.containsKey("cookie")) { + for (String cookie : headers.get("cookie").split(";")) { + cookie = cookie.trim(); + if (cookie.startsWith("SESSIONID=")) { + sessionId = cookie.substring("SESSIONID=".length()); + } + } + } + + if (!file.exists() || !file.isFile()) { + sendResponse(out, 404, new File(ProtocolBridge.getInstance().getProtocolWebServer().getErrorsFolder(), "404.html")); + return; + } + + String clientIp = webSocket.getInetAddress().getHostAddress(); + String userAgent = headers.getOrDefault("user-agent", null); + + boolean loggedIn = sessionId != null && SessionManager.isValid(sessionId, clientIp, userAgent); + + if (path.equals("/403-login") && headers.getOrDefault("content-type","").startsWith("application/x-www-form-urlencoded")) { + Map postParams = parsePostParams(in); + String login = postParams.get("login"); + String password = postParams.get("password"); + + if (AuthManager.checkAuth(login, password)) { + String newSessionId = SessionManager.create(login, clientIp, userAgent); + Map cookies = Map.of("Set-Cookie", "SESSIONID=" + newSessionId + "; HttpOnly; Path=/"); + sendRedirect(out, "/main.html", cookies); + return; + } else { + sendRedirect(out, "/403.php", null); + return; + } + } + + if (isMultipart(headers)) { + handleMultipart(in, headers, new File(ProtocolBridge.getInstance().getProtocolWebServer().getContentFolder(), "uploads")); + } + + if (RuleManager.requiresAuth(path) && !loggedIn) { + PHPResponse phpResp = renderPHPWithCookies(new File(ProtocolBridge.getInstance().getProtocolWebServer().getContentFolder(), "403.php")); + sendResponse(out, 200, phpResp.body.getBytes(StandardCharsets.UTF_8), "text/html", phpResp.cookies); + return; + } + + + if (RuleManager.isDenied(path) && !RuleManager.isAllowed(path)) { + sendResponse(out, 403, new File(ProtocolBridge.getInstance().getProtocolWebServer().getErrorsFolder(), "403.php")); + return; + } + + if (path.endsWith(".php")) { + PHPResponse phpResp = renderPHPWithCookies(file); + sendResponse(out, 200, phpResp.body.getBytes(StandardCharsets.UTF_8), "text/html", phpResp.cookies); + } else { + sendResponse(out, 200, Files.readAllBytes(file.toPath()), getContentType(path), null); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + disconnect(); + } + } + } catch (Exception var2) { + this.disconnect(); + } + } + + private static void sendRedirect(OutputStream out, String location, Map cookies) throws IOException { + out.write(("HTTP/1.1 302 Found\r\n").getBytes()); + out.write(("Location: " + location + "\r\n").getBytes()); + if (cookies != null) { + for (var entry : cookies.entrySet()) { + out.write((entry.getKey() + ": " + entry.getValue() + "\r\n").getBytes()); + } + } + out.write("\r\n".getBytes()); + out.flush(); + } + + private static Map parsePostParams(InputStream in) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); + StringBuilder sb = new StringBuilder(); + while (reader.ready()) { + sb.append((char) reader.read()); + } + Map map = new HashMap<>(); + String[] pairs = sb.toString().split("&"); + for (String p : pairs) { + String[] kv = p.split("=",2); + if (kv.length == 2) map.put(URLDecoder.decode(kv[0], StandardCharsets.UTF_8), URLDecoder.decode(kv[1], StandardCharsets.UTF_8)); + } + return map; + } + + private static String normalizePath(String path) { + path = path.replace("/", File.separator).replace("\\","/"); + while (path.contains("..")) path = path.replace("..", ""); + if (path.startsWith("/")) path = path.substring(1); + return path; + } + + private static Map parseQueryParams(String rawPath) { + Map map = new HashMap<>(); + if (rawPath.contains("?")) { + String[] params = rawPath.substring(rawPath.indexOf("?") + 1).split("&"); + for (String p : params) { + String[] kv = p.split("="); + if (kv.length == 2) map.put(kv[0], kv[1]); + } + } + return map; + } + + private static boolean isMultipart(Map headers) { + String contentType = headers.get("content-type"); + return contentType != null && contentType.startsWith("multipart/form-data"); + } + + private static void handleMultipart(InputStream in, Map headers, File uploadDir) throws IOException { + if (!uploadDir.exists()) uploadDir.mkdirs(); + + String contentType = headers.get("content-type"); + String boundary = "--" + contentType.split("boundary=")[1]; + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + byte[] lineBuffer = new byte[8192]; + int read; + while ((read = in.read(lineBuffer)) != -1) { + buffer.write(lineBuffer, 0, read); + if (buffer.size() > 10 * 1024 * 1024) break; // 10 MB max + } + + String data = buffer.toString(StandardCharsets.UTF_8); + String[] parts = data.split(boundary); + + for (String part : parts) { + if (part.contains("Content-Disposition")) { + String name = null; + String filename = null; + + for (String headerLine : part.split("\r\n")) { + if (headerLine.startsWith("Content-Disposition")) { + if (headerLine.contains("filename=\"")) { + int start = headerLine.indexOf("filename=\"") + 10; + int end = headerLine.indexOf("\"", start); + filename = headerLine.substring(start, end); + } + if (headerLine.contains("name=\"")) { + int start = headerLine.indexOf("name=\"") + 6; + int end = headerLine.indexOf("\"", start); + name = headerLine.substring(start, end); + } + } + } + + if (filename != null && !filename.isEmpty()) { + int headerEnd = part.indexOf("\r\n\r\n"); + byte[] fileData = part.substring(headerEnd + 4).getBytes(StandardCharsets.UTF_8); + File outFile = new File(uploadDir, filename); + Files.write(outFile.toPath(), fileData); + } + } + } + } + + private static String renderPHP(File file) throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("php", file.getAbsolutePath()); + pb.redirectErrorStream(true); + Process p = pb.start(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + InputStream processIn = p.getInputStream(); + byte[] buf = new byte[8192]; + int read; + while ((read = processIn.read(buf)) != -1) { + output.write(buf, 0, read); + } + p.waitFor(); + return output.toString(StandardCharsets.UTF_8); + } + + private static void sendResponse(OutputStream out, int code, File file, Map headers) throws IOException { + byte[] body = Files.readAllBytes(file.toPath()); + sendResponse(out, code, body, "text/html", headers); + } + + private static void sendResponse(OutputStream out, int code, File file) throws IOException { + sendResponse(out, code, Files.readString(file.toPath()), "text/html"); + } + + private static void sendResponse(OutputStream out, int code, String body, String contentType) throws IOException { + sendResponse(out, code, body.getBytes(StandardCharsets.UTF_8), contentType, null); + } + + private static void sendResponse(OutputStream out, int code, File file, String contentType) throws IOException { + byte[] bytes = Files.readAllBytes(file.toPath()); + sendResponse(out, code, bytes, contentType, null); + } + + private static void sendResponse(OutputStream out, int code, byte[] body, String contentType, Map headers) throws IOException { + out.write(("HTTP/1.1 " + code + " " + getStatusText(code) + "\r\n").getBytes()); + out.write(("Content-Type: " + contentType + "\r\n").getBytes()); + out.write(("Content-Length: " + body.length + "\r\n").getBytes()); + if (headers != null) headers.forEach((k, v) -> { + try { out.write((k + ": " + v + "\r\n").getBytes()); } catch (IOException ignored) {} + }); + out.write("\r\n".getBytes()); + out.write(body); + out.flush(); + } + + private static String getStatusText(int code) { + return switch (code) { + case 200 -> "OK"; + case 301 -> "Moved Permanently"; + case 302 -> "Found"; + case 400 -> "Bad Request"; + case 401 -> "Unauthorized"; + case 403 -> "Forbidden"; + case 404 -> "Not Found"; + case 500 -> "Internal Server Error"; + default -> "Unknown"; + }; + } + + private static String getContentType(String name) { + return switch (name.substring(name.lastIndexOf('.') + 1).toLowerCase()) { + case "html", "php" -> "text/html"; + case "js" -> "text/javascript"; + case "css" -> "text/css"; + case "json" -> "application/json"; + case "png" -> "image/png"; + case "jpg", "jpeg" -> "image/jpeg"; + case "mp4" -> "video/mp4"; + case "mp3" -> "audio/mpeg3"; + case "wav" -> "audio/wav"; + case "pdf" -> "application/pdf"; + default -> "text/plain"; + }; + } + + private static PHPResponse renderPHPWithCookies(File file) throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("php", file.getAbsolutePath()); + pb.redirectErrorStream(true); + Process p = pb.start(); + + ByteArrayOutputStream output = new ByteArrayOutputStream(); + InputStream processIn = p.getInputStream(); + byte[] buf = new byte[8192]; + int read; + while ((read = processIn.read(buf)) != -1) { + output.write(buf, 0, read); + } + p.waitFor(); + + String fullOutput = output.toString(StandardCharsets.UTF_8); + Map cookies = new HashMap<>(); + + String[] parts = fullOutput.split("\r\n\r\n", 2); + String body; + if (parts.length == 2) { + String headers = parts[0]; + body = parts[1]; + for (String headerLine : headers.split("\r\n")) { + if (headerLine.toLowerCase().startsWith("set-cookie:")) { + String cookie = headerLine.substring("set-cookie:".length()).trim(); + String[] kv = cookie.split(";", 2); + String[] pair = kv[0].split("=", 2); + if (pair.length == 2) cookies.put(pair[0], pair[1]); + } + } + } else { + body = fullOutput; + } + + return new PHPResponse(body, cookies); + } + + private static class PHPResponse { + String body; + Map cookies; + + public PHPResponse(String body, Map cookies) { + this.body = body; + this.cookies = cookies; + } + } +} diff --git a/src/main/java/org/openautonomousconnection/protocol/side/web/ProtocolWebServer.java b/src/main/java/org/openautonomousconnection/protocol/side/web/ProtocolWebServer.java new file mode 100644 index 0000000..6d522d9 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/side/web/ProtocolWebServer.java @@ -0,0 +1,235 @@ +package org.openautonomousconnection.protocol.side.web; + +import dev.unlegitdqrk.unlegitlibrary.file.ConfigurationManager; +import dev.unlegitdqrk.unlegitlibrary.file.FileUtils; +import dev.unlegitdqrk.unlegitlibrary.network.system.server.NetworkServer; +import dev.unlegitdqrk.unlegitlibrary.network.utils.NetworkUtils; +import lombok.Getter; +import org.openautonomousconnection.protocol.ProtocolBridge; +import org.openautonomousconnection.protocol.side.web.managers.AuthManager; +import org.openautonomousconnection.protocol.side.web.managers.RuleManager; + +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLSocket; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class ProtocolWebServer { + public final class ServerCertificateFolderStructure { + public final File certificatesFolder; + + public final File publicFolder; + public final File privateFolder; + + public final File privateCAFolder; + public final File privateServerFolder; + + public final File publicCAFolder; + public final File publicServerFolder; + + public ServerCertificateFolderStructure() { + certificatesFolder = new File("certificates"); + + publicFolder = new File(certificatesFolder, "public"); + privateFolder = new File(certificatesFolder, "private"); + + privateCAFolder = new File(privateFolder, "ca"); + privateServerFolder = new File(privateFolder, "server"); + + publicCAFolder = new File(publicFolder, "ca"); + publicServerFolder = new File(publicFolder, "server"); + + if (!certificatesFolder.exists()) certificatesFolder.mkdirs(); + + if (!publicFolder.exists()) publicFolder.mkdirs(); + if (!privateFolder.exists()) privateFolder.mkdirs(); + + if (!privateCAFolder.exists()) privateCAFolder.mkdirs(); + if (!privateServerFolder.exists()) privateServerFolder.mkdirs(); + + if (!publicCAFolder.exists()) publicCAFolder.mkdirs(); + if (!publicServerFolder.exists()) publicServerFolder.mkdirs(); + } + + public final String caPrefix = "ca_server_"; + public final String certPrefix = "cert_server_"; + } + + @Getter + private NetworkServer pipelineServer; + @Getter + private SSLServerSocket webServer; + + @Getter + private final File contentFolder; + @Getter + private final File errorsFolder; + + @Getter + private final ServerCertificateFolderStructure folderStructure; + + private final ConfigurationManager configurationManager; + private final File certFile; + private final File keyFile; + + @Getter + private List clients; + + public ProtocolWebServer(File configFile, File authFile, File rulesFile) throws Exception { + this.clients = new ArrayList<>(); + + folderStructure = new ServerCertificateFolderStructure(); + + checkFileExists(folderStructure.publicServerFolder, folderStructure.certPrefix, ".crt"); + checkFileExists(folderStructure.privateServerFolder, folderStructure.certPrefix, ".key"); + + this.configurationManager = getConfigurationManager(configFile); + + contentFolder = new File("content"); + errorsFolder = new File("errors"); + + if (!contentFolder.exists()) contentFolder.mkdir(); + if (!errorsFolder.exists()) errorsFolder.mkdir(); + + this.certFile = new File(folderStructure.publicServerFolder, folderStructure.certPrefix + NetworkUtils.getPublicIPAddress() + ".crt"); + this.keyFile = new File(folderStructure.privateServerFolder, folderStructure.certPrefix + NetworkUtils.getPublicIPAddress() + ".key"); + + if (!authFile.exists()) { + authFile.createNewFile(); + FileUtils.writeFile(authFile, """ + admin:5e884898da28047151d0e56f8dc6292773603d0d6aabbddab8f91d8e5f99f6c7 + user:e99a18c428cb38d5f260853678922e03abd8335f + """); + } + + if (!rulesFile.exists()) { + rulesFile.createNewFile(); + FileUtils.writeFile(rulesFile, """ + { + "allow": [ + "index.html", + "css/*", + "private/info.php" + ], + "deny": [ + "private/*" + ], + "auth": [ + "private/*", + "admin/*" + ] + } + """); + } + + AuthManager.loadAuthFile(authFile); + RuleManager.loadRules(rulesFile); + + pipelineServer = new NetworkServer.ServerBuilder(). + setPort(configurationManager.getInt("port.pipeline")).setTimeout(0). + setPacketHandler(ProtocolBridge.getInstance().getProtocolSettings().packetHandler).setEventManager(ProtocolBridge.getInstance().getProtocolSettings().eventManager). + setLogger(ProtocolBridge.getInstance().getLogger()). + setServerCertificate(certFile, keyFile).setRootCAFolder(folderStructure.publicCAFolder). + build(); + } + + public final ConnectedWebClient getClientByID(int clientID) { + for (ConnectedWebClient client : clients) + if (client.getPipelineConnection().getClientID() == clientID) return client; + return null; + } + + public final void startWebServer() throws Exception { + webServer = (SSLServerSocket)NetworkServer.ServerBuilder. + createSSLServerSocketFactory(folderStructure.publicCAFolder, certFile,keyFile). + createServerSocket(configurationManager.getInt("port")); + webServer.setSoTimeout(0); + webServer.setEnabledProtocols(pipelineServer.getServerSocket().getEnabledProtocols()); + + // Stop WebServer if pipelineServer dies + new Thread(() -> { + while (true) { + if (pipelineServer == null || !pipelineServer.getServerSocket().isBound()) { + try { + onPipelineStop(); + } catch (IOException e) { + pipelineServer.getLogger().exception("Failed to stop WebServer", e); + } + + Thread.currentThread().interrupt(); + break; + } + } + }).start(); + + // Handle every client + new Thread(() -> { + while (true) { + try { + SSLSocket client = (SSLSocket) webServer.accept(); + for (ConnectedWebClient connectedWebClient : clients) { + if (connectedWebClient.getPipelineConnection().getClientID() != -1 && connectedWebClient.isClientVersionLoaded()) { + connectedWebClient.setWebSocket(client); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + }).start(); + } + + private void onPipelineStop() throws IOException { + webServer.close(); + } + + private void checkFileExists(File folder, String prefix, String extension) throws CertificateException, IOException { + boolean found = false; + if (folder == null) throw new FileNotFoundException("Folder does not exist"); + + File[] files = folder.listFiles(); + if (files == null || files.length == 0) throw new FileNotFoundException("Folder " + folder.getAbsolutePath() + " is empty"); + + for (File file : files) { + if (!file.getName().startsWith(prefix) || !file.getName().endsWith(extension)) throw new CertificateException(file.getAbsolutePath() + " is not valid"); + if (!found) found = file.getName().equalsIgnoreCase(prefix + NetworkUtils.getPublicIPAddress() + extension); + } + + if (!found) throw new CertificateException("Missing " + prefix + NetworkUtils.getPublicIPAddress() + extension); + } + + private ConfigurationManager getConfigurationManager(File configFile) throws IOException { + if (!configFile.exists()) configFile.createNewFile(); + + ConfigurationManager configurationManager = new ConfigurationManager(configFile); + configurationManager.loadProperties(); + + if (!configurationManager.isSet("port.webserver")) { + configurationManager.set("port.webserver", 9824); + configurationManager.saveProperties(); + } + + if (!configurationManager.isSet("port.pipeline")) { + configurationManager.set("port.pipeline", 9389); + configurationManager.saveProperties(); + } + + if (!configurationManager.isSet("filemaxuploadmb")) { + configurationManager.set("filemaxuploadmb", 1000); + configurationManager.saveProperties(); + } + + if (!configurationManager.isSet("sessionexpireminutes")) { + configurationManager.set("sessionexpireminutes", 60); + configurationManager.saveProperties(); + } + + return configurationManager; + } +} diff --git a/src/main/java/org/openautonomousconnection/protocol/side/web/events/ConnectedWebClientEvent.java b/src/main/java/org/openautonomousconnection/protocol/side/web/events/ConnectedWebClientEvent.java new file mode 100644 index 0000000..4cfeb92 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/side/web/events/ConnectedWebClientEvent.java @@ -0,0 +1,15 @@ +package org.openautonomousconnection.protocol.side.web.events; + +import dev.unlegitdqrk.unlegitlibrary.event.impl.Event; +import lombok.Getter; +import org.openautonomousconnection.protocol.side.web.ConnectedWebClient; + +public final class ConnectedWebClientEvent extends Event { + + @Getter + private final ConnectedWebClient webClient; + + public ConnectedWebClientEvent(ConnectedWebClient webClient) { + this.webClient = webClient; + } +} diff --git a/src/main/java/org/openautonomousconnection/protocol/side/web/managers/AuthManager.java b/src/main/java/org/openautonomousconnection/protocol/side/web/managers/AuthManager.java new file mode 100644 index 0000000..8120b06 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/side/web/managers/AuthManager.java @@ -0,0 +1,48 @@ +package org.openautonomousconnection.protocol.side.web.managers; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.security.MessageDigest; +import java.util.HashMap; +import java.util.Map; + +public class AuthManager { + + private static Map users = new HashMap<>(); + + public static void loadAuthFile(File authFile) throws IOException { + if (!authFile.exists()) authFile.createNewFile(); + for (String line : Files.readAllLines(authFile.toPath(), StandardCharsets.UTF_8)) { + line = line.trim(); + if (line.isEmpty() || line.startsWith("#")) continue; + String[] parts = line.split(":", 2); + if (parts.length == 2) { + users.put(parts[0], parts[1]); + } + } + } + + public static boolean checkAuth(String login, String password) { + + String storedHash = users.get(login); + if (storedHash == null) return false; + + String hash = sha256(password); + return storedHash.equalsIgnoreCase(hash); + } + + private static String sha256(String input) { + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8)); + StringBuilder sb = new StringBuilder(); + for (byte b : digest) sb.append(String.format("%02x", b)); + return sb.toString(); + } catch (Exception e) { + return ""; + } + } +} + diff --git a/src/main/java/org/openautonomousconnection/protocol/side/web/managers/RuleManager.java b/src/main/java/org/openautonomousconnection/protocol/side/web/managers/RuleManager.java new file mode 100644 index 0000000..d68857b --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/side/web/managers/RuleManager.java @@ -0,0 +1,40 @@ +package org.openautonomousconnection.protocol.side.web.managers; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.io.File; +import java.nio.file.Files; +import java.util.List; +import java.util.Map; + +public class RuleManager { + private static List allow; + private static List deny; + private static List auth; + + public static void loadRules(File rulesFile) throws Exception { + String json = new String(Files.readAllBytes(rulesFile.toPath())); + Map> map = new Gson().fromJson(json, new TypeToken>>(){}.getType()); + allow = map.getOrDefault("allow", List.of()); + deny = map.getOrDefault("deny", List.of()); + auth = map.getOrDefault("auth", List.of()); + } + + public static boolean isAllowed(String path) { + return allow.stream().anyMatch(p -> pathMatches(path, p)); + } + + public static boolean isDenied(String path) { + return deny.stream().anyMatch(p -> pathMatches(path, p)); + } + + public static boolean requiresAuth(String path) { + return auth.stream().anyMatch(p -> pathMatches(path, p)); + } + + private static boolean pathMatches(String path, String pattern) { + pattern = pattern.replace("/", File.separator).replace("*", ".*"); + return path.matches(pattern); + } +} diff --git a/src/main/java/org/openautonomousconnection/protocol/side/web/managers/SessionManager.java b/src/main/java/org/openautonomousconnection/protocol/side/web/managers/SessionManager.java new file mode 100644 index 0000000..a4eefef --- /dev/null +++ b/src/main/java/org/openautonomousconnection/protocol/side/web/managers/SessionManager.java @@ -0,0 +1,79 @@ +package org.openautonomousconnection.protocol.side.web.managers; + +import lombok.Getter; + +import java.io.IOException; +import java.security.SecureRandom; +import java.util.Base64; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class SessionManager { + + private static final Map sessions = new ConcurrentHashMap<>(); + private static final SecureRandom secureRandom = new SecureRandom(); + + private static class Session { + @Getter + String login; + String ip; + String userAgent; + long expiresAt; + + Session(String login, String ip, String userAgent) throws IOException { + this.login = login; + this.ip = ip; + this.userAgent = userAgent; + this.expiresAt = System.currentTimeMillis() + (long) Main.getConfigurationManager().getInt("sessionexpireminutes") * 60 * 1000;;; + } + + boolean isExpired() { + return System.currentTimeMillis() > expiresAt; + } + + boolean matches(String ip, String userAgent) { + return this.ip.equals(ip) && this.userAgent.equals(userAgent); + } + + void refresh() throws IOException { + this.expiresAt = System.currentTimeMillis() + (long) Main.getConfigurationManager().getInt("sessionexpireminutes") * 60 * 1000;;; + } + } + + public static String create(String login, String ip, String userAgent) throws IOException { + byte[] bytes = new byte[32]; + secureRandom.nextBytes(bytes); + String sessionId = Base64.getUrlEncoder().withoutPadding().encodeToString(bytes); + sessions.put(sessionId, new Session(login, ip, userAgent)); + return sessionId; + } + + public static boolean isValid(String sessionId, String ip, String userAgent) throws IOException { + Session session = sessions.get(sessionId); + if (session == null || session.isExpired() || !session.matches(ip, userAgent)) { + sessions.remove(sessionId); + return false; + } + + session.refresh(); + return true; + } + + public static void invalidate(String sessionId) { + sessions.remove(sessionId); + } + + public static String getUser(String sessionId) { + Session session = sessions.get(sessionId); + if (session == null || session.isExpired()) { + sessions.remove(sessionId); + return null; + } + return session.getLogin(); + } + + public static void cleanupExpiredSessions() { + long now = System.currentTimeMillis(); + sessions.entrySet().removeIf(entry -> entry.getValue().isExpired()); + } +} diff --git a/src/main/java/org/openautonomousconnection/protocol/versions/ProtocolVersion.java b/src/main/java/org/openautonomousconnection/protocol/versions/ProtocolVersion.java index fd2596e..c4f8474 100644 --- a/src/main/java/org/openautonomousconnection/protocol/versions/ProtocolVersion.java +++ b/src/main/java/org/openautonomousconnection/protocol/versions/ProtocolVersion.java @@ -8,8 +8,8 @@ import java.util.Arrays; import java.util.List; public enum ProtocolVersion implements Serializable { - PV_1_0_0_CLASSIC("1.0.0", ProtocolType.CLASSIC, ProtocolSide.BOTH), - PV_1_0_0_BETA("1.0.0", ProtocolType.BETA, ProtocolSide.BOTH, PV_1_0_0_CLASSIC); + PV_1_0_0_CLASSIC("1.0.0", ProtocolType.CLASSIC, ProtocolSide.WEB_DNS, List.of(Protocol.HTTP)), + PV_1_0_0_BETA("1.0.0", ProtocolType.BETA, ProtocolSide.ALL, List.of(Protocol.OAC), PV_1_0_0_CLASSIC); @Getter private final String version; @@ -19,30 +19,49 @@ public enum ProtocolVersion implements Serializable { private final ProtocolSide protocolSide; @Getter private final List compatibleVersions; + @Getter + private final List supportedProtocols; - ProtocolVersion(String version, ProtocolType protocolType, ProtocolSide protocolSide, ProtocolVersion... compatibleVersions) { + ProtocolVersion(String version, ProtocolType protocolType, ProtocolSide protocolSide, List supportedProtocols, ProtocolVersion... compatibleVersions) { this.version = version; this.protocolType = protocolType; this.protocolSide = protocolSide; this.compatibleVersions = new ArrayList<>(Arrays.stream(compatibleVersions).toList()); if (!this.compatibleVersions.contains(this)) this.compatibleVersions.add(this); + this.supportedProtocols = supportedProtocols; } @Override public final String toString() { StringBuilder compatible = new StringBuilder("["); + StringBuilder supported = new StringBuilder("["); for (ProtocolVersion compatibleVersion : compatibleVersions) compatible.append(compatibleVersion.buildName()); + for (Protocol supportedProtocol : supportedProtocols) supported.append(supportedProtocol.toString()); compatible.append("]"); + supported.append("]"); - return "{version=" + version + ";type=" + protocolType.toString() + ";side=" + protocolSide.toString() + ";compatible=" + compatible + "}"; + return "{version=" + version + ";type=" + protocolType.toString() + ";side=" + protocolSide.toString() + ";supportedProtocols=" + supported + ";compatibleVersions=" + compatible + "}"; } public final String buildName() { return version + "-" + protocolType.toString(); } + public enum Protocol implements Serializable { + HTTP, + HTTPS, + OAC + + ; + + @Override + public final String toString() { + return name().toUpperCase(); + } + } + public enum ProtocolType implements Serializable { - CLASSIC, // -> See "_old" Projects on GitHub Organisation https://github.com/Open-Autonomous-Connection/ + CLASSIC, // -> See "_old" Projects https://repo.open-autonomous-connection.org/Open-Autonomous-Connection/ BETA, STABLE; @@ -54,9 +73,15 @@ public enum ProtocolVersion implements Serializable { public enum ProtocolSide implements Serializable { CLIENT, // Protocol version can only used on Client - SERVER, // Protocol version can only used on Server - BOTH // Protocol version can only used on Server and Client + DNS, // Protocol version can only used on DNS Server + WEB, // Protocol version can only used on Web Server + WEB_DNS, // Protocol version can only used on DNS and WebSerber + + CLIENT_DNS, // Protocol version can only used on DNS and Client + CLIENT_WEB, // Protocol version can only used on WebServer and Client + + ALL // Protocol version can used on all Sides ; @Override diff --git a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/Domain.java b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/Domain.java index 806f957..75900b3 100644 --- a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/Domain.java +++ b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/beta/Domain.java @@ -77,17 +77,17 @@ public class Domain implements Serializable { } public final String getDestination() { - if (ProtocolBridge.getInstance().isRunningAsClient()) + if (ProtocolBridge.getInstance().isRunningAsClient() || ProtocolBridge.getInstance().isRunningAsWebServer()) return DNSResponseCode.RESPONSE_INVALID_REQUEST.toString(); if (this.equals(DefaultDomains.DNS_INFO_SITE)) - return ProtocolBridge.getInstance().getProtocolServer().getDNSInfoSite(); + return ProtocolBridge.getInstance().getProtocolDNSServer().getDNSInfoSite(); if (this.equals(DefaultDomains.DNS_REGISTER_SITE)) - return ProtocolBridge.getInstance().getProtocolServer().getDNSRegisterSite(); + return ProtocolBridge.getInstance().getProtocolDNSServer().getDNSRegisterSite(); if (this.name.equalsIgnoreCase("about") && this.protocol.equalsIgnoreCase("oac")) - return ProtocolBridge.getInstance().getProtocolServer().getTLNInfoSite(topLevelName); + return ProtocolBridge.getInstance().getProtocolDNSServer().getTLNInfoSite(topLevelName); - return !hasSubname() ? ProtocolBridge.getInstance().getProtocolServer().getDomainDestination(this) : ProtocolBridge.getInstance().getProtocolServer().getSubnameDestination(this, subname); + return !hasSubname() ? ProtocolBridge.getInstance().getProtocolDNSServer().getDomainDestination(this) : ProtocolBridge.getInstance().getProtocolDNSServer().getSubnameDestination(this, subname); } public static class DefaultDomains { diff --git a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/classic/ClassicHandlerClient.java b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/classic/ClassicHandlerClient.java index 9698b47..08885df 100644 --- a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/classic/ClassicHandlerClient.java +++ b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/classic/ClassicHandlerClient.java @@ -1,5 +1,11 @@ package org.openautonomousconnection.protocol.versions.v1_0_0.classic; +import org.openautonomousconnection.protocol.ProtocolBridge; +import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_DomainPacket; +import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_MessagePacket; + +import java.io.IOException; + public abstract class ClassicHandlerClient { public abstract void unsupportedClassicPacket(String classicPacketClassName, Object[] content); @@ -7,4 +13,8 @@ public abstract class ClassicHandlerClient { public abstract void handleHTMLContent(Classic_SiteType siteType, Classic_Domain domain, String html); public abstract void handleMessage(String message); + + public final void sendMessage(String message) throws IOException, ClassNotFoundException { + ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().sendPacket(new Classic_MessagePacket(message, 0)); + } } diff --git a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/classic/ClassicHandlerServer.java b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/classic/ClassicHandlerServer.java index a2c4b12..690d4ff 100644 --- a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/classic/ClassicHandlerServer.java +++ b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/classic/ClassicHandlerServer.java @@ -1,6 +1,6 @@ package org.openautonomousconnection.protocol.versions.v1_0_0.classic; -import org.openautonomousconnection.protocol.side.server.ConnectedProtocolClient; +import org.openautonomousconnection.protocol.side.dns.ConnectedProtocolClient; import java.sql.SQLException; diff --git a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/classic/Classic_ClientListener.java b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/classic/Classic_ClientListener.java index 3d58041..98c077b 100644 --- a/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/classic/Classic_ClientListener.java +++ b/src/main/java/org/openautonomousconnection/protocol/versions/v1_0_0/classic/Classic_ClientListener.java @@ -19,7 +19,7 @@ public class Classic_ClientListener extends EventListener { if (exists) { try { - if (!ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().sendPacket(new Classic_PingPacket(event.requestDomain, event.domain, false))) { + if (!ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().sendPacket(new Classic_PingPacket(event.requestDomain, event.domain, false))) { ProtocolBridge.getInstance().getClassicHandlerClient().handleHTMLContent(Classic_SiteType.PROTOCOL, new Classic_LocalDomain("error-occurred", "html", ""), Classic_WebsitesContent.ERROR_OCCURRED(event.domain + "/" + event.domain.path)); }