Compare commits

...

10 Commits

Author SHA1 Message Date
Tinglyyy
dae382d07d Added ProtocolInfoProcessing and its components 2025-09-29 18:27:03 +02:00
Tinglyyy
846fa167bc Revert "Revert "- Maked classes final""
This reverts commit 742059ff67.
2025-09-29 18:22:08 +02:00
Tinglyyy
1d2c94678e Revert "Revert "- Added comments""
This reverts commit 44ef52dba4.
2025-09-29 18:22:04 +02:00
Tinglyyy
8afab87f59 Revert "Revert "- Started with WebServer""
This reverts commit d14f2ec6f8.
2025-09-29 18:21:59 +02:00
Tinglyyy
bb5f312d63 Revert "Revert "- Code cleanup""
This reverts commit 95ac2b988b.
2025-09-29 18:21:54 +02:00
Tinglyyy
4b0009aff0 Revert "Revert "- Started with Web Protocol""
This reverts commit 944d0a71bc.
2025-09-29 18:21:50 +02:00
Tinglyyy
f0468c6f91 Revert "Revert "- Updated to new repo""
This reverts commit b88bae9f5e.
2025-09-29 18:21:45 +02:00
Tinglyyy
509d54c537 Revert "Revert "- Updated to new repo""
This reverts commit 257af4af91.
2025-09-29 18:21:41 +02:00
Tinglyyy
300615427c Revert "Revert "- Updated to new repo""
This reverts commit 06c5724803.
2025-09-29 18:21:37 +02:00
Tinglyyy
54e6c4163d Revert "Revert "- Updated to new repo""
This reverts commit 6c7a0728ee.
2025-09-29 18:21:32 +02:00
75 changed files with 4537 additions and 1343 deletions

6
.idea/GitLink.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="uk.co.ben_gibson.git.link.SettingsState">
<option name="host" value="e0f86390-1091-4871-8aeb-f534fbc99cf0" />
</component>
</project>

2
.idea/encodings.xml generated
View File

@@ -3,5 +3,7 @@
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/../../../../../../Windows/System32/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/../../../../../../Windows/System32/src/main/resources" charset="UTF-8" />
</component>
</project>

View File

@@ -23,7 +23,7 @@ This project (OAC) is licensed under the [Open Autonomous Public License (OAPL)]
### pom.xml
```
<dependency>
<groupId>github.openautonomousconnection</groupId>
<groupId>org.openautonomousconnection</groupId>
<artifactId>protocol</artifactId>
<version>VERSION</version>
</dependency>
@@ -31,15 +31,13 @@ This project (OAC) is licensed under the [Open Autonomous Public License (OAPL)]
### Repository:
```
<repositories>
<repository>
<id>github</id>
<url>https://maven.pkg.github.com/open-autonomous-connection/protocol</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<repository>
<id>oac</id>
<url>https://repo.open-autonomous-connection.org/api/packages/open-autonomous-connection/maven</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
```
# Examples
@@ -47,7 +45,7 @@ This project (OAC) is licensed under the [Open Autonomous Public License (OAPL)]
### Server
```java
import me.finn.unlegitlibrary.network.system.server.ConnectionHandler;
import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectionHandler;
import me.openautonomousconnection.protocol.ProtocolBridge;
import me.openautonomousconnection.protocol.ProtocolSettings;
import me.openautonomousconnection.protocol.ProtocolVersion;

66
pom.xml
View File

@@ -4,14 +4,14 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>github.openautonomousconnection</groupId>
<groupId>org.openautonomousconnection</groupId>
<artifactId>protocol</artifactId>
<version>1.0.0-BETA.3</version>
<organization>
<name>Open Autonomous Connection</name>
<url>https://open-autonomous-connection.org/</url>
</organization>
<url>https://open-autonomous-connection.org/protocol/</url>
<url>https://open-autonomous-connection.org/</url>
<description>The Protocol for Server and Client</description>
<properties>
@@ -53,14 +53,14 @@
</developers>
<issueManagement>
<system>GitHub Issue Tracker</system>
<url>https://github.com/Open-Autonomous-Connection/Protocol/issues</url>
<system>Issue Tracker</system>
<url>https://repo.open-autonomous-connection.org/open-autonomous-connection/Protocol/issues</url>
</issueManagement>
<repositories>
<repository>
<id>github</id>
<url>https://maven.pkg.github.com/unlegitdqrk/unlegitlibrary</url>
<id>repounlegitdqrk</id>
<url>https://repo.unlegitdqrk.dev/api/packages/UnlegitDqrk/maven</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
@@ -69,25 +69,25 @@
<distributionManagement>
<repository>
<id>github</id>
<name>protocol</name>
<url>https://maven.pkg.github.com/open-autonomous-connection/protocol</url>
<id>oac</id>
<name>Protocol</name>
<url>https://repo.open-autonomous-connection.org/api/packages/open-autonomous-connection/maven</url>
</repository>
</distributionManagement>
<licenses>
<license>
<name>Open Autonomous Public License</name>
<url>https://github.com/Open-Autonomous-Connection/OAPL/blob/main/LICENSE</url>
<url>https://repo.open-autonomous-connection.org/Open-Autonomous-Connection/OAPL/</url>
<distribution>repo</distribution>
</license>
</licenses>
<dependencies>
<dependency>
<groupId>me.finn.unlegitlibrary</groupId>
<groupId>dev.unlegitdqrk</groupId>
<artifactId>unlegitlibrary</artifactId>
<version>1.6.2</version>
<version>1.6.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
@@ -95,5 +95,47 @@
<version>1.18.38</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.13.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-fileupload2-jakarta-servlet6</artifactId>
<version>2.0.0-M4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-fileupload2</artifactId>
<version>2.0.0-M4</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-fileupload2-core</artifactId>
<version>2.0.0-M4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.20.0</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>LATEST</version>
</dependency>
</dependencies>
</project>

View File

@@ -1,159 +0,0 @@
package github.openautonomousconnection.protocol;
import github.openautonomousconnection.protocol.listeners.ClientListener;
import github.openautonomousconnection.protocol.listeners.ServerListener;
import github.openautonomousconnection.protocol.packets.OACPacket;
import github.openautonomousconnection.protocol.packets.v1_0_0.beta.AuthPacket;
import github.openautonomousconnection.protocol.packets.v1_0_0.beta.GetDestinationPacket;
import github.openautonomousconnection.protocol.packets.v1_0_0.beta.UnsupportedClassicPacket;
import github.openautonomousconnection.protocol.packets.v1_0_0.beta.ValidateDomainPacket;
import github.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_DomainPacket;
import github.openautonomousconnection.protocol.side.client.ProtocolClient;
import github.openautonomousconnection.protocol.side.server.ProtocolServer;
import github.openautonomousconnection.protocol.versions.ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.classic.ClassicHandlerClient;
import github.openautonomousconnection.protocol.versions.v1_0_0.classic.ClassicHandlerServer;
import github.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_ClientListener;
import lombok.Getter;
import lombok.Setter;
import me.finn.unlegitlibrary.utils.Logger;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
public class ProtocolBridge {
@Getter
private static ProtocolBridge instance;
@Getter
private final ProtocolSettings protocolSettings;
@Getter
private final ProtocolVersion protocolVersion;
@Getter
private final Logger logger;
@Getter
private ProtocolServer protocolServer;
@Getter
private ProtocolClient protocolClient;
@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;
this.protocolSettings = protocolSettings;
this.protocolVersion = protocolVersion;
Logger tmpLogger = null;
try {
tmpLogger = new Logger(logFolder, false, true);
} catch (IOException | NoSuchFieldException | IllegalAccessException exception) {
exception.printStackTrace();
tmpLogger = null;
System.exit(1);
}
this.logger = tmpLogger;
protocolSettings.eventManager.registerListener(new ServerListener());
protocolSettings.eventManager.unregisterListener(new ClientListener());
if (!validateProtocolSide()) {
this.logger.error("Invalid protocol version '" + protocolVersion.toString() + "'!");
System.exit(1);
}
if (isClassicSupported()) protocolSettings.eventManager.unregisterListener(new Classic_ClientListener());
registerPackets();
instance = this;
}
public ProtocolBridge(ProtocolClient protocolClient, ProtocolSettings protocolSettings, ProtocolVersion protocolVersion, File logFolder) throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
this.protocolClient = protocolClient;
this.protocolSettings = protocolSettings;
this.protocolVersion = protocolVersion;
Logger tmpLogger = null;
try {
tmpLogger = new Logger(logFolder, false, true);
} catch (IOException | NoSuchFieldException | IllegalAccessException exception) {
exception.printStackTrace();
tmpLogger = null;
System.exit(1);
}
this.logger = tmpLogger;
protocolSettings.eventManager.registerListener(new ClientListener());
protocolSettings.eventManager.unregisterListener(new ServerListener());
if (!validateProtocolSide()) {
this.logger.error("Invalid protocol version '" + protocolVersion.toString() + "'!");
System.exit(1);
}
if (isClassicSupported()) protocolSettings.eventManager.registerListener(new Classic_ClientListener());
registerPackets();
instance = this;
}
private void registerPackets() {
// Classic packets
Classic_DomainPacket cDomainPacket = new Classic_DomainPacket();
Classic_DomainPacket cMessagePacket = new Classic_DomainPacket();
Classic_DomainPacket cPingPacket = new Classic_DomainPacket();
if (isPacketSupported(cDomainPacket)) protocolSettings.packetHandler.registerPacket(cDomainPacket);
if (isPacketSupported(cMessagePacket)) protocolSettings.packetHandler.registerPacket(cMessagePacket);
if (isPacketSupported(cPingPacket)) protocolSettings.packetHandler.registerPacket(cPingPacket);
// 1.0.0-BETA packets
AuthPacket v100bAuthPath = new AuthPacket();
UnsupportedClassicPacket v100bUnsupportedClassicPacket = new UnsupportedClassicPacket();
ValidateDomainPacket v100bValidateDomainPacket = new ValidateDomainPacket();
GetDestinationPacket v100bGetDestinationPacket = new GetDestinationPacket();
if (isPacketSupported(v100bAuthPath)) protocolSettings.packetHandler.registerPacket(v100bAuthPath);
if (isPacketSupported(v100bUnsupportedClassicPacket))
protocolSettings.packetHandler.registerPacket(v100bUnsupportedClassicPacket);
if (isPacketSupported(v100bValidateDomainPacket))
protocolSettings.packetHandler.registerPacket(v100bValidateDomainPacket);
if (isPacketSupported(v100bGetDestinationPacket))
protocolSettings.packetHandler.registerPacket(v100bGetDestinationPacket);
}
public boolean isPacketSupported(OACPacket packet) {
return isVersionSupported(packet.getProtocolVersion());
}
public boolean isClassicSupported() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : protocolVersion.getCompatibleVersions()) {
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
if (yes) break;
}
return protocolVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC || yes;
}
public boolean isRunningAsServer() {
return protocolServer != null;
}
public boolean isRunningAsClient() {
return protocolClient != null;
}
private boolean validateProtocolSide() {
return (isRunningAsServer() && protocolVersion.getProtocolSide() != ProtocolVersion.ProtocolSide.CLIENT) ||
(isRunningAsClient() && protocolVersion.getProtocolSide() != ProtocolVersion.ProtocolSide.SERVER);
}
public boolean isVersionSupported(ProtocolVersion targetVersion) {
return protocolVersion == targetVersion || protocolVersion.getCompatibleVersions().contains(targetVersion);
}
}

View File

@@ -1,14 +0,0 @@
package github.openautonomousconnection.protocol;
import me.finn.unlegitlibrary.event.EventManager;
import me.finn.unlegitlibrary.network.system.packets.PacketHandler;
import me.finn.unlegitlibrary.utils.DefaultMethodsOverrider;
public class ProtocolSettings extends DefaultMethodsOverrider {
public String host;
public int port;
public PacketHandler packetHandler;
public EventManager eventManager;
}

View File

@@ -1,29 +0,0 @@
package github.openautonomousconnection.protocol.listeners;
import github.openautonomousconnection.protocol.ProtocolBridge;
import github.openautonomousconnection.protocol.packets.v1_0_0.beta.AuthPacket;
import me.finn.unlegitlibrary.event.EventListener;
import me.finn.unlegitlibrary.event.Listener;
import me.finn.unlegitlibrary.network.system.client.events.ClientConnectedEvent;
import me.finn.unlegitlibrary.network.system.client.events.ClientDisconnectedEvent;
import java.io.IOException;
public class ClientListener extends EventListener {
@Listener
public void onConnect(ClientConnectedEvent event) {
try {
event.client.sendPacket(new AuthPacket());
} catch (IOException | ClassNotFoundException exception) {
ProtocolBridge.getInstance().getLogger().exception("Failed to send auth packet", exception);
event.client.disconnect();
}
}
@Listener
public void onDisconnect(ClientDisconnectedEvent event) {
ProtocolBridge.getInstance().getProtocolClient().onDisconnect(event);
}
}

View File

@@ -1,22 +0,0 @@
package github.openautonomousconnection.protocol.listeners;
import github.openautonomousconnection.protocol.ProtocolBridge;
import github.openautonomousconnection.protocol.side.server.ConnectedProtocolClient;
import me.finn.unlegitlibrary.event.EventListener;
import me.finn.unlegitlibrary.event.Listener;
import me.finn.unlegitlibrary.network.system.server.events.ConnectionHandlerConnectedEvent;
import me.finn.unlegitlibrary.network.system.server.events.ConnectionHandlerDisconnectedEvent;
public class ServerListener extends EventListener {
@Listener
public void onConnect(ConnectionHandlerConnectedEvent event) {
ProtocolBridge.getInstance().getProtocolServer().getClients().add(new ConnectedProtocolClient(event.connectionHandler));
}
@Listener
public void onDisconnect(ConnectionHandlerDisconnectedEvent event) {
ProtocolBridge.getInstance().getProtocolServer().getClients().removeIf(client -> client.getConnectionHandler().getClientID() == -1);
}
}

View File

@@ -1,54 +0,0 @@
package github.openautonomousconnection.protocol.packets;
import github.openautonomousconnection.protocol.versions.ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode;
import lombok.Getter;
import me.finn.unlegitlibrary.network.system.packets.Packet;
import me.finn.unlegitlibrary.network.system.packets.PacketHandler;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public abstract class OACPacket extends Packet {
@Getter
private final ProtocolVersion protocolVersion;
private DNSResponseCode responseCode = DNSResponseCode.RESPONSE_NOT_REQUIRED;
public OACPacket(int id, ProtocolVersion protocolVersion) {
super(id);
this.protocolVersion = protocolVersion;
}
protected final DNSResponseCode getResponseCode() {
return responseCode;
}
protected final void setResponseCode(DNSResponseCode responseCode) {
this.responseCode = responseCode;
}
@Override
public final void write(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException {
onWrite(packetHandler, objectOutputStream);
if (protocolVersion != ProtocolVersion.PV_1_0_0_CLASSIC) objectOutputStream.writeObject(responseCode);
}
@Override
public final void read(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
onRead(packetHandler, objectInputStream);
if (protocolVersion != ProtocolVersion.PV_1_0_0_CLASSIC) {
responseCode = (DNSResponseCode) objectInputStream.readObject();
onResponseCodeRead(packetHandler, objectInputStream);
}
}
public abstract void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException;
public abstract void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException;
protected void onResponseCodeRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) {
}
}

View File

@@ -1,57 +0,0 @@
package github.openautonomousconnection.protocol.packets.v1_0_0.beta;
import github.openautonomousconnection.protocol.ProtocolBridge;
import github.openautonomousconnection.protocol.packets.OACPacket;
import github.openautonomousconnection.protocol.versions.ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain;
import me.finn.unlegitlibrary.network.system.packets.PacketHandler;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class ValidateDomainPacket extends OACPacket {
private Domain domain;
private int clientID;
public ValidateDomainPacket(Domain domain) {
this();
this.domain = domain;
}
public ValidateDomainPacket() {
super(6, ProtocolVersion.PV_1_0_0_BETA);
}
@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.writeObject(domain);
}
@Override
public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
if (ProtocolBridge.getInstance().isRunningAsServer()) clientID = objectInputStream.readInt();
domain = (Domain) objectInputStream.readObject();
}
@Override
protected void onResponseCodeRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) {
super.onResponseCodeRead(packetHandler, objectInputStream);
if (ProtocolBridge.getInstance().isRunningAsServer()) {
try {
ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID).getConnectionHandler().sendPacket(new ValidateDomainPacket(domain));
} catch (IOException | ClassNotFoundException e) {
ProtocolBridge.getInstance().getProtocolServer().validationFailed(domain, ProtocolBridge.getInstance().getProtocolServer().getClientByID(clientID), e);
}
return;
}
ProtocolBridge.getInstance().getProtocolClient().validationCompleted(domain, getResponseCode());
}
}

View File

@@ -1,79 +0,0 @@
package github.openautonomousconnection.protocol.packets.v1_0_0.classic;
import github.openautonomousconnection.protocol.ProtocolBridge;
import github.openautonomousconnection.protocol.packets.OACPacket;
import github.openautonomousconnection.protocol.packets.v1_0_0.beta.UnsupportedClassicPacket;
import github.openautonomousconnection.protocol.versions.ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_Domain;
import github.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_DomainPacketReceivedEvent;
import github.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_RequestDomain;
import me.finn.unlegitlibrary.network.system.packets.PacketHandler;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.SQLException;
// ProtocolVersion 1.0.0-CLASSIC is ProtocolSide Server only
public class Classic_DomainPacket extends OACPacket {
private Classic_RequestDomain requestDomain;
private Classic_Domain domain;
private int clientID;
public Classic_DomainPacket(int toClient, Classic_RequestDomain requestDomain, Classic_Domain domain) {
this();
this.clientID = toClient;
this.requestDomain = requestDomain;
this.domain = domain;
}
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()) {
objectOutputStream.writeInt(clientID);
objectOutputStream.writeObject(requestDomain);
objectOutputStream.writeObject(domain);
} else {
clientID = ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().getClientID();
objectOutputStream.writeInt(clientID);
objectOutputStream.writeObject(requestDomain);
}
objectOutputStream.writeObject(Classic_ProtocolVersion.PV_1_0_0);
}
@Override
public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
if (ProtocolBridge.getInstance().isRunningAsServer()) {
clientID = objectInputStream.readInt();
requestDomain = (Classic_RequestDomain) objectInputStream.readObject();
Classic_ProtocolVersion protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject();
try {
domain = ProtocolBridge.getInstance().getClassicHandlerServer().getDomain(requestDomain);
} catch (SQLException exception) {
exception.printStackTrace();
}
ProtocolBridge.getInstance().getProtocolServer().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));
else
ProtocolBridge.getInstance().getProtocolServer().getNetworkServer().getConnectionHandlerByID(clientID).sendPacket(new UnsupportedClassicPacket(Classic_PingPacket.class, new Object[]{clientID, requestDomain, domain}));
} else {
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));
}
}
}

View File

@@ -1,56 +0,0 @@
package github.openautonomousconnection.protocol.packets.v1_0_0.classic;
import github.openautonomousconnection.protocol.ProtocolBridge;
import github.openautonomousconnection.protocol.packets.OACPacket;
import github.openautonomousconnection.protocol.versions.ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_ProtocolVersion;
import me.finn.unlegitlibrary.network.system.packets.PacketHandler;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
// ProtocolVersion 1.0.0-CLASSIC is ProtocolSide Server only
public class Classic_MessagePacket extends OACPacket {
private String message;
private int clientID;
public Classic_MessagePacket(String message, int toClient) {
this();
this.message = message;
this.clientID = toClient;
}
public Classic_MessagePacket() {
super(3, ProtocolVersion.PV_1_0_0_CLASSIC);
}
@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();
objectOutputStream.writeInt(clientID);
}
objectOutputStream.writeUTF(message);
objectOutputStream.writeObject(Classic_ProtocolVersion.PV_1_0_0);
}
@Override
public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
if (ProtocolBridge.getInstance().isRunningAsServer()) {
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 {
clientID = objectInputStream.readInt();
String message = objectInputStream.readUTF();
Classic_ProtocolVersion protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject();
ProtocolBridge.getInstance().getClassicHandlerClient().handleMessage(message);
}
}
}

View File

@@ -1,83 +0,0 @@
package github.openautonomousconnection.protocol.packets.v1_0_0.classic;
import github.openautonomousconnection.protocol.ProtocolBridge;
import github.openautonomousconnection.protocol.packets.OACPacket;
import github.openautonomousconnection.protocol.packets.v1_0_0.beta.UnsupportedClassicPacket;
import github.openautonomousconnection.protocol.versions.ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_Domain;
import github.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_PingPacketReceivedEvent;
import github.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.classic.Classic_RequestDomain;
import me.finn.unlegitlibrary.network.system.packets.PacketHandler;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.SQLException;
public class Classic_PingPacket extends OACPacket {
private Classic_RequestDomain requestDomain;
private Classic_Domain domain;
private int clientID;
private boolean reachable;
private Classic_ProtocolVersion protocolVersion;
public Classic_PingPacket(Classic_RequestDomain requestDomain, Classic_Domain domain, boolean reachable) {
this();
this.requestDomain = requestDomain;
this.domain = domain;
this.reachable = reachable;
this.protocolVersion = Classic_ProtocolVersion.PV_1_0_0;
}
public Classic_PingPacket() {
super(1, ProtocolVersion.PV_1_0_0_CLASSIC);
}
@Override
public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException {
if (ProtocolBridge.getInstance().isRunningAsServer()) {
objectOutputStream.writeInt(clientID);
objectOutputStream.writeObject(requestDomain);
objectOutputStream.writeObject(domain);
objectOutputStream.writeBoolean(reachable);
} else {
clientID = ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().getClientID();
objectOutputStream.writeInt(clientID);
objectOutputStream.writeObject(requestDomain);
}
objectOutputStream.writeObject(protocolVersion);
}
@Override
public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
if (ProtocolBridge.getInstance().isRunningAsServer()) {
clientID = objectInputStream.readInt();
requestDomain = (Classic_RequestDomain) objectInputStream.readObject();
protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject();
try {
domain = ProtocolBridge.getInstance().getClassicHandlerServer().ping(requestDomain);
} catch (SQLException exception) {
exception.printStackTrace();
}
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));
else
ProtocolBridge.getInstance().getProtocolServer().getNetworkServer().getConnectionHandlerByID(clientID).sendPacket(new UnsupportedClassicPacket(Classic_PingPacket.class, new Object[]{requestDomain, domain, reachable}));
} else {
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));
}
}
}

View File

@@ -1,158 +0,0 @@
package github.openautonomousconnection.protocol.side.client;
import github.openautonomousconnection.protocol.ProtocolBridge;
import github.openautonomousconnection.protocol.packets.OACPacket;
import github.openautonomousconnection.protocol.packets.v1_0_0.beta.ValidateDomainPacket;
import github.openautonomousconnection.protocol.versions.ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode;
import github.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain;
import lombok.Getter;
import me.finn.unlegitlibrary.network.system.client.NetworkClient;
import me.finn.unlegitlibrary.network.system.client.events.ClientDisconnectedEvent;
import me.finn.unlegitlibrary.network.utils.NetworkUtils;
import me.finn.unlegitlibrary.utils.DefaultMethodsOverrider;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.cert.CertificateException;
public abstract class ProtocolClient extends DefaultMethodsOverrider {
public final class ClientCertificateFolderStructure {
public final File certificatesFolder;
public final File publicFolder;
public final File privateFolder;
public final File privateCAFolder;
public final File privateClientFolder;
public final File publicCAFolder;
public final File publicClientFolder;
public ClientCertificateFolderStructure() {
certificatesFolder = new File("certificates");
publicFolder = new File(certificatesFolder, "public");
privateFolder = new File(certificatesFolder, "private");
privateCAFolder = new File(privateFolder, "ca");
privateClientFolder = new File(privateFolder, "client");
publicCAFolder = new File(publicFolder, "ca");
publicClientFolder = new File(publicFolder, "client");
if (!certificatesFolder.exists()) certificatesFolder.mkdirs();
if (!publicFolder.exists()) publicFolder.mkdirs();
if (!privateFolder.exists()) privateFolder.mkdirs();
if (!privateCAFolder.exists()) privateCAFolder.mkdirs();
if (!privateClientFolder.exists()) privateClientFolder.mkdirs();
if (!publicCAFolder.exists()) publicCAFolder.mkdirs();
if (!publicClientFolder.exists()) publicClientFolder.mkdirs();
}
}
@Getter
private final NetworkClient networkClient;
private ProtocolVersion serverVersion = null;
@Getter
private final ClientCertificateFolderStructure folderStructure;
public ProtocolClient() throws CertificateException, IOException {
folderStructure = new ClientCertificateFolderStructure();
networkClient = 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();
}
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");
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);
}
public final ProtocolVersion getServerVersion() {
return serverVersion == null ? ProtocolVersion.PV_1_0_0_CLASSIC : serverVersion;
}
public final void setServerVersion(ProtocolVersion serverVersion) {
if (serverVersion == null) this.serverVersion = serverVersion;
}
public final void onDisconnect(ClientDisconnectedEvent event) {
serverVersion = null;
}
public final boolean isStableServer() {
return !isBetaServer() && !isClassicServer();
}
public final boolean serverSupportStable() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) {
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.STABLE;
if (yes) break;
}
return isStableServer() || yes;
}
public final boolean isBetaServer() {
return getServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.BETA;
}
public final boolean serverSupportBeta() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) {
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.BETA;
if (yes) break;
}
return isBetaServer() || yes;
}
public final boolean isClassicServer() {
return getServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
}
public final boolean serverSupportClassic() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) {
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
if (yes) break;
}
return isClassicServer() || yes;
}
public final boolean isPacketSupported(OACPacket packet) {
return isVersionSupported(packet.getProtocolVersion());
}
public final boolean isVersionSupported(ProtocolVersion targetVersion) {
return getServerVersion() == targetVersion || getServerVersion().getCompatibleVersions().contains(targetVersion);
}
public final void validateDomain(Domain domain) throws IOException, ClassNotFoundException {
networkClient.sendPacket(new ValidateDomainPacket(domain));
}
public abstract void validationCompleted(Domain domain, DNSResponseCode responseCode);
public abstract void getDestinationCompleted(Domain domain, String destination, DNSResponseCode validationResponse);
}

View File

@@ -1,6 +0,0 @@
package github.openautonomousconnection.protocol.side.client.events;
import me.finn.unlegitlibrary.event.impl.Event;
public class ConnectedToProtocolServer extends Event {
}

View File

@@ -1,76 +0,0 @@
package github.openautonomousconnection.protocol.side.server;
import github.openautonomousconnection.protocol.packets.OACPacket;
import github.openautonomousconnection.protocol.versions.ProtocolVersion;
import lombok.Getter;
import me.finn.unlegitlibrary.network.system.server.ConnectionHandler;
public class ConnectedProtocolClient {
@Getter
private final ConnectionHandler connectionHandler;
private ProtocolVersion clientVersion = null;
public ConnectedProtocolClient(ConnectionHandler connectionHandler) {
this.connectionHandler = connectionHandler;
}
public ProtocolVersion getClientVersion() {
return clientVersion == null ? ProtocolVersion.PV_1_0_0_CLASSIC : clientVersion;
}
public void setClientVersion(ProtocolVersion clientVersion) {
if (clientVersion == null) this.clientVersion = clientVersion;
}
public boolean isStableClient() {
return !isBetaClient() && !isClassicClient();
}
public boolean clientSupportStable() {
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 clientSupportBeta() {
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 clientSupportClassic() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) {
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
if (yes) break;
}
return isClassicClient() || yes;
}
public boolean isPacketSupported(OACPacket packet) {
return isVersionSupported(packet.getProtocolVersion());
}
public boolean isVersionSupported(ProtocolVersion targetVersion) {
return getClientVersion() == targetVersion || getClientVersion().getCompatibleVersions().contains(targetVersion);
}
}

View File

@@ -1,152 +0,0 @@
package github.openautonomousconnection.protocol.side.server;
import github.openautonomousconnection.protocol.ProtocolBridge;
import github.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode;
import github.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain;
import lombok.Getter;
import me.finn.unlegitlibrary.file.ConfigurationManager;
import me.finn.unlegitlibrary.network.system.server.NetworkServer;
import me.finn.unlegitlibrary.network.utils.NetworkUtils;
import me.finn.unlegitlibrary.utils.DefaultMethodsOverrider;
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;
public abstract class ProtocolServer extends DefaultMethodsOverrider {
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_dns_";
public final String certPrefix = "cert_dns_";
}
@Getter
private final NetworkServer networkServer;
@Getter
private List<ConnectedProtocolClient> clients;
@Getter
private ServerCertificateFolderStructure folderStructure;
private final ConfigurationManager configurationManager;
public ProtocolServer(File configFile) throws IOException, CertificateException {
if (!configFile.exists()) configFile.createNewFile();
configurationManager = new ConfigurationManager(configFile);
configurationManager.loadProperties();
if (!configurationManager.isSet("server.site.info")) {
configurationManager.set("server.site.info", "DNS-SERVER INFO SITE IP");
configurationManager.saveProperties();
}
if (!configurationManager.isSet("server.site.register")) {
configurationManager.set("server.site.register", "SERVER IP TO DNS-FRONTENT WEBSITE");
configurationManager.saveProperties();
}
folderStructure = new ServerCertificateFolderStructure();
checkFileExists(folderStructure.publicCAFolder, folderStructure.caPrefix, ".pem");
checkFileExists(folderStructure.publicCAFolder, folderStructure.caPrefix, ".srl");
checkFileExists(folderStructure.privateCAFolder, folderStructure.caPrefix, ".key");
checkFileExists(folderStructure.publicServerFolder, folderStructure.certPrefix, ".crt");
checkFileExists(folderStructure.privateServerFolder, folderStructure.certPrefix, ".key");
File certFile = new File(folderStructure.publicServerFolder, folderStructure.certPrefix + NetworkUtils.getPublicIPAddress() + ".crt");
File keyFile = new File(folderStructure.privateServerFolder, folderStructure.certPrefix + NetworkUtils.getPublicIPAddress() + ".key");
ProtocolBridge protocolBridge = ProtocolBridge.getInstance();
this.clients = new ArrayList<>();
this.networkServer = new NetworkServer.ServerBuilder().setLogger(protocolBridge.getLogger()).
setEventManager(protocolBridge.getProtocolSettings().eventManager).
setPacketHandler(protocolBridge.getProtocolSettings().packetHandler).
setPort(protocolBridge.getProtocolSettings().port).
setRequireClientCertificate(false).setRootCAFolder(folderStructure.publicCAFolder).setServerCertificate(certFile, keyFile).
build();
}
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");
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);
}
public final ConnectedProtocolClient getClientByID(int clientID) {
for (ConnectedProtocolClient client : clients)
if (client.getConnectionHandler().getClientID() == clientID) return client;
return null;
}
public final String getDNSInfoSite() {
return configurationManager.getString("server.site.info");
}
public final String getDNSRegisterSite() {
return configurationManager.getString("server.site.register");
}
public abstract List<Domain> getDomains();
public abstract String getDomainDestination(Domain domain);
public abstract String getSubnameDestination(Domain domain, String subname);
public abstract String getTLNInfoSite(String topLevelName);
public abstract DNSResponseCode validateDomain(Domain requestedDomain);
public abstract void validationFailed(Domain domain, ConnectedProtocolClient client, Exception exception);
public abstract void getDomainDestinationFailed(ConnectedProtocolClient client, Domain domain, DNSResponseCode validationResponse, Exception exception);
}

View File

@@ -1,15 +0,0 @@
package github.openautonomousconnection.protocol.side.server.events;
import github.openautonomousconnection.protocol.side.server.ConnectedProtocolClient;
import lombok.Getter;
import me.finn.unlegitlibrary.event.impl.Event;
public class ProtocolClientConnected extends Event {
@Getter
private final ConnectedProtocolClient protocolClient;
public ProtocolClientConnected(ConnectedProtocolClient protocolClient) {
this.protocolClient = protocolClient;
}
}

View File

@@ -1,67 +0,0 @@
package github.openautonomousconnection.protocol.versions;
import lombok.Getter;
import java.io.Serializable;
import java.util.ArrayList;
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);
@Getter
private final String version;
@Getter
private final ProtocolType protocolType;
@Getter
private final ProtocolSide protocolSide;
@Getter
private final List<ProtocolVersion> compatibleVersions;
ProtocolVersion(String version, ProtocolType protocolType, ProtocolSide protocolSide, 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);
}
@Override
public final String toString() {
StringBuilder compatible = new StringBuilder("[");
for (ProtocolVersion compatibleVersion : compatibleVersions) compatible.append(compatibleVersion.buildName());
compatible.append("]");
return "{version=" + version + ";type=" + protocolType.toString() + ";side=" + protocolSide.toString() + ";compatible=" + compatible + "}";
}
public final String buildName() {
return version + "-" + protocolType.toString();
}
public enum ProtocolType implements Serializable {
CLASSIC, // -> See "_old" Projects on GitHub Organisation https://github.com/Open-Autonomous-Connection/
BETA,
STABLE;
@Override
public final String toString() {
return name().toUpperCase();
}
}
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
;
@Override
public final String toString() {
return name().toUpperCase();
}
}
}

View File

@@ -1,25 +0,0 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
import github.openautonomousconnection.protocol.versions.ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain;
public class ClassicConverter {
public static Domain classicDomainToNewDomain(Classic_Domain classicDomain) {
return new Domain(classicDomain.name + "." + classicDomain.topLevelDomain + (classicDomain.path.startsWith("/") ? classicDomain.path : "/" + classicDomain.path));
}
public static Classic_Domain newDomainToClassicDomain(Domain newDomain) {
return new Classic_Domain(newDomain.getName(), newDomain.getTopLevelName(), newDomain.getDestination(), newDomain.getPath());
}
public static ProtocolVersion classicProtocolVersionToNewProtocolVersion(Classic_ProtocolVersion classicProtocolVersion) {
if (classicProtocolVersion == Classic_ProtocolVersion.PV_1_0_0) return ProtocolVersion.PV_1_0_0_CLASSIC;
return null;
}
public static Classic_ProtocolVersion newProtocolVersionToClassicProtocolVersion(ProtocolVersion newProtocolVersion) {
return Classic_ProtocolVersion.PV_1_0_0;
}
}

View File

@@ -1,10 +0,0 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
public abstract class ClassicHandlerClient {
public abstract void unsupportedClassicPacket(String classicPacketClassName, Object[] content);
public abstract void handleHTMLContent(Classic_SiteType siteType, Classic_Domain domain, String html);
public abstract void handleMessage(String message);
}

View File

@@ -1,15 +0,0 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
import github.openautonomousconnection.protocol.side.server.ConnectedProtocolClient;
import java.sql.SQLException;
public abstract class ClassicHandlerServer {
public abstract void handleMessage(ConnectedProtocolClient client, String message, Classic_ProtocolVersion protocolVersion);
public abstract Classic_Domain getDomain(Classic_RequestDomain requestDomain) throws SQLException;
public abstract Classic_Domain ping(Classic_RequestDomain requestDomain) throws SQLException;
public abstract void unsupportedClassicPacket(String className, Object[] content, ConnectedProtocolClient client);
}

View File

@@ -1,39 +0,0 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
import github.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain;
import lombok.Getter;
import java.io.Serializable;
public class Classic_Domain implements Serializable {
public final String name;
public final String topLevelDomain;
public final String path;
private final String destination;
@Getter
private final Domain domain;
public Classic_Domain(String name, String topLevelDomain, String destination, String path) {
this.domain = new Domain(name + "." + topLevelDomain + "/" + (path.startsWith("/") ? path : "/" + path));
this.name = domain.getName();
this.topLevelDomain = domain.getTopLevelName();
this.destination = domain.getDestination();
this.path = domain.getPath();
}
@Override
protected final Object clone() throws CloneNotSupportedException {
return new Classic_Domain(name, topLevelDomain, destination, path);
}
@Override
public final boolean equals(Object obj) {
if (!(obj instanceof Classic_Domain other)) return false;
return other.name.equalsIgnoreCase(name) && other.topLevelDomain.equalsIgnoreCase(topLevelDomain);
}
@Override
public final int hashCode() {
return super.hashCode();
}
}

View File

@@ -1,38 +0,0 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
import me.finn.unlegitlibrary.event.impl.Event;
public class Classic_DomainPacketReceivedEvent extends Event {
public final Classic_ProtocolVersion protocolVersion;
public final Classic_Domain domain;
public final Classic_RequestDomain requestDomain;
public final int clientID;
public Classic_DomainPacketReceivedEvent(Classic_ProtocolVersion protocolVersion, Classic_Domain domain, Classic_RequestDomain requestDomain, int clientID) {
this.protocolVersion = protocolVersion;
this.domain = domain;
this.requestDomain = requestDomain;
this.clientID = clientID;
}
@Override
protected final Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public final boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public final String toString() {
return super.toString();
}
@Override
public final int hashCode() {
return super.hashCode();
}
}

View File

@@ -1,7 +0,0 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
public class Classic_LocalDomain extends Classic_Domain {
public Classic_LocalDomain(String name, String endName, String path) {
super(name, endName, null, path);
}
}

View File

@@ -1,40 +0,0 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
import me.finn.unlegitlibrary.event.impl.Event;
public class Classic_PingPacketReceivedEvent extends Event {
public final Classic_ProtocolVersion protocolVersion;
public final Classic_Domain domain;
public final Classic_RequestDomain requestDomain;
public final boolean reachable;
public final int clientID;
public Classic_PingPacketReceivedEvent(Classic_ProtocolVersion protocolVersion, Classic_Domain domain, Classic_RequestDomain requestDomain, boolean reachable, int clientID) {
this.protocolVersion = protocolVersion;
this.domain = domain;
this.requestDomain = requestDomain;
this.reachable = reachable;
this.clientID = clientID;
}
@Override
protected final Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public final boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public final String toString() {
return super.toString();
}
@Override
public final int hashCode() {
return super.hashCode();
}
}

View File

@@ -1,10 +0,0 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
import java.io.Serializable;
public class Classic_RequestDomain extends Classic_Domain implements Serializable {
public Classic_RequestDomain(String name, String topLevelDomain, String path) {
super(name, topLevelDomain, null, path);
}
}

View File

@@ -1,14 +0,0 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
import java.io.Serializable;
enum Classic_SiteType implements Serializable {
CLIENT("oac-client"), SERVER("oac-server"),
PUBLIC("oac"), PROTOCOL("oac-protocol"), LOCAL("oac-local");
public final String name;
Classic_SiteType(String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,375 @@
package org.openautonomousconnection.protocol;
import dev.unlegitdqrk.unlegitlibrary.utils.Logger;
import lombok.Getter;
import lombok.Setter;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.annotations.processing.ProtocolInfoProcessing;
import org.openautonomousconnection.protocol.listeners.ClientListener;
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;
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.UnsupportedClassicPacket;
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.dns.ProtocolDNSServer;
import org.openautonomousconnection.protocol.side.web.ProtocolWebServer;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerClient;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerDNSServer;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerWebServer;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils.Classic_ClientListener;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
/**
* The main bridge class for the protocol connection.
* It manages the protocol settings, version, and side instances.
*/
public final class ProtocolBridge {
/**
* The singleton instance of the ProtocolBridge class
*/
@Getter
private static ProtocolBridge instance;
/**
* The protocol settings for the current connection
*/
@Getter
private final ProtocolSettings protocolSettings;
/**
* The protocol version for the current connection
*/
@Getter
private final ProtocolVersion protocolVersion;
/**
* The logger instance for logging events and errors
*/
@Getter
private Logger logger;
/**
* The protocol side instances
*/
@Getter
private ProtocolDNSServer protocolDNSServer;
/**
* The protocol side instances
*/
@Getter
private ProtocolClient protocolClient;
/**
* The protocol side instances
*/
@Getter
private ProtocolWebServer protocolWebServer;
/**
* The classic protocol handlers for dns server side
*/
@Getter
@Setter
private ClassicHandlerDNSServer classicHandlerDNSServer;
/**
* The classic protocol handlers for web server side
*/
@Getter
@Setter
private ClassicHandlerWebServer classicHandlerWebServer;
/**
* The classic protocol handlers for client side
*/
@Getter
@Setter
private ClassicHandlerClient classicHandlerClient;
private final ProtocolInfoProcessing protocolInfoProcessing;
/**
* Initialize the ProtocolBridge instance for the DNS server side
* @param protocolDNSServer The ProtocolDNSServer instance
* @param protocolSettings The ProtocolSettings instance
* @param protocolVersion The ProtocolVersion instance
* @param logFolder The folder to store the log files
* @throws Exception if an error occurs while initializing the ProtocolBridge
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.DNS)
public ProtocolBridge(ProtocolDNSServer protocolDNSServer, ProtocolSettings protocolSettings, ProtocolVersion protocolVersion, File logFolder) throws Exception {
// Assign the parameters to the class fields
this.protocolDNSServer = protocolDNSServer;
this.protocolSettings = protocolSettings;
this.protocolVersion = protocolVersion;
// Initialize the logger and protocol version
initializeLogger(logFolder);
initializeProtocolVersion();
// Register the appropriate listeners and packets
registerListeners();
registerPackets();
// Set the static instance to this instance
instance = this;
this.protocolInfoProcessing = new ProtocolInfoProcessing();
}
/**
* Initialize the ProtocolBridge instance for the web server side
* @param protocolWebServer The ProtocolWebServer instance
* @param protocolSettings The ProtocolSettings instance
* @param protocolVersion The ProtocolVersion instance
* @param logFolder The folder to store the log files
* @throws Exception if an error occurs while initializing the ProtocolBridge
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.WEB)
public ProtocolBridge(ProtocolWebServer protocolWebServer, ProtocolSettings protocolSettings, ProtocolVersion protocolVersion, File logFolder) throws Exception {
// Assign the parameters to the class fields
this.protocolWebServer = protocolWebServer;
this.protocolSettings = protocolSettings;
this.protocolVersion = protocolVersion;
// Initialize the logger and protocol version
initializeLogger(logFolder);
initializeProtocolVersion();
// Register the appropriate listeners and packets
registerListeners();
registerPackets();
// Set the static instance to this instance
instance = this;
this.protocolInfoProcessing = new ProtocolInfoProcessing();
}
/**
* Initialize the ProtocolBridge instance for the client side
* @param protocolClient The ProtocolClient instance
* @param protocolSettings The ProtocolSettings instance
* @param protocolVersion The ProtocolVersion instance
* @param logFolder The folder to store the log files
* @throws Exception if an error occurs while initializing the ProtocolBridge
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.CLIENT)
public ProtocolBridge(ProtocolClient protocolClient, ProtocolSettings protocolSettings, ProtocolVersion protocolVersion, File logFolder) throws Exception {
// Assign the parameters to the class fields
this.protocolClient = protocolClient;
this.protocolSettings = protocolSettings;
this.protocolVersion = protocolVersion;
// Initialize the logger and protocol version
initializeLogger(logFolder);
initializeProtocolVersion();
// Register the appropriate listeners and packets
registerListeners();
registerPackets();
// Set the static instance to this instance
instance = this;
this.protocolInfoProcessing = new ProtocolInfoProcessing();
}
/**
* Register the appropriate packets based on the current protocol version
*/
private void registerPackets() {
// Classic packets
Classic_DomainPacket cDomainPacket = new Classic_DomainPacket();
Classic_DomainPacket cMessagePacket = new Classic_DomainPacket();
Classic_DomainPacket cPingPacket = new Classic_DomainPacket();
if (isPacketSupported(cDomainPacket)) protocolSettings.packetHandler.registerPacket(cDomainPacket);
if (isPacketSupported(cMessagePacket)) protocolSettings.packetHandler.registerPacket(cMessagePacket);
if (isPacketSupported(cPingPacket)) protocolSettings.packetHandler.registerPacket(cPingPacket);
// 1.0.0-BETA packets
AuthPacket v100bAuthPath = new AuthPacket();
UnsupportedClassicPacket v100bUnsupportedClassicPacket = new UnsupportedClassicPacket();
ValidateDomainPacket v100bValidateDomainPacket = new ValidateDomainPacket();
GetDestinationPacket v100bGetDestinationPacket = new GetDestinationPacket();
if (isPacketSupported(v100bAuthPath)) protocolSettings.packetHandler.registerPacket(v100bAuthPath);
if (isPacketSupported(v100bUnsupportedClassicPacket)) protocolSettings.packetHandler.registerPacket(v100bUnsupportedClassicPacket);
if (isPacketSupported(v100bValidateDomainPacket)) protocolSettings.packetHandler.registerPacket(v100bValidateDomainPacket);
if (isPacketSupported(v100bGetDestinationPacket)) protocolSettings.packetHandler.registerPacket(v100bGetDestinationPacket);
}
/**
* Register the appropriate listeners based on the current side
* @throws Exception if an error occurs while registering the listeners
*/
private void registerListeners() throws Exception {
// Classic listeners
if (isClassicSupported()) protocolSettings.eventManager.registerListener(Classic_ClientListener.class);
else protocolSettings.eventManager.unregisterListener(Classic_ClientListener.class);
// DNS Listeners
if (isRunningAsDNSServer()) {
protocolSettings.eventManager.registerListener(DNSServerListener.class);
protocolSettings.eventManager.unregisterListener(WebServerListener.class);
protocolSettings.eventManager.unregisterListener(ClientListener.class);
}
// Web Listeners
if (isRunningAsWebServer()) {
protocolSettings.eventManager.registerListener(WebServerListener.class);
protocolSettings.eventManager.unregisterListener(DNSServerListener.class);
protocolSettings.eventManager.unregisterListener(ClientListener.class);
}
// Client Listeners
if (isRunningAsClient()) {
protocolSettings.eventManager.registerListener(ClientListener.class);
protocolSettings.eventManager.unregisterListener(DNSServerListener.class);
protocolSettings.eventManager.unregisterListener(WebServerListener.class);
}
}
/**
* Initialize the logger instance
* @param logFolder The folder to store the log files
*/
private void initializeLogger(File logFolder) {
// Create a temporary logger instance to avoid final field issues
Logger tmpLogger = null;
try {
// Initialize temporary logger
tmpLogger = new Logger(logFolder, false, true);
} catch (IOException | NoSuchFieldException | IllegalAccessException exception) {
exception.printStackTrace();
System.exit(1);
}
// Assign the temporary logger to the final field
this.logger = tmpLogger;
}
/**
* Initialize the protocol version
* Validate if the protocol version is valid for the current side
* If not, log an error and exit the application
*/
private void initializeProtocolVersion() {
// Check if the protocol version is valid for the current side
// If not, log an error and exit the application
if (!validateProtocolSide()) {
this.logger.error("Invalid protocol version '" + protocolVersion.toString() + "'!");
System.exit(1);
}
}
/**
* Check if the classic protocol is supported by the current protocol version
* @return true if the classic protocol is supported, false otherwise
*/
public final boolean isClassicSupported() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : protocolVersion.getCompatibleVersions()) {
// Check if the compatible version is classic
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
if (yes) break;
}
// Check if the current protocol version is classic or if it is supported by any of the compatible versions
return protocolVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC || yes;
}
/**
* Check if the target protocol is supported by the current protocol version
* @param protocol The target protocol to check
* @return true If the target protocol is supported, false otherwise
*/
public final boolean isProtocolSupported(ProtocolVersion.Protocol protocol) {
boolean yes = false;
for (ProtocolVersion compatibleVersion : protocolVersion.getCompatibleVersions()) {
// Check if the compatible version supports the target protocol
yes = compatibleVersion.getSupportedProtocols().contains(protocol);
if (yes) break;
}
// Check if the current protocol version supports the target protocol or if it is supported by any of the compatible versions
return protocolVersion.getSupportedProtocols().contains(protocol) || yes;
}
/**
* Check if the target packet is supported by the current protocol version
* @param packet The target packet to check
* @return true if the target packet is supported, false otherwise
*/
public final boolean isPacketSupported(OACPacket packet) {
return isVersionSupported(packet.getProtocolVersion());
}
/**
* Check if the target protocol version is supported by the current protocol version
* @param targetVersion The target protocol version to check
* @return true if the target protocol version is supported, false otherwise
*/
public final boolean isVersionSupported(ProtocolVersion targetVersion) {
// Check if the target protocol version is the same as the current protocol version or if it is in the list of compatible versions
return protocolVersion == targetVersion || protocolVersion.getCompatibleVersions().contains(targetVersion);
}
/**
* Validate if the protocol version is valid for the current side
* @return true if the protocol version is valid for the current side, false otherwise
*/
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);
}
/**
* Check if the current instance is running as a DNS server
* @return true if the current instance is running as a DNS server, false otherwise
*/
public final boolean isRunningAsDNSServer() {
return protocolDNSServer != null;
}
/**
* Check if the current instance is running as a client
* @return true if the current instance is running as a client, false otherwise
*/
public final boolean isRunningAsClient() {
return protocolClient != null;
}
/**
* Check if the current instance is running as a web server
* @return true if the current instance is running as a web server, false otherwise
*/
public final boolean isRunningAsWebServer() {
return protocolWebServer != null;
}
}

View File

@@ -0,0 +1,32 @@
package org.openautonomousconnection.protocol;
import dev.unlegitdqrk.unlegitlibrary.event.EventManager;
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
import dev.unlegitdqrk.unlegitlibrary.utils.DefaultMethodsOverrider;
/**
* Settings for the protocol connection.
*/
public final class ProtocolSettings extends DefaultMethodsOverrider {
/**
* The host to connect to.
*/
public String host;
/**
* The port to connect to.
*/
public int port;
/**
* The protocol version to use.
*/
public PacketHandler packetHandler;
/**
* The event manager to use.
*/
public EventManager eventManager;
}

View File

@@ -0,0 +1,17 @@
package org.openautonomousconnection.protocol.annotations;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
/**
* Annotation to provide metadata about protocol handlers or classes.
*/
public @interface ProtocolInfo {
/**
* Specifies the side of the protocol that the annotated class or method is associated with.
* Default is ALL, indicating that it can be used on any side.
* @return The protocol side.
*/
ProtocolVersion.ProtocolSide protocolSide() default ProtocolVersion.ProtocolSide.ALL;
}

View File

@@ -0,0 +1,83 @@
package org.openautonomousconnection.protocol.annotations.processing;
import dev.unlegitdqrk.unlegitlibrary.reflections.GenericReflectClass;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import javax.annotation.Nullable;
import java.lang.annotation.Annotation;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import static net.bytebuddy.matcher.ElementMatchers.any;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
public class CallTracker<A extends Annotation> extends GenericReflectClass<A> {
private static final AtomicReference<Class<? extends Annotation>> atomicClass = new AtomicReference<>();
public CallTracker(CallInterceptor interceptor) {
super();
atomicClass.set(this.persistentClass);
}
public static void premain(String agentArgs, Instrumentation inst) {
ByteBuddyAgent.install();
new AgentBuilder.Default()
.type(any()) // instrument all classes, you can restrict here
.transform((builder, type, classLoader, module, protectionDomain) ->
builder.visit(Advice.to(CallInterceptor.class).on(isMethod()))
).installOn(inst);
}
public abstract static class CallInterceptor {
private static Set<CallInterceptor> interceptors = new HashSet<>();
public CallInterceptor() {
interceptors.add(this);
}
/**
* Code executed on any method call
*/
public abstract void onCall(Method method, @Nullable StackTraceElement callerMethod);
@Advice.OnMethodEnter
static void intercept(@Advice.Origin Method method) {
for(CallInterceptor interceptor : interceptors) {
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
if (stack.length <= 3)
return;
StackTraceElement caller = stack[3];
interceptor.onCall(method, caller);
}
// if (method.isAnnotationPresent(atomicClass.get())) {
// StackTraceElement[] stack = Thread.currentThread().getStackTrace();
// // stack[0] = getStackTrace
// // stack[1] = intercept
// // stack[2] = Advice dispatcher
// // stack[3+] = your actual caller
// if (stack.length <= 3)
// return;
//
//
//
// StackTraceElement caller = stack[3];
//
// System.out.println("Annotated method " + method.getName()
// + " was called by " + caller.getClassName() + "." + caller.getMethodName());
//
// }
}
}
}

View File

@@ -0,0 +1,99 @@
// Author: maple
// date: 9/29/25
package org.openautonomousconnection.protocol.annotations.processing;
import dev.unlegitdqrk.unlegitlibrary.reflections.annotation.processing.AnnotationProcessor;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.exceptions.IncompatibleProtocolException;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import javax.annotation.Nullable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/**
* Process ProtocolInfo annotation and throw exception on mismatching annotation and ProtocolSide
*/
public class ProtocolInfoProcessing extends AnnotationProcessor<ProtocolInfo> {
private final CallTracker<ProtocolInfo> tracker;
private final AtomicReference<Set<Method>> methodReferences = new AtomicReference<>();
private final AtomicReference<Set<Class<?>>> typeReferences = new AtomicReference<>();
public ProtocolInfoProcessing() {
super("org.openautonomousconnection.protocol");
this.process();
this.methodReferences.set(this.annotatedMethods);
this.typeReferences.set(this.annotatedTypes);
this.tracker = new CallTracker<>(new CallTracker.CallInterceptor() {
@Override
public void onCall(Method method, @Nullable StackTraceElement callerMethod) {
ProtocolVersion.ProtocolSide side, callerSide;
Object o;
if((o = methodGetByName(callerMethod.getMethodName())) != null)
callerSide = ((Method) o).getAnnotation(ProtocolInfo.class).protocolSide();
else if((o = typeHasAnnotation(callerMethod.getClassName())) != null)
callerSide = ((Class<?>) o).getAnnotation(ProtocolInfo.class).protocolSide();
else
return;
if(methodReferences.get().contains(method))
side = method.getAnnotation(ProtocolInfo.class).protocolSide();
else if(typeReferences.get().contains(method.getDeclaringClass()))
side = method.getDeclaringClass().getAnnotation(ProtocolInfo.class).protocolSide();
else
return;
if(callerSide.equals(ProtocolVersion.ProtocolSide.CLIENT) &&
!side.equals(callerSide))
throw new IncompatibleProtocolException(callerSide, side);
}
});
}
private Method methodGetByName(String methodName) {
for(Method method : this.annotatedMethods)
if(method.getName().equals(methodName))
return method;
return null;
}
private Class<?> typeHasAnnotation(String typeName) {
for(Class<?> type : this.annotatedTypes)
if(type.getName().equals(typeName))
return type;
return null;
}
@Override
protected void processType(Class<?> type) {
}
@Override
protected void processMethod(Method method) {
}
@Override
protected void processField(Field field) {
}
@Override
protected void processConstructor(Constructor constructor) {
}
}

View File

@@ -0,0 +1,9 @@
package org.openautonomousconnection.protocol.exceptions;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
public class IncompatibleProtocolException extends RuntimeException {
public IncompatibleProtocolException(ProtocolVersion.ProtocolSide callerSide, ProtocolVersion.ProtocolSide side) {
super(callerSide.name() + " is incompatible with called method of ProtocolSide " + side.name());
}
}

View File

@@ -0,0 +1,27 @@
package org.openautonomousconnection.protocol.exceptions;
/**
* Exception thrown when an unsupported protocol is encountered.
*/
public final 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);
}
}

View File

@@ -0,0 +1,45 @@
package org.openautonomousconnection.protocol.listeners;
import dev.unlegitdqrk.unlegitlibrary.event.EventListener;
import dev.unlegitdqrk.unlegitlibrary.event.Listener;
import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.ClientConnectedEvent;
import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.ClientDisconnectedEvent;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.AuthPacket;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import java.io.IOException;
/**
* Listener for client-side events such as connection and disconnection.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.CLIENT)
public final class ClientListener extends EventListener {
/**
* Handles the event when a client connects.
* Sends an authentication packet to the server.
* @param event The client connected event.
*/
@Listener
public void onConnect(ClientConnectedEvent event) {
try {
event.getClient().sendPacket(new AuthPacket());
} catch (IOException | ClassNotFoundException exception) {
ProtocolBridge.getInstance().getLogger().exception("Failed to send auth packet", exception);
event.getClient().disconnect();
}
}
/**
* Handles the event when a client disconnects.
* Notifies the protocol client of the disconnection.
* @param event The client disconnected event.
*/
@Listener
public void onDisconnect(ClientDisconnectedEvent event) {
ProtocolBridge.getInstance().getProtocolClient().onDNSDisconnect(event);
}
}

View File

@@ -0,0 +1,39 @@
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.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.side.dns.ConnectedProtocolClient;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
/**
* Listener for DNS server connection events.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.DNS)
public final class DNSServerListener extends EventListener {
/**
* Handles the event when a connection handler connects to the DNS server.
* Adds the connected client to the ProtocolBridge's DNS server client list.
* @param event The connection handler connected event.
*/
@Listener
public void onConnect(ConnectionHandlerConnectedEvent event) {
ProtocolBridge.getInstance().getProtocolDNSServer().getClients().add(new ConnectedProtocolClient(event.getConnectionHandler()));
}
/**
* Handles the event when a connection handler disconnects from the DNS server.
* Removes the disconnected client from the ProtocolBridge's DNS server client list.
* @param event The connection handler disconnected event.
*/
@Listener
public void onDisconnect(ConnectionHandlerDisconnectedEvent event) {
ProtocolBridge.getInstance().getProtocolDNSServer().getClients().removeIf(client ->
client.getConnectionHandler().getClientID() == -1);
}
}

View File

@@ -0,0 +1,38 @@
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.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.side.web.ConnectedWebClient;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
/**
* Listener for web server connection events.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.WEB)
public final class WebServerListener extends EventListener {
/**
* Handles the event when a connection is established.
* Adds the connected client to the protocol web server's client list.
* @param event The connection handler connected event.
*/
@Listener
public void onConnect(ConnectionHandlerConnectedEvent event) {
ProtocolBridge.getInstance().getProtocolWebServer().getClients().add(new ConnectedWebClient(event.getConnectionHandler()));
}
/**
* Handles the event when a connection is disconnected.
* Removes the disconnected client from the protocol web server's client list.
* @param event The connection handler disconnected event.
*/
@Listener
public void onDisconnect(ConnectionHandlerDisconnectedEvent event) {
ProtocolBridge.getInstance().getProtocolWebServer().getClients().removeIf(client -> client.getPipelineConnection().getClientID() == -1);
}
}

View File

@@ -0,0 +1,110 @@
package org.openautonomousconnection.protocol.packets;
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.Packet;
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
import lombok.Getter;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* Abstract class representing a packet in the Open Autonomous Connection (OAC) protocol.
* This class extends the base Packet class and includes additional functionality specific to OAC.
*/
public abstract class OACPacket extends Packet {
/**
* The protocol version associated with this packet.
*/
@Getter
private final ProtocolVersion protocolVersion;
/**
* The response code for the packet, defaulting to RESPONSE_NOT_REQUIRED.
*/
private DNSResponseCode responseCode = DNSResponseCode.RESPONSE_NOT_REQUIRED;
/**
* Constructor for OACPacket.
* @param id The unique identifier for the packet.
* @param protocolVersion The protocol version associated with this packet.
*/
public OACPacket(int id, ProtocolVersion protocolVersion) {
super(id);
this.protocolVersion = protocolVersion;
}
/**
* Gets the response code for the packet.
* @return The DNSResponseCode associated with the packet.
*/
protected final DNSResponseCode getResponseCode() {
return responseCode;
}
/**
* Sets the response code for the packet.
* @param responseCode The DNSResponseCode to set for the packet.
*/
protected final void setResponseCode(DNSResponseCode responseCode) {
this.responseCode = responseCode;
}
/**
* Writes the packet data to the output stream.
* @param packetHandler The packet handler managing the packet.
* @param objectOutputStream The output stream to write the packet data to.
* @throws IOException If an I/O error occurs.
* @throws ClassNotFoundException If a class cannot be found during serialization.
*/
@Override
public final void write(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException {
// Write the specific packet data
onWrite(packetHandler, objectOutputStream);
// Write the response code if the protocol version is not classic
if (protocolVersion != ProtocolVersion.PV_1_0_0_CLASSIC) objectOutputStream.writeObject(responseCode);
}
@Override
public final void read(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
// Read the specific packet data
onRead(packetHandler, objectInputStream);
// Read the response code if the protocol version is not classic
if (protocolVersion != ProtocolVersion.PV_1_0_0_CLASSIC) responseCode = (DNSResponseCode) objectInputStream.readObject();
else responseCode = DNSResponseCode.RESPONSE_NOT_REQUIRED;
// Call the response code read handler
onResponseCodeRead(packetHandler, objectInputStream);
}
/**
* Abstract method to be implemented by subclasses for writing specific packet data.
* @param packetHandler The packet handler managing the packet.
* @param objectOutputStream The output stream to write the packet data to.
* @throws IOException If an I/O error occurs.
* @throws ClassNotFoundException If a class cannot be found during serialization.
*/
public abstract void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException;
/**
* Abstract method to be implemented by subclasses for reading specific packet data.
* @param packetHandler The packet handler managing the packet.
* @param objectInputStream The input stream to read the packet data from.
* @throws IOException If an I/O error occurs.
* @throws ClassNotFoundException If a class cannot be found during deserialization.
*/
public abstract void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException;
/**
* Method called after the response code has been read from the input stream.
* Subclasses can override this method to handle any additional logic based on the response code.
* @param packetHandler The packet handler managing the packet.
* @param objectInputStream The input stream from which the response code was read.
*/
protected void onResponseCodeRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) {}
}

View File

@@ -1,42 +1,40 @@
package github.openautonomousconnection.protocol.packets.v1_0_0.beta;
package org.openautonomousconnection.protocol.packets.v1_0_0.beta;
import github.openautonomousconnection.protocol.ProtocolBridge;
import github.openautonomousconnection.protocol.packets.OACPacket;
import github.openautonomousconnection.protocol.side.client.events.ConnectedToProtocolServer;
import github.openautonomousconnection.protocol.side.server.ConnectedProtocolClient;
import github.openautonomousconnection.protocol.side.server.events.ProtocolClientConnected;
import github.openautonomousconnection.protocol.versions.ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode;
import me.finn.unlegitlibrary.file.FileUtils;
import me.finn.unlegitlibrary.network.system.packets.PacketHandler;
import me.finn.unlegitlibrary.network.system.server.ConnectionHandler;
import me.finn.unlegitlibrary.network.utils.NetworkUtils;
import dev.unlegitdqrk.unlegitlibrary.file.FileUtils;
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectionHandler;
import dev.unlegitdqrk.unlegitlibrary.network.utils.NetworkUtils;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.packets.OACPacket;
import org.openautonomousconnection.protocol.side.client.events.ConnectedToProtocolDNSServerEvent;
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.versions.ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class AuthPacket extends OACPacket {
public final class AuthPacket extends OACPacket {
File certificatesFolder = new File("certificates");
File publicFolder = new File(certificatesFolder, "public");
File publicCAFolder = new File(publicFolder, "ca");
File publicServerFolder = new File(publicFolder, "server");
File privateFolder = new File(certificatesFolder, "private");
File privateCAFolder = new File(privateFolder, "ca");
File privateServerFolder = new File(privateFolder, "server");
// Registration Constructor
public AuthPacket() {
super(4, ProtocolVersion.PV_1_0_0_BETA);
}
File certificatesFolder = new File("certificates");
File publicFolder = new File(certificatesFolder, "public");
File privateFolder = new File(certificatesFolder, "private");
File privateCAFolder = new File(privateFolder, "ca");
File privateServerFolder = new File(privateFolder, "server");
File publicCAFolder = new File(publicFolder, "ca");
File publicServerFolder = new File(publicFolder, "server");
@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 +42,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 +64,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 +84,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);
@@ -127,7 +130,7 @@ public class AuthPacket extends OACPacket {
}
ProtocolBridge.getInstance().getProtocolClient().setServerVersion(serverVersion);
ProtocolBridge.getInstance().getProtocolSettings().eventManager.executeEvent(new ConnectedToProtocolServer());
ProtocolBridge.getInstance().getProtocolSettings().eventManager.executeEvent(new ConnectedToProtocolDNSServerEvent());
}
}
}

View File

@@ -1,22 +1,23 @@
package github.openautonomousconnection.protocol.packets.v1_0_0.beta;
package org.openautonomousconnection.protocol.packets.v1_0_0.beta;
import github.openautonomousconnection.protocol.ProtocolBridge;
import github.openautonomousconnection.protocol.packets.OACPacket;
import github.openautonomousconnection.protocol.versions.ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode;
import github.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain;
import me.finn.unlegitlibrary.network.system.packets.PacketHandler;
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.packets.OACPacket;
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;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class GetDestinationPacket extends OACPacket {
public final class GetDestinationPacket extends OACPacket {
private Domain domain;
private int clientID;
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);
}
}
}

View File

@@ -1,25 +1,27 @@
package github.openautonomousconnection.protocol.packets.v1_0_0.beta;
package org.openautonomousconnection.protocol.packets.v1_0_0.beta;
import github.openautonomousconnection.protocol.ProtocolBridge;
import github.openautonomousconnection.protocol.packets.OACPacket;
import github.openautonomousconnection.protocol.versions.ProtocolVersion;
import github.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode;
import me.finn.unlegitlibrary.network.system.packets.PacketHandler;
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.packets.OACPacket;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.DNSResponseCode;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class UnsupportedClassicPacket extends OACPacket {
public final class UnsupportedClassicPacket extends OACPacket {
private Class<? extends OACPacket> unsupportedClassicPacket;
private Object[] content;
// Constructor with more information
public UnsupportedClassicPacket(Class<? extends OACPacket> 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,12 @@ 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().getClassicHandlerDNSServer().unsupportedClassicPacket(className, content, ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID));
else if (ProtocolBridge.getInstance().isRunningAsClient())
ProtocolBridge.getInstance().getClassicHandlerClient().unsupportedClassicPacket(className, content);
else if (ProtocolBridge.getInstance().isRunningAsWebServer())
ProtocolBridge.getInstance().getClassicHandlerWebServer().unsupportedClassicPacket(className, content, ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID));
}
}

View File

@@ -0,0 +1,56 @@
package org.openautonomousconnection.protocol.packets.v1_0_0.beta;
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.packets.OACPacket;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public final class ValidateDomainPacket extends OACPacket {
private Domain domain;
private int clientID;
public ValidateDomainPacket(Domain domain) {
this();
this.domain = domain;
}
public ValidateDomainPacket() {
super(6, ProtocolVersion.PV_1_0_0_BETA);
}
@Override
public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException {
if (ProtocolBridge.getInstance().isRunningAsClient())
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().isRunningAsDNSServer()) clientID = objectInputStream.readInt();
domain = (Domain) objectInputStream.readObject();
}
@Override
protected void onResponseCodeRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) {
super.onResponseCodeRead(packetHandler, objectInputStream);
if (ProtocolBridge.getInstance().isRunningAsDNSServer()) {
try {
ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID).getConnectionHandler().sendPacket(new ValidateDomainPacket(domain));
} catch (IOException | ClassNotFoundException e) {
ProtocolBridge.getInstance().getProtocolDNSServer().validationPacketSendFailed(domain, ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID), e);
}
} else if (ProtocolBridge.getInstance().isRunningAsClient())
ProtocolBridge.getInstance().getProtocolClient().validationCompleted(domain, getResponseCode());
}
}

View File

@@ -0,0 +1,85 @@
package org.openautonomousconnection.protocol.packets.v1_0_0.classic;
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
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.classic.objects.Classic_Domain;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.events.Classic_DomainPacketReceivedEvent;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils.Classic_ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_RequestDomain;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.SQLException;
public final class Classic_DomainPacket extends OACPacket {
private Classic_RequestDomain requestDomain;
private Classic_Domain domain;
private int clientID;
public Classic_DomainPacket(int toClient, Classic_RequestDomain requestDomain, Classic_Domain domain) {
this();
this.clientID = toClient;
this.requestDomain = requestDomain;
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().isRunningAsDNSServer()) {
objectOutputStream.writeInt(clientID);
objectOutputStream.writeObject(requestDomain);
objectOutputStream.writeObject(domain);
} else if (ProtocolBridge.getInstance().isRunningAsClient()) {
clientID = ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getClientID();
objectOutputStream.writeInt(clientID);
objectOutputStream.writeObject(requestDomain);
}
objectOutputStream.writeObject(Classic_ProtocolVersion.PV_1_0_0);
}
@Override
public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
if (ProtocolBridge.getInstance().isRunningAsDNSServer()) {
clientID = objectInputStream.readInt();
requestDomain = (Classic_RequestDomain) objectInputStream.readObject();
Classic_ProtocolVersion protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject();
try {
domain = ProtocolBridge.getInstance().getClassicHandlerDNSServer().getDomain(requestDomain);
} catch (SQLException exception) {
exception.printStackTrace();
}
ProtocolBridge.getInstance().getProtocolDNSServer().getNetworkServer().getEventManager().executeEvent(new Classic_DomainPacketReceivedEvent(protocolVersion, domain, requestDomain, clientID));
if (ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID).supportClientClassic())
ProtocolBridge.getInstance().getProtocolDNSServer().getNetworkServer().getConnectionHandlerByID(clientID).sendPacket(new Classic_DomainPacket(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().getClientDNSConnection().getEventManager().executeEvent(new Classic_DomainPacketReceivedEvent(protocolVersion, domain, requestDomain, clientID));
} else if (ProtocolBridge.getInstance().isRunningAsWebServer()) {
clientID = objectInputStream.readInt();
requestDomain = (Classic_RequestDomain) objectInputStream.readObject();
Classic_ProtocolVersion protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject();
ProtocolBridge.getInstance().getProtocolWebServer().getPipelineServer().getConnectionHandlerByID(clientID).sendPacket(new UnsupportedClassicPacket(Classic_PingPacket.class, new Object[]{clientID, requestDomain, domain}));
}
}
}

View File

@@ -0,0 +1,62 @@
package org.openautonomousconnection.protocol.packets.v1_0_0.classic;
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.packets.OACPacket;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils.Classic_ProtocolVersion;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public final 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;
this.clientID = toClient;
}
public Classic_MessagePacket() {
super(3, ProtocolVersion.PV_1_0_0_CLASSIC);
}
@Override
public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException {
if (ProtocolBridge.getInstance().isRunningAsDNSServer() || ProtocolBridge.getInstance().isRunningAsWebServer()) objectOutputStream.writeInt(clientID);
else if (ProtocolBridge.getInstance().isRunningAsClient()) {
clientID = ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getClientID();
objectOutputStream.writeInt(clientID);
}
objectOutputStream.writeUTF(message);
objectOutputStream.writeObject(Classic_ProtocolVersion.PV_1_0_0);
}
@Override
public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
if (ProtocolBridge.getInstance().isRunningAsDNSServer()) {
clientID = objectInputStream.readInt();
String message = objectInputStream.readUTF();
Classic_ProtocolVersion protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject();
ProtocolBridge.getInstance().getClassicHandlerDNSServer().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();
ProtocolBridge.getInstance().getClassicHandlerClient().handleMessage(message, protocolVersion);
} else if (ProtocolBridge.getInstance().isRunningAsWebServer()) {
clientID = objectInputStream.readInt();
String message = objectInputStream.readUTF();
Classic_ProtocolVersion protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject();
ProtocolBridge.getInstance().getClassicHandlerWebServer().handleMessage(ProtocolBridge.getInstance().getProtocolDNSServer().getClientByID(clientID), message, protocolVersion);
}
}
}

View File

@@ -0,0 +1,91 @@
package org.openautonomousconnection.protocol.packets.v1_0_0.classic;
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
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.objects.Classic_Domain;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.events.Classic_PingPacketReceivedEvent;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils.Classic_ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_RequestDomain;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.SQLException;
public final class Classic_PingPacket extends OACPacket {
private Classic_RequestDomain requestDomain;
private Classic_Domain domain;
private int clientID;
private boolean reachable;
private Classic_ProtocolVersion protocolVersion;
public Classic_PingPacket(Classic_RequestDomain requestDomain, Classic_Domain domain, boolean reachable) {
this();
this.requestDomain = requestDomain;
this.domain = domain;
this.reachable = reachable;
this.protocolVersion = Classic_ProtocolVersion.PV_1_0_0;
}
public Classic_PingPacket() {
super(1, ProtocolVersion.PV_1_0_0_CLASSIC);
}
@Override
public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException {
if (ProtocolBridge.getInstance().isRunningAsDNSServer()) {
objectOutputStream.writeInt(clientID);
objectOutputStream.writeObject(requestDomain);
objectOutputStream.writeObject(domain);
objectOutputStream.writeBoolean(reachable);
} else if (ProtocolBridge.getInstance().isRunningAsClient()) {
clientID = ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getClientID();
objectOutputStream.writeInt(clientID);
objectOutputStream.writeObject(requestDomain);
}
objectOutputStream.writeObject(protocolVersion);
}
@Override
public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
if (ProtocolBridge.getInstance().isRunningAsDNSServer()) {
clientID = objectInputStream.readInt();
requestDomain = (Classic_RequestDomain) objectInputStream.readObject();
protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject();
try {
domain = ProtocolBridge.getInstance().getClassicHandlerDNSServer().ping(requestDomain);
} catch (SQLException exception) {
exception.printStackTrace();
}
reachable = domain != null;
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().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().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));
} else if (ProtocolBridge.getInstance().isRunningAsWebServer()) {
clientID = objectInputStream.readInt();
requestDomain = (Classic_RequestDomain) objectInputStream.readObject();
protocolVersion = (Classic_ProtocolVersion) objectInputStream.readObject();
ProtocolBridge.getInstance().getProtocolWebServer().getPipelineServer().getConnectionHandlerByID(clientID).sendPacket(new UnsupportedClassicPacket(Classic_PingPacket.class, new Object[]{requestDomain}));
}
}
}

View File

@@ -0,0 +1,368 @@
package org.openautonomousconnection.protocol.side.client;
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 lombok.Getter;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
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;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_RequestDomain;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.cert.CertificateException;
/**
* Abstract class defining the client-side protocol operations and interactions with DNS and web servers.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.DNS)
public abstract class ProtocolClient extends DefaultMethodsOverrider {
/**
* Handles everything with DNS-Connection.
*/
private final NetworkClient clientToDNS;
/**
* Manages the folder structure for client certificates.
*/
@Getter
private final ClientCertificateFolderStructure folderStructure;
/**
* Manages the web connection to the destination server.
*/
@Getter
private WebClient webClient;
/**
* Stores the protocol version of the connected server.
*/
private ProtocolVersion serverVersion = null;
/**
* Initializes the ProtocolClient, setting up certificate folders and the DNS client connection.
* @throws CertificateException if there are issues with the certificates.
* @throws IOException if there are I/O issues during initialization.
*/
public ProtocolClient() throws CertificateException, IOException {
// Initialize and verify certificate folders and files
folderStructure = new ClientCertificateFolderStructure();
// Initialize connection to DNS server
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();
}
/**
* Gets the DNS connection client.
* @return the NetworkClient handling the DNS connection.
*/
public final NetworkClient getClientDNSConnection() {
return clientToDNS;
}
/**
* Creates a web connection to the specified domain and ports.
* @param domain the target domain for the web connection.
* @param pipelinePort the port used for the pipeline connection.
* @param webPort the port used for the web connection.
* @throws Exception if there are issues creating the web connection or if the protocol is unsupported.
*/
public final void createWebConnection(Domain domain, int pipelinePort, int webPort) throws Exception {
// Ensure the protocol supports web connections
if (!ProtocolBridge.getInstance().isProtocolSupported(ProtocolVersion.Protocol.OAC))
throw new UnsupportedProtocolException();
// Check if web client is already connected and close it
if (webClient != null) {
try {
webClient.closeConnection();
} catch (IOException e) {
ProtocolBridge.getInstance().getLogger().exception("Failed to close connection to web server", e);
return;
}
}
// Verify necessary certificate files exist
webClient = new WebClient(domain, pipelinePort, webPort);
}
/**
* Checks if the required certificate files exist in the specified folder.
* @param folder the folder to check for certificate files.
* @param prefix the prefix of the certificate files.
* @param extension the extension of the certificate files.
* @throws CertificateException if any required certificate file is missing or invalid.
* @throws IOException if there are I/O issues during the check.
*/
private final void checkFileExists(File folder, String prefix, String extension) throws CertificateException, IOException {
boolean found = false;
// Check if folder exists
if (folder == null) throw new FileNotFoundException("Folder does not exist");
// List files in the folder
File[] files = folder.listFiles();
// Check if folder is empty
if (files == null || files.length == 0)
throw new FileNotFoundException("Folder " + folder.getAbsolutePath() + " is empty");
// Validate each file in the folder
for (File file : files) {
if (!file.getName().startsWith(prefix) || !file.getName().endsWith(extension))
throw new CertificateException(file.getAbsolutePath() + " is not valid");
// Check for specific files
if (!found) found = file.getName().equalsIgnoreCase(prefix + NetworkUtils.getPublicIPAddress() + extension);
}
// If the specific file is not found, throw an exception
if (!found) throw new CertificateException("Missing " + prefix + NetworkUtils.getPublicIPAddress() + extension);
}
/**
* Gets the protocol version of the connected server.
* @return the ProtocolVersion of the server, or PV_1_0_0_CLASSIC if not set.
*/
public final ProtocolVersion getServerVersion() {
return serverVersion == null ? ProtocolVersion.PV_1_0_0_CLASSIC : serverVersion;
}
/**
* Sets the protocol version of the connected server.
* @param serverVersion the ProtocolVersion to set for the server.
*/
public final void setServerVersion(ProtocolVersion serverVersion) {
if (serverVersion == null) this.serverVersion = serverVersion;
}
/**
* Handles DNS disconnection events, resetting the server version and closing the web client connection if necessary.
* @param event the ClientDisconnectedEvent triggered on DNS disconnection.
*/
public final void onDNSDisconnect(ClientDisconnectedEvent event) {
// Reset server version on DNS disconnect
serverVersion = null;
// Close web client connection if it exists
if (webClient != null) {
try {
webClient.closeConnection();
} catch (IOException e) {
ProtocolBridge.getInstance().getLogger().exception("Failed to close connection to web server", e);
}
}
}
/**
* Checks if the connected server is a stable server.
* @return true if the server is stable, false otherwise.
*/
public final boolean isStableServer() {
// Check if the server version is stable
return !isBetaServer() && !isClassicServer();
}
/**
* Checks if the connected server or its compatible versions support stable protocol.
* @return true if stable protocol is supported, false otherwise.
*/
public final boolean supportServerStable() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) {
// Check if compatible version is stable
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.STABLE;
if (yes) break;
}
// Check if the server version is stable
return isStableServer() || yes;
}
/**
* Checks if the connected server is a beta server.
* @return true if the server is beta, false otherwise.
*/
public final boolean isBetaServer() {
// Check if the server version is beta
return getServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.BETA;
}
/**
* Checks if the connected server or its compatible versions support beta protocol.
* @return true if beta protocol is supported, false otherwise.
*/
public final boolean supportServerBeta() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) {
// Check if compatible version is beta
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.BETA;
if (yes) break;
}
// Check if the server version is beta
return isBetaServer() || yes;
}
/**
* Checks if the connected server is a classic server.
* @return true if the server is classic, false otherwise.
*/
public final boolean isClassicServer() {
// Check if the server version is classic
return getServerVersion().getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
}
/**
* Checks if the connected server or its compatible versions support classic protocol.
* @return true if classic protocol is supported, false otherwise.
*/
public final boolean supportServerClassic() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) {
// Check if compatible version is classic
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
if (yes) break;
}
// Check if the server version is classic
return isClassicServer() || yes;
}
/**
* Checks if the connected server supports the protocol version of the given packet.
* @param packet the OACPacket to check against the server's supported protocol version.
* @return true if the server supports the packet's protocol version, false otherwise.
*/
public final boolean supportServerPacket(OACPacket packet) {
// Check if the server supports the protocol version of the packet
return supportServerVersion(packet.getProtocolVersion());
}
/**
* Checks if the connected server or its compatible versions support the specified protocol version.
* @param targetVersion the ProtocolVersion to check for support.
* @return true if the server or its compatible versions support the target version, false otherwise.
*/
public final boolean supportServerVersion(ProtocolVersion targetVersion) {
// Directly check if the server version matches or is in the list of compatible versions
return getServerVersion() == targetVersion || getServerVersion().getCompatibleVersions().contains(targetVersion);
}
/**
* Checks if the connected server or its compatible versions support the specified protocol.
* @param protocol the Protocol to check for support.
* @return true if the server or its compatible versions support the protocol, false otherwise.
*/
public final boolean supportServerProtocol(ProtocolVersion.Protocol protocol) {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getServerVersion().getCompatibleVersions()) {
// Check if compatible version supports the protocol
yes = compatibleVersion.getSupportedProtocols().contains(protocol);
if (yes) break;
}
// Check if the server version supports the protocol
return getServerVersion().getSupportedProtocols().contains(protocol) || yes;
}
/**
* Validates the specified domain by sending a validation request to the DNS server.
* @param domain the Domain to validate.
* @throws IOException if there are I/O issues during the validation process.
* @throws ClassNotFoundException if there are issues with class loading during packet handling.
*/
public final void validateDomain(Domain domain) throws IOException, ClassNotFoundException {
// Send Classic_PingPacket if classic protocol is supported
Classic_PingPacket cPingPacket = new Classic_PingPacket(new Classic_RequestDomain(domain.getName(), domain.getTopLevelName(), domain.getPath()), null, false);
if (ProtocolBridge.getInstance().isClassicSupported()) clientToDNS.sendPacket(cPingPacket);
// Send ValidateDomainPacket
clientToDNS.sendPacket(new ValidateDomainPacket(domain));
}
/**
* Requests the destination for the specified domain from the DNS server.
* @param domain the Domain for which to request the destination.
* @param responseCode the expected DNSResponseCode for the request.
* @throws IOException if there are I/O issues during the request process.
* @throws ClassNotFoundException if there are issues with class loading during packet handling.
*/
public final void requestDestination(Domain domain, DNSResponseCode responseCode) throws IOException, ClassNotFoundException {
// Send Classic_DomainPacket if classic protocol is supported
Classic_DomainPacket cDomainPacket = new Classic_DomainPacket(0, new Classic_RequestDomain(domain.getName(), domain.getTopLevelName(), domain.getPath()), null);
if (ProtocolBridge.getInstance().isClassicSupported()) clientToDNS.sendPacket(cDomainPacket);
// Send GetDestinationPacket
clientToDNS.sendPacket(new GetDestinationPacket(domain, responseCode));
}
/**
* Callback method invoked when domain validation is completed.
* @param domain the Domain that was validated.
* @param responseCode the DNSResponseCode resulting from the validation.
*/
public abstract void validationCompleted(Domain domain, DNSResponseCode responseCode);
/**
* Callback method invoked when the destination retrieval is completed.
* @param domain the Domain for which the destination was requested.
* @param destination the retrieved destination as a string.
* @param validationResponse the DNSResponseCode resulting from the destination retrieval.
*/
public abstract void getDestinationCompleted(Domain domain, String destination, DNSResponseCode validationResponse);
/**
* Manages the folder structure for client certificates.
*/
public final class ClientCertificateFolderStructure {
public final File certificatesFolder;
public final File publicFolder;
public final File privateFolder;
public final File privateCAFolder;
public final File privateClientFolder;
public final File publicCAFolder;
public final File publicClientFolder;
public ClientCertificateFolderStructure() {
certificatesFolder = new File("certificates");
publicFolder = new File(certificatesFolder, "public");
privateFolder = new File(certificatesFolder, "private");
privateCAFolder = new File(privateFolder, "ca");
privateClientFolder = new File(privateFolder, "client");
publicCAFolder = new File(publicFolder, "ca");
publicClientFolder = new File(publicFolder, "client");
if (!certificatesFolder.exists()) certificatesFolder.mkdirs();
if (!publicFolder.exists()) publicFolder.mkdirs();
if (!privateFolder.exists()) privateFolder.mkdirs();
if (!privateCAFolder.exists()) privateCAFolder.mkdirs();
if (!privateClientFolder.exists()) privateClientFolder.mkdirs();
if (!publicCAFolder.exists()) publicCAFolder.mkdirs();
if (!publicClientFolder.exists()) publicClientFolder.mkdirs();
}
}
}

View File

@@ -0,0 +1,228 @@
package org.openautonomousconnection.protocol.side.client;
import dev.unlegitdqrk.unlegitlibrary.network.system.client.NetworkClient;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
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;
/**
* WebClient handles secure connections to web servers through a pipeline connection.
* It manages SSL/TLS handshakes and data transmission over the established connection.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.DNS)
public final class WebClient {
/**
* NetworkClient instance for managing the pipeline connection to the web server.
*/
private final NetworkClient clientToWebPipeline;
/**
* SSLSocket for secure communication with the web server.
*/
private SSLSocket clientToWebServer;
/**
* Streams for object serialization over the SSL connection.
*/
private ObjectOutputStream outputStream;
/**
* Streams for object serialization over the SSL connection.
*/
private ObjectInputStream inputStream;
/**
* Thread for receiving data from the web server.
*/
private final Thread receiveThread = new Thread(this::receive);
/**
* Constructs a WebClient instance and establishes a secure connection to the web server.
* @param domain The domain information for the web server.
* @param pipelinePort The port for the pipeline connection.
* @param webPort The port for the web server connection.
* @throws Exception If an error occurs during connection setup.
*/
public WebClient(Domain domain, int pipelinePort, int webPort) throws Exception {
// Initialize and connect the pipeline client
clientToWebPipeline = new NetworkClient.ClientBuilder().
// Set logger from ProtocolBridge
setLogger(ProtocolBridge.getInstance().getLogger()).
// Set the destination and port for the pipeline connection
setHost(domain.getDestination()).setPort(pipelinePort).
// Configure packet handler and event manager
setPacketHandler(ProtocolBridge.getInstance().getProtocolSettings().packetHandler).
setEventManager(ProtocolBridge.getInstance().getProtocolSettings().eventManager).
// Set proxy and ssl parameters from DNS connection settings
setProxy(ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getProxy()).
setSSLParameters(ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().getSocket().getSSLParameters()).
// Set certificates and folders for SSL
setRootCAFolder(ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().publicCAFolder).
setClientCertificatesFolder(ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().publicClientFolder,
ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().privateClientFolder).
// Finalize the client setup
build();
// Connect to the pipeline
clientToWebPipeline.connect();
// Wait until the pipeline connection is established
while (!clientToWebPipeline.isConnected()) if (clientToWebPipeline.isConnected()) break;
// Create SSL socket factory using client certificates
SSLSocketFactory sslSocketFactory = NetworkClient.ClientBuilder.
createSSLSocketFactory(ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().publicCAFolder,
ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().publicClientFolder,
ProtocolBridge.getInstance().getProtocolClient().getFolderStructure().privateClientFolder);
// Get proxy settings from the pipeline client
Proxy proxy = clientToWebPipeline.getProxy();
// Establish SSL connection to the web server
SSLSocket tempSocket;
if (sslSocketFactory == null) {
throw new ConnectException("SSL socket factory not set. Client certificate required!");
} else {
// Create raw socket and wrap it in SSL socket
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;
// Configure SSL parameters
SSLParameters sslParameters = clientToWebPipeline.getSocket().getSSLParameters();
if (sslParameters != null) {
clientToWebServer.setSSLParameters(sslParameters);
} else {
// Set default to TLSv1.3 if no parameters are provided
SSLParameters defaultParams = clientToWebServer.getSSLParameters();
defaultParams.setProtocols(new String[]{"TLSv1.3"});
clientToWebServer.setSSLParameters(defaultParams);
}
// Configure socket options
clientToWebServer.setTcpNoDelay(true);
clientToWebServer.setSoTimeout(0);
try {
this.clientToWebServer.startHandshake();
} catch (Exception handshakeEx) {
throw new ConnectException("Handshake failed: " + handshakeEx.getMessage());
}
// Initialize object streams for communication
this.outputStream = new ObjectOutputStream(clientToWebServer.getOutputStream());
this.inputStream = new ObjectInputStream(clientToWebServer.getInputStream());
// Start the receive thread
this.receiveThread.start();
}
}
/**
* Gets the NetworkClient used for the pipeline connection to the web server.
* @return The NetworkClient connected to the web server pipeline.
*/
public NetworkClient getClientPipelineConnection() {
return clientToWebPipeline;
}
/**
* Gets the SSLSocket used for communication with the web server.
* @return The SSLSocket connected to the web server.
*/
public SSLSocket getClientWebConnection() {
return clientToWebServer;
}
/**
* Checks if the WebClient is currently connected to the web server.
* @return true if connected, false otherwise.
*/
public 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();
}
/**
* Continuously receives data from the web server.
* This method runs in a separate thread and handles incoming objects.
* If an error occurs, it attempts to close the connection.
*/
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);
}
}
}
/**
* Closes the connection to the web server and releases resources.
* @return true if the connection was successfully closed, false if it was already closed.
* @throws IOException If an I/O error occurs during closure.
*/
public synchronized boolean closeConnection() throws IOException {
if (!this.isConnected()) {
return false;
} else {
clientToWebPipeline.disconnect();
try {
// Interrupt the receive thread
this.receiveThread.interrupt();
// Close streams and socket
if (this.outputStream != null) {
this.outputStream.close();
}
if (this.inputStream != null) {
this.inputStream.close();
}
if (this.clientToWebServer != null) {
this.clientToWebServer.close();
}
} finally {
// Nullify references to help with garbage collection
this.clientToWebServer = null;
this.outputStream = null;
this.inputStream = null;
}
return true;
}
}
}

View File

@@ -0,0 +1,12 @@
package org.openautonomousconnection.protocol.side.client.events;
import dev.unlegitdqrk.unlegitlibrary.event.impl.Event;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
/**
* Event triggered when a client successfully connects to a DNS protocol server.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.DNS)
public final class ConnectedToProtocolDNSServerEvent extends Event {
}

View File

@@ -0,0 +1,158 @@
package org.openautonomousconnection.protocol.side.dns;
import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectionHandler;
import lombok.Getter;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.packets.OACPacket;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
/**
* Represents a connected protocol client on the DNS server side.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.DNS)
public final class ConnectedProtocolClient {
/**
* The connection handler associated with this protocol client.
*/
@Getter
private final ConnectionHandler connectionHandler;
/**
* The protocol version of the connected client.
*/
private ProtocolVersion clientVersion = null;
public ConnectedProtocolClient(ConnectionHandler connectionHandler) {
this.connectionHandler = connectionHandler;
}
/**
* Gets the protocol version of the connected client.
* Defaults to PV_1_0_0_CLASSIC if not set.
* @return The protocol version of the client.
*/
public ProtocolVersion getClientVersion() {
return clientVersion == null ? ProtocolVersion.PV_1_0_0_CLASSIC : clientVersion;
}
/**
* Sets the protocol version of the connected client.
* @param clientVersion The protocol version to set.
*/
public void setClientVersion(ProtocolVersion clientVersion) {
if (clientVersion == null) this.clientVersion = clientVersion;
}
/**
* Checks if the connected client is a stable client.
* @return True if the client is stable, false otherwise.
*/
public boolean isStableClient() {
// Check if the server version is stable
return !isBetaClient() && !isClassicClient();
}
/**
* Checks if the connected client supports stable protocol versions.
* @return True if the client supports stable versions, false otherwise.
*/
public boolean supportClientStable() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) {
// Check if compatible version is stable
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.STABLE;
if (yes) break;
}
// Check if the client version is stable
return isStableClient() || yes;
}
/**
* Checks if the connected client is a beta client.
* @return True if the client is beta, false otherwise.
*/
public boolean isBetaClient() {
// Check if the server version is beta
return getClientVersion().getProtocolType() == ProtocolVersion.ProtocolType.BETA;
}
/**
* Checks if the connected client supports beta protocol versions.
* @return True if the client supports beta versions, false otherwise.
*/
public boolean supportClientBeta() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) {
// Check if compatible version is beta
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.BETA;
if (yes) break;
}
// Check if the client version is beta
return isBetaClient() || yes;
}
/**
* Checks if the connected client is a classic client.
* @return True if the client is classic, false otherwise.
*/
public boolean isClassicClient() {
// Check if the server version is classic
return getClientVersion().getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
}
/**
* Checks if the connected client supports classic protocol versions.
* @return True if the client supports classic versions, false otherwise.
*/
public boolean supportClientClassic() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) {
// Check if compatible version is classic
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
if (yes) break;
}
// Check if the client version is classic
return isClassicClient() || yes;
}
/**
* Checks if the connected client supports the given packet's protocol version.
* @param packet The packet to check.
* @return True if the client supports the packet's protocol version, false otherwise.
*/
public boolean supportClientPacket(OACPacket packet) {
return supportClientVersion(packet.getProtocolVersion());
}
/**
* Checks if the connected client supports the given protocol version.
* @param targetVersion The protocol version to check.
* @return True if the client supports the target version, false otherwise.
*/
public boolean supportClientVersion(ProtocolVersion targetVersion) {
// Check if the client version matches or is compatible with the target version
return getClientVersion() == targetVersion || getClientVersion().getCompatibleVersions().contains(targetVersion);
}
/**
* Checks if the connected client supports the given protocol.
* @param protocol The protocol to check.
* @return True if the client supports the protocol, false otherwise.
*/
public boolean supportClientProtocol(ProtocolVersion.Protocol protocol) {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) {
// Check if compatible version supports the protocol
yes = compatibleVersion.getSupportedProtocols().contains(protocol);
if (yes) break;
}
// Check if the client version supports the protocol
return getClientVersion().getSupportedProtocols().contains(protocol) || yes;
}
}

View File

@@ -0,0 +1,261 @@
package org.openautonomousconnection.protocol.side.dns;
import dev.unlegitdqrk.unlegitlibrary.file.ConfigurationManager;
import dev.unlegitdqrk.unlegitlibrary.network.system.server.NetworkServer;
import dev.unlegitdqrk.unlegitlibrary.network.utils.NetworkUtils;
import dev.unlegitdqrk.unlegitlibrary.utils.DefaultMethodsOverrider;
import lombok.Getter;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
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;
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;
/**
* Abstract class representing a DNS server in the protocol.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.DNS)
public abstract class ProtocolDNSServer extends DefaultMethodsOverrider {
/**
* The network server instance.
*/
@Getter
private final NetworkServer networkServer;
/**
* The configuration manager for handling server configurations.
*/
private final ConfigurationManager configurationManager;
/**
* List of connected protocol clients.
*/
@Getter
private List<ConnectedProtocolClient> clients;
/**
* The folder structure for server certificates.
*/
@Getter
private ServerCertificateFolderStructure folderStructure;
/**
* Constructs a ProtocolDNSServer with the specified configuration file.
*
* @param configFile The configuration file for the DNS server.
* @throws IOException If an I/O error occurs.
* @throws CertificateException If a certificate error occurs.
*/
public ProtocolDNSServer(File configFile) throws IOException, CertificateException {
// Ensure the configuration file exists
if (!configFile.exists()) configFile.createNewFile();
// Load the configuration properties
configurationManager = new ConfigurationManager(configFile);
configurationManager.loadProperties();
// Set default values for configuration properties if not already set
if (!configurationManager.isSet("server.site.info")) {
configurationManager.set("server.site.info", "DNS-SERVER INFO SITE IP");
configurationManager.saveProperties();
}
if (!configurationManager.isSet("server.site.register")) {
configurationManager.set("server.site.register", "SERVER IP TO DNS-FRONTENT WEBSITE");
configurationManager.saveProperties();
}
// Initialize the folder structure
folderStructure = new ServerCertificateFolderStructure();
// Check for the existence of necessary certificate files
checkFileExists(folderStructure.publicCAFolder, folderStructure.caPrefix, ".pem");
checkFileExists(folderStructure.publicCAFolder, folderStructure.caPrefix, ".srl");
checkFileExists(folderStructure.privateCAFolder, folderStructure.caPrefix, ".key");
checkFileExists(folderStructure.publicServerFolder, folderStructure.certPrefix, ".crt");
checkFileExists(folderStructure.privateServerFolder, folderStructure.certPrefix, ".key");
// Define the certificate and key files based on the public IP address
File certFile = new File(folderStructure.publicServerFolder, folderStructure.certPrefix + NetworkUtils.getPublicIPAddress() + ".crt");
File keyFile = new File(folderStructure.privateServerFolder, folderStructure.certPrefix + NetworkUtils.getPublicIPAddress() + ".key");
// Initialize the protocol bridge and clients list
ProtocolBridge protocolBridge = ProtocolBridge.getInstance();
this.clients = new ArrayList<>();
// Build the network server with the specified settings
this.networkServer = new NetworkServer.ServerBuilder().
setLogger(protocolBridge.getLogger()).
setEventManager(protocolBridge.getProtocolSettings().eventManager).
setPacketHandler(protocolBridge.getProtocolSettings().packetHandler).
setPort(protocolBridge.getProtocolSettings().port).
setRequireClientCertificate(false).setRootCAFolder(folderStructure.publicCAFolder).setServerCertificate(certFile, keyFile).
build();
}
/**
* Checks if the required certificate files exist in the specified folder.
* @param folder The folder to check for certificate files.
* @param prefix The prefix of the certificate files.
* @param extension The extension of the certificate files.
* @throws CertificateException If a certificate error occurs.
* @throws IOException If an I/O error occurs.
*/
private final void checkFileExists(File folder, String prefix, String extension) throws CertificateException, IOException {
boolean found = false;
// Check if the folder exists
if (folder == null) throw new FileNotFoundException("Folder does not exist");
// List all files in the folder
File[] files = folder.listFiles();
// Check if the folder is empty
if (files == null || files.length == 0)
throw new FileNotFoundException("Folder " + folder.getAbsolutePath() + " is empty");
// Validate each file in the folder
for (File file : files) {
if (!file.getName().startsWith(prefix) || !file.getName().endsWith(extension))
throw new CertificateException(file.getAbsolutePath() + " is not valid");
// Check if the file matches the expected naming convention
if (!found) found = file.getName().equalsIgnoreCase(prefix + NetworkUtils.getPublicIPAddress() + extension);
}
// If the required file is not found, throw an exception
if (!found) throw new CertificateException("Missing " + prefix + NetworkUtils.getPublicIPAddress() + extension);
}
/**
* Retrieves a connected protocol client by its client ID.
* @param clientID The ID of the client to retrieve.
* @return The ConnectedProtocolClient with the specified ID, or null if not found.
*/
public final ConnectedProtocolClient getClientByID(int clientID) {
for (ConnectedProtocolClient client : clients)
if (client.getConnectionHandler().getClientID() == clientID) return client;
return null;
}
/**
* Gets the DNS information site URL from the configuration.
* @return The DNS information site URL.
*/
public final String getDNSInfoSite() {
return configurationManager.getString("server.site.info");
}
/**
* Gets the DNS registration site URL from the configuration.
* @return The DNS registration site URL.
*/
public final String getDNSRegisterSite() {
return configurationManager.getString("server.site.register");
}
/**
* Abstract method to retrieve the list of domains managed by the DNS server.
* @return A list of Domain objects.
*/
public abstract List<Domain> getDomains();
/**
* @see Domain#getDestination()
* Abstract method to get the destination for a given domain.
* @param domain The domain to look up.
* @return The destination associated with the domain.
*/
public abstract String getDomainDestination(Domain domain);
/**
* @see Domain#getDestination()
* Abstract method to get the destination for a given subname under a specific domain.
* @param domain The parent domain.
* @param subname The subname to look up.
* @return The destination associated with the subname.
*/
public abstract String getSubnameDestination(Domain domain, String subname);
/**
* @see Domain#getDestination()
* Abstract method to get the top-level domain information site URL.
* @param topLevelName The top-level domain name.
* @return The information site URL for the specified top-level domain.
*/
public abstract String getTLNInfoSite(String topLevelName);
/**
* Abstract method to validate a requested domain.
* @param requestedDomain The domain to validate.
* @return A DNSResponseCode indicating the result of the validation.
*/
public abstract DNSResponseCode validateDomain(Domain requestedDomain);
/**
* Abstract method called when a validation packet fails to send.
* @param domain The domain associated with the validation.
* @param client The connected protocol client.
* @param exception The exception that occurred during sending.
*/
public abstract void validationPacketSendFailed(Domain domain, ConnectedProtocolClient client, Exception exception);
/**
* Abstract method called when a domain destination packet fails to send.
* @param client The connected protocol client.
* @param domain The domain associated with the packet.
* @param validationResponse The DNS response code from validation.
* @param exception The exception that occurred during sending.
*/
public abstract void domainDestinationPacketFailedSend(ConnectedProtocolClient client, Domain domain, DNSResponseCode validationResponse, Exception exception);
/**
* Class representing the folder structure for server certificates.
*/
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 final String caPrefix = "ca_dns_";
public final String certPrefix = "cert_dns_";
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();
}
}
}

View File

@@ -0,0 +1,21 @@
package org.openautonomousconnection.protocol.side.dns.events;
import dev.unlegitdqrk.unlegitlibrary.event.impl.Event;
import lombok.Getter;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.side.dns.ConnectedProtocolClient;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
/**
* Event triggered when a protocol client connects to the DNS server.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.DNS)
public final class ConnectedProtocolClientEvent extends Event {
@Getter
private final ConnectedProtocolClient protocolClient;
public ConnectedProtocolClientEvent(ConnectedProtocolClient protocolClient) {
this.protocolClient = protocolClient;
}
}

View File

@@ -0,0 +1,692 @@
package org.openautonomousconnection.protocol.side.web;
import dev.unlegitdqrk.unlegitlibrary.network.system.server.ConnectionHandler;
import lombok.Getter;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
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.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
/**
* Represents a connected web client.
* Manages the connection, handles HTTP requests, and serves files.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.WEB)
public final class ConnectedWebClient {
/**
* The connection handler associated with this web client.
*/
@Getter
private final ConnectionHandler pipelineConnection;
/**
* The SSL socket for the web client connection.
*/
@Getter
private SSLSocket webSocket;
/**
* The output stream for sending data to the client.
*/
private ObjectOutputStream outputStream;
/**
* The input stream for receiving data from the client.
*/
private ObjectInputStream inputStream;
/**
* The protocol version of the connected client.
*/
private ProtocolVersion clientVersion = null;
/**
* Thread for receiving data from the client.
*/
private final Thread receiveThread = new Thread(this::receive);
/**
* Indicates if the client version has been loaded.
*/
@Getter
private boolean clientVersionLoaded = false;
/**
* Constructs a ConnectedWebClient with the given connection handler.
* @param pipelineConnection The connection handler for the web client.
*/
public ConnectedWebClient(ConnectionHandler pipelineConnection) {
this.pipelineConnection = pipelineConnection;
}
/**
* Sends an HTTP redirect response to the client.
* @param out The output stream to send the response to.
* @param location The URL to redirect to.
* @param cookies Optional cookies to set in the response.
* @throws IOException If an I/O error occurs.
*/
private static void sendRedirect(OutputStream out, String location, Map<String, String> cookies) throws IOException {
// Send HTTP 302 Found response with Location header
out.write(("OAC 302 Found\r\n").getBytes());
out.write(("Location: " + location + "\r\n").getBytes());
// Set cookies if provided
if (cookies != null) {
for (var entry : cookies.entrySet()) {
out.write((entry.getKey() + ": " + entry.getValue() + "\r\n").getBytes());
}
}
// End of headers
out.write("\r\n".getBytes());
out.flush();
}
/**
* Parses POST parameters from the input stream.
* @param in The input stream to read from.
* @return A map of POST parameter names to values.
* @throws IOException If an I/O error occurs.
*/
private static Map<String, String> parsePostParams(InputStream in) throws IOException {
// Read the entire input stream into a string
BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
while (reader.ready()) {
sb.append((char) reader.read());
}
// Split the string into key-value pairs and decode them
Map<String, String> map = new HashMap<>();
String[] pairs = sb.toString().split("&");
for (String p : pairs) {
// Split each pair into key and value
String[] kv = p.split("=", 2);
if (kv.length == 2)
// Decode and store in the map
map.put(URLDecoder.decode(kv[0], StandardCharsets.UTF_8), URLDecoder.decode(kv[1], StandardCharsets.UTF_8));
}
return map;
}
/**
* Normalizes a file path to prevent directory traversal attacks.
* @param path The raw file path.
* @return The normalized file path.
*/
private static String normalizePath(String path) {
// Replace backslashes with forward slashes and remove ".." segments
path = path.replace("/", File.separator).replace("\\", "/");
// Remove any ".." segments to prevent directory traversal
while (path.contains("..")) path = path.replace("..", "");
// Remove leading slashes
if (path.startsWith("/")) path = path.substring(1);
return path;
}
/**
* Parses query parameters from a raw URL path.
* @param rawPath The raw URL path containing query parameters.
* @return A map of query parameter names to values.
*/
private static Map<String, String> parseQueryParams(String rawPath) {
// Extract query parameters from the URL path
Map<String, String> map = new HashMap<>();
if (rawPath.contains("?")) {
// Split the query string into key-value pairs
String[] params = rawPath.substring(rawPath.indexOf("?") + 1).split("&");
for (String p : params) {
// Split each pair into key and value
String[] kv = p.split("=");
if (kv.length == 2) map.put(kv[0], kv[1]);
}
}
return map;
}
/**
* Checks if the request is a multipart/form-data request.
* @param headers The HTTP headers of the request.
* @return True if the request is multipart/form-data, false otherwise.
*/
private static boolean isMultipart(Map<String, String> headers) {
String contentType = headers.get("content-type");
return contentType != null && contentType.startsWith("multipart/form-data");
}
/**
* Handles a multipart/form-data request, saving uploaded files to the specified directory.
* @param in The input stream to read the request body from.
* @param headers The HTTP headers of the request.
* @param uploadDir The directory to save uploaded files to.
* @throws IOException If an I/O error occurs.
*/
private static void handleMultipart(InputStream in, Map<String, String> headers, File uploadDir) throws IOException {
// Ensure the upload directory exists
if (!uploadDir.exists()) uploadDir.mkdirs();
// Extract the boundary from the Content-Type header
String contentType = headers.get("content-type");
String boundary = "--" + contentType.split("boundary=")[1];
// Read the entire request body into a buffer
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
}
// Parse the multipart data
String data = buffer.toString(StandardCharsets.UTF_8);
String[] parts = data.split(boundary);
// Process each part
for (String part : parts) {
if (part.contains("Content-Disposition")) {
String name = null;
String filename = null;
// Extract headers from the part
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);
}
}
}
// Save the file if a filename is provided
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);
}
}
}
}
/**
* Sends an response to the client.
* @param out
* @param code
* @param file
* @param headers
* @throws IOException
*/
private static void sendResponse(OutputStream out, int code, File file, Map<String, String> headers) throws IOException {
byte[] body = Files.readAllBytes(file.toPath());
sendResponse(out, code, body, "text/html", headers);
}
/**
* Sends an response to the client.
* @param out The output stream to send the response to.
* @param code The HTTP status code.
* @param file The file to read the response body from.
* @throws IOException If an I/O error occurs.
*/
private static void sendResponse(OutputStream out, int code, File file) throws IOException {
sendResponse(out, code, Files.readString(file.toPath()), "text/html");
}
/**
* Sends an response to the client.
* @param out The output stream to send the response to.
* @param code The HTTP status code.
* @param body The response body as a string.
* @param contentType The content type of the response.
* @throws IOException If an I/O error occurs.
*/
private static void sendResponse(OutputStream out, int code, String body, String contentType) throws IOException {
sendResponse(out, code, body.getBytes(StandardCharsets.UTF_8), contentType, null);
}
/**
* Sends an response to the client.
* @param out The output stream to send the response to.
* @param code The HTTP status code.
* @param file The file to read the response body from.
* @param contentType The content type of the response.
* @throws IOException If an I/O error occurs.
*/
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);
}
/**
* Sends an response to the client.
* @param out The output stream to send the response to.
* @param code The HTTP status code.
* @param body The response body as a byte array.
* @param contentType The content type of the response.
* @param headers Additional headers to include in the response.
* @throws IOException If an I/O error occurs.
*/
private static void sendResponse(OutputStream out, int code, byte[] body, String contentType, Map<String, String> headers) throws IOException {
// Send response status line and headers
out.write(("OAC " + code + " " + getStatusText(code) + "\r\n").getBytes());
out.write(("Content-Type: " + contentType + "\r\n").getBytes());
out.write(("Content-Length: " + body.length + "\r\n").getBytes());
// Write additional headers if provided
if (headers != null) headers.forEach((k, v) -> {
try {
out.write((k + ": " + v + "\r\n").getBytes());
} catch (IOException ignored) {
}
});
// End of headers
out.write("\r\n".getBytes());
out.write(body);
out.flush();
}
/**
* Returns the standard status text for a given status code.
* @param code The status code.
* @return The corresponding status text.
*/
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";
};
}
/**
* Returns the content type based on the file extension.
* @param name The file name.
* @return The corresponding content type.
*/
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";
};
}
/**
* Renders a PHP file by executing it with the PHP interpreter and captures cookies.
* @param file The PHP file to render.
* @return A PHPResponse containing the output and cookies.
* @throws IOException If an I/O error occurs.
* @throws InterruptedException If the process is interrupted.
*/
private static PHPResponse renderPHPWithCookies(File file) throws IOException, InterruptedException {
// Execute the PHP file using the PHP interpreter
ProcessBuilder pb = new ProcessBuilder("php", file.getAbsolutePath());
pb.redirectErrorStream(true);
Process p = pb.start();
// Capture the output of the PHP process
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();
// Parse the output to separate headers and body, and extract cookies
String fullOutput = output.toString(StandardCharsets.UTF_8);
Map<String, String> cookies = new HashMap<>();
// Split headers and body
String[] parts = fullOutput.split("\r\n\r\n", 2);
String body;
if (parts.length == 2) {
// Get headers and body
String headers = parts[0];
body = parts[1];
// Extract cookies from headers
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 {
// No headers, only body
body = fullOutput;
}
return new PHPResponse(body, cookies);
}
/**
* Sets the SSL socket for the web client and starts the receive thread.
* @param webSocket The SSL socket to set.
*/
public void setWebSocket(SSLSocket webSocket) {
if (webSocket != null) this.webSocket = webSocket;
this.receiveThread.start();
}
/**
* Checks if the web client is currently connected.
* @return True if connected, false otherwise.
*/
public boolean isConnected() {
return this.webSocket != null && this.webSocket.isConnected() && !this.webSocket.isClosed() && this.receiveThread.isAlive() && pipelineConnection.isConnected();
}
/**
* Disconnects the web client, closing streams and the socket.
* @return True if disconnection was successful, false if already disconnected.
*/
public synchronized boolean disconnect() {
if (!this.isConnected()) {
return false;
} else {
// Disconnect the underlying connection handler
pipelineConnection.disconnect();
// Interrupt the receive thread if it's still alive
if (this.receiveThread.isAlive()) {
this.receiveThread.interrupt();
}
try {
// Close streams and the socket
this.outputStream.close();
this.inputStream.close();
this.webSocket.close();
} catch (IOException var2) {
}
// Nullify references
this.webSocket = null;
this.outputStream = null;
this.inputStream = null;
return true;
}
}
/**
* Gets the protocol version of the connected client.
* @return The protocol version of the client, defaults to PV_1_0_0_CLASSIC if not set.
*/
public ProtocolVersion getClientVersion() {
return clientVersion == null ? ProtocolVersion.PV_1_0_0_CLASSIC : clientVersion;
}
/**
* Sets the protocol version of the connected client.
* @param clientVersion The protocol version to set.
*/
public void setClientVersion(ProtocolVersion clientVersion) {
if (!clientVersionLoaded) clientVersionLoaded = true;
if (clientVersion == null) this.clientVersion = clientVersion;
}
/**
* Checks if the connected client is a stable client.
* @return True if the client is stable, false otherwise.
*/
public boolean isStableClient() {
// Check if the server version is stable
return !isBetaClient() && !isClassicClient();
}
/**
* Checks if the connected client supports stable protocol versions.
* @return True if the client supports stable versions, false otherwise.
*/
public boolean supportClientStable() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) {
// Check if compatible version is stable
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.STABLE;
if (yes) break;
}
// Check if the client version is stable
return isStableClient() || yes;
}
/**
* Checks if the connected client is a beta client.
* @return True if the client is beta, false otherwise.
*/
public boolean isBetaClient() {
// Check if the server version is beta
return getClientVersion().getProtocolType() == ProtocolVersion.ProtocolType.BETA;
}
/**
* Checks if the connected client supports beta protocol versions.
* @return True if the client supports beta versions, false otherwise.
*/
public boolean supportClientBeta() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) {
// Check if compatible version is beta
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.BETA;
if (yes) break;
}
// Check if the client version is beta
return isBetaClient() || yes;
}
/**
* Checks if the connected client is a classic client.
* @return True if the client is classic, false otherwise.
*/
public boolean isClassicClient() {
return getClientVersion().getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
}
/**
* Checks if the connected client supports classic protocol versions.
* @return True if the client supports classic versions, false otherwise.
*/
public boolean supportClientClassic() {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) {
// Check if compatible version is classic
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
if (yes) break;
}
// Check if the client version is classic
return isClassicClient() || yes;
}
/**
* Checks if the connected client supports the protocol version of the given packet.
* @param packet The packet to check support for.
* @return True if the client supports the packet's protocol version, false otherwise.
*/
public boolean supportClientPacket(OACPacket packet) {
return supportClientVersion(packet.getProtocolVersion());
}
/**
* Checks if the connected client supports the given protocol version.
* @param targetVersion The protocol version to check support for.
* @return True if the client supports the target version, false otherwise.
*/
public boolean supportClientVersion(ProtocolVersion targetVersion) {
// Check if the client version matches the target version or is compatible
return getClientVersion() == targetVersion || getClientVersion().getCompatibleVersions().contains(targetVersion);
}
/**
* Checks if the connected client supports the given protocol.
* @param protocol The protocol to check support for.
* @return True if the client supports the protocol, false otherwise.
*/
public boolean supportClientProtocol(ProtocolVersion.Protocol protocol) {
boolean yes = false;
for (ProtocolVersion compatibleVersion : getClientVersion().getCompatibleVersions()) {
// Check if compatible version supports the protocol
yes = compatibleVersion.getSupportedProtocols().contains(protocol);
if (yes) break;
}
// Check if the client version supports the protocol
return getClientVersion().getSupportedProtocols().contains(protocol) || yes;
}
/**
* Receives and processes requests from the client.
* Handles authentication, file serving, and PHP rendering.
*/
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<String, String> 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<String, String> 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<String, String> 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();
}
}
/**
* Represents the response from a PHP script, including body and cookies.
*/
private static class PHPResponse {
String body;
Map<String, String> cookies;
public PHPResponse(String body, Map<String, String> cookies) {
this.body = body;
this.cookies = cookies;
}
}
}

View File

@@ -0,0 +1,366 @@
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 dev.unlegitdqrk.unlegitlibrary.string.RandomString;
import lombok.Getter;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.side.web.managers.AuthManager;
import org.openautonomousconnection.protocol.side.web.managers.RuleManager;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
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.Random;
/**
* Represents the web server for the protocol.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.WEB)
public final class ProtocolWebServer {
/**
* Folder for web content.
*/
@Getter
private final File contentFolder;
/**
* Folder for error pages.
*/
@Getter
private final File errorsFolder;
/**
* Structure for server.
*/
@Getter
private final ServerCertificateFolderStructure folderStructure;
/**
* Configuration manager for server settings.
*/
private final ConfigurationManager configurationManager;
/**
* Certificate files for SSL.
*/
private final File certFile;
/**
* Certificate files for SSL.
*/
private final File keyFile;
/**
* The network server handling pipeline connections.
*/
@Getter
private NetworkServer pipelineServer;
/**
* The SSL server socket for web connections.
*/
@Getter
private SSLServerSocket webServer;
/**
* List of connected web clients.
*/
@Getter
private List<ConnectedWebClient> clients;
/**
* The configuration file for the web server.
*/
private final File configFile;
/**
* A unique secret for session management.
*/
@Getter
private String uniqueSessionString;
/**
* Initializes the web server with the given configuration, authentication, and rules files.
* @param configFile The configuration file.
* @param authFile The authentication file.
* @param rulesFile The rules file.
* @throws Exception If an error occurs during initialization.
*/
public ProtocolWebServer(File configFile, File authFile, File rulesFile) throws Exception {
// Initialize the list of connected clients
this.clients = new ArrayList<>();
// Store the configuration file
this.configFile = configFile;
// Set up folder structure for certificates
folderStructure = new ServerCertificateFolderStructure();
// Check for necessary certificate files
checkFileExists(folderStructure.publicServerFolder, folderStructure.certPrefix, ".crt");
checkFileExists(folderStructure.privateServerFolder, folderStructure.certPrefix, ".key");
// Load configuration settings
this.configurationManager = getConfigurationManager(configFile);
// Set up content and error folders
contentFolder = new File("content");
errorsFolder = new File("errors");
// Create folders if they don't exist
if (!contentFolder.exists()) contentFolder.mkdir();
if (!errorsFolder.exists()) errorsFolder.mkdir();
// Set up certificate files based on public IP address
this.certFile = new File(folderStructure.publicServerFolder, folderStructure.certPrefix + NetworkUtils.getPublicIPAddress() + ".crt");
this.keyFile = new File(folderStructure.privateServerFolder, folderStructure.certPrefix + NetworkUtils.getPublicIPAddress() + ".key");
// Create auth and rules files with default content if they don't exist
if (!authFile.exists()) {
authFile.createNewFile();
FileUtils.writeFile(authFile, """
admin:5e884898da28047151d0e56f8dc6292773603d0d6aabbddab8f91d8e5f99f6c7
user:e99a18c428cb38d5f260853678922e03abd8335f
""");
}
// Create default rules file if it doesn't exist
if (!rulesFile.exists()) {
rulesFile.createNewFile();
FileUtils.writeFile(rulesFile, """
{
"allow": [
"index.html",
"css/*",
"private/info.php"
],
"deny": [
"private/*"
],
"auth": [
"private/*",
"admin/*"
]
}
""");
}
// Load authentication and rules
uniqueSessionString = AuthManager.sha256(new RandomString(new Random(System.currentTimeMillis()).nextInt(10, 20)).nextString());
AuthManager.loadAuthFile(authFile);
RuleManager.loadRules(rulesFile);
// Initialize the pipeline server
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();
}
/**
* Retrieves a connected web client by its client ID.
* @param clientID The client ID to search for.
* @return The connected web client with the specified ID, or null if not found.
*/
public final ConnectedWebClient getClientByID(int clientID) {
for (ConnectedWebClient client : clients)
if (client.getPipelineConnection().getClientID() == clientID) return client;
return null;
}
/**
* Starts the web server to accept and handle client connections.
* @throws Exception If an error occurs while starting the server.
*/
public final void startWebServer() throws Exception {
// Start the pipeline server
pipelineServer.start();
// Create the SSL server socket for web connections
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) {
// Check if the pipeline server is still running
if (pipelineServer == null || !pipelineServer.getServerSocket().isBound()) {
try {
// Stop the web server
onPipelineStop();
} catch (IOException e) {
pipelineServer.getLogger().exception("Failed to stop WebServer", e);
}
Thread.currentThread().interrupt();
break;
}
try {
// Sleep for a while before checking again
Thread.sleep(1000);
} catch (InterruptedException ignored) {}
}
}).start();
// Handle every client
new Thread(() -> {
while (true) {
try {
// Accept incoming client connections
SSLSocket client = (SSLSocket) webServer.accept();
for (ConnectedWebClient connectedWebClient : clients) {
if (connectedWebClient.getPipelineConnection().getClientID() != -1 && connectedWebClient.isClientVersionLoaded()) {
// Assign socket to an existing connected client
connectedWebClient.setWebSocket(client);
}
}
} catch (IOException e) {
pipelineServer.getLogger().exception("Failed to accept WebClient", e);
}
}
}).start();
}
/**
* Handles the shutdown of the web server when the pipeline server stops.
* @throws IOException If an I/O error occurs while closing the web server.
*/
private void onPipelineStop() throws IOException {
webServer.close();
}
/**
* Checks if the required certificate files exist in the specified folder.
* @param folder The folder to check for certificate files.
* @param prefix The prefix of the certificate files.
* @param extension The extension of the certificate files.
* @throws CertificateException If a required certificate file is missing or invalid.
* @throws IOException If an I/O error occurs while checking the files.
*/
private void checkFileExists(File folder, String prefix, String extension) throws CertificateException, IOException {
boolean found = false;
// Ensure the folder exists
if (folder == null) throw new FileNotFoundException("Folder does not exist");
// List all files in the folder
File[] files = folder.listFiles();
if (files == null || files.length == 0)
throw new FileNotFoundException("Folder " + folder.getAbsolutePath() + " is empty");
// Check for the required certificate file
for (File file : files) {
if (!file.getName().startsWith(prefix) || !file.getName().endsWith(extension))
throw new CertificateException(file.getAbsolutePath() + " is not valid");
// Check for file matching the public IP address
if (!found) found = file.getName().equalsIgnoreCase(prefix + NetworkUtils.getPublicIPAddress() + extension);
}
// Throw exception if the required file is not found
if (!found) throw new CertificateException("Missing " + prefix + NetworkUtils.getPublicIPAddress() + extension);
}
/**
* Retrieves the configuration manager for the web server.
* @return The configuration manager.
* @throws IOException If an I/O error occurs while loading or saving the configuration.
*/
public final ConfigurationManager getConfigurationManager() throws IOException {
return getConfigurationManager(configFile);
}
/**
* Loads and initializes the configuration manager with default settings if necessary.
* @param configFile The configuration file to load.
* @return The initialized configuration manager.
* @throws IOException If an I/O error occurs while loading or saving the configuration.
*/
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;
}
/**
* Represents the folder structure for server certificates.
*/
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 final String caPrefix = "ca_server_";
public final String certPrefix = "cert_server_";
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();
}
}
}

View File

@@ -0,0 +1,24 @@
package org.openautonomousconnection.protocol.side.web.events;
import dev.unlegitdqrk.unlegitlibrary.event.impl.Event;
import lombok.Getter;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.side.web.ConnectedWebClient;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
/**
* Event triggered when a web client connects to the web server.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.WEB)
public final class ConnectedWebClientEvent extends Event {
/**
* The connected web client.
*/
@Getter
private final ConnectedWebClient webClient;
public ConnectedWebClientEvent(ConnectedWebClient webClient) {
this.webClient = webClient;
}
}

View File

@@ -0,0 +1,84 @@
package org.openautonomousconnection.protocol.side.web.managers;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
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;
/**
* Manages authentication for web clients.
* Loads user credentials from a file and verifies login attempts.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.WEB)
public final class AuthManager {
/**
* Map of usernames to their SHA-256 hashed passwords
*/
private static final Map<String, String> users = new HashMap<>();
/**
* Loads the authentication file and populates the users map.
* The file should contain lines in the format: username:hashed_password
* Lines starting with '#' are treated as comments and ignored.
* @param authFile The authentication file to load.
* @throws IOException If an I/O error occurs reading from the file.
*/
public static void loadAuthFile(File authFile) throws IOException {
// Create the file if it doesn't exist
if (!authFile.exists()) authFile.createNewFile();
for (String line : Files.readAllLines(authFile.toPath(), StandardCharsets.UTF_8)) {
// Trim whitespace and ignore comments/empty lines
line = line.trim();
if (line.isEmpty() || line.startsWith("#")) continue;
// Split the line into username and hashed password
String[] parts = line.split(":", 2);
if (parts.length == 2) {
users.put(parts[0], parts[1]);
}
}
}
/**
* Checks if the provided login and password are valid.
* @param login The username to check.
* @param password The password to verify.
* @return True if the credentials are valid, false otherwise.
*/
public static boolean checkAuth(String login, String password) {
// Retrieve the stored hashed password for the given username
String storedHash = users.get(login);
if (storedHash == null) return false;
// Hash the provided password and compare it to the stored hash
String hash = sha256(password);
return storedHash.equalsIgnoreCase(hash);
}
/**
* Computes the SHA-256 hash of the given input string.
* @param input The input string to hash.
* @return The hexadecimal representation of the SHA-256 hash.
*/
public static String sha256(String input) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
// Convert the byte array to a hexadecimal string
StringBuilder sb = new StringBuilder();
for (byte b : digest) sb.append(String.format("%02x", b));
return sb.toString();
} catch (Exception e) {
return "";
}
}
}

View File

@@ -0,0 +1,90 @@
package org.openautonomousconnection.protocol.side.web.managers;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import java.io.File;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;
/**
* Manages access rules for web resources.
* Loads allow, deny, and auth rules from a JSON file and provides methods to check access.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.WEB)
public final class RuleManager {
/**
* Lists of path patterns for allow, deny, and auth rules
*/
private static List<String> allow;
/**
* Lists of path patterns for allow, deny, and auth rules
*/
private static List<String> deny;
/**
* Lists of path patterns for allow, deny, and auth rules
*/
private static List<String> auth;
/**
* Loads rules from a JSON file.
* The JSON should have the structure:
* {
* "allow": ["pattern1", "pattern2", ...],
* "deny": ["pattern1", "pattern2", ...],
* "auth": ["pattern1", "pattern2", ...]
* }
* @param rulesFile The JSON file containing the rules.
* @throws Exception If an error occurs reading the file or parsing JSON.
*/
public static void loadRules(File rulesFile) throws Exception {
// Load and parse the JSON file
String json = new String(Files.readAllBytes(rulesFile.toPath()));
Map<String, List<String>> map = new Gson().fromJson(json, new TypeToken<Map<String, List<String>>>() {}.getType());
// Default to empty lists if keys are missing
allow = map.getOrDefault("allow", List.of());
deny = map.getOrDefault("deny", List.of());
auth = map.getOrDefault("auth", List.of());
}
/** Checks if the given path is allowed based on the allow rules.
* @param path The path to check.
* @return True if the path is allowed, false otherwise.
*/
public static boolean isAllowed(String path) {
return allow.stream().anyMatch(p -> pathMatches(path, p));
}
/** Checks if the given path is denied based on the deny rules.
* @param path The path to check.
* @return True if the path is denied, false otherwise.
*/
public static boolean isDenied(String path) {
return deny.stream().anyMatch(p -> pathMatches(path, p));
}
/** Checks if the given path requires authentication based on the auth rules.
* @param path The path to check.
* @return True if the path requires authentication, false otherwise.
*/
public static boolean requiresAuth(String path) {
return auth.stream().anyMatch(p -> pathMatches(path, p));
}
/** Helper method to check if a path matches a pattern.
* Patterns can include '*' as a wildcard.
* @param path The path to check.
* @param pattern The pattern to match against.
* @return True if the path matches the pattern, false otherwise.
*/
private static boolean pathMatches(String path, String pattern) {
pattern = pattern.replace("/", File.separator).replace("*", ".*");
return path.matches(pattern);
}
}

View File

@@ -0,0 +1,154 @@
package org.openautonomousconnection.protocol.side.web.managers;
import lombok.Getter;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Manages user sessions for web clients.
* Provides methods to create, validate, and invalidate sessions.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.WEB)
public final class SessionManager {
/**
* Map of session IDs to Session objects.
*/
private static final Map<String, Session> sessions = new ConcurrentHashMap<>();
/**
* Secure random number generator for session ID creation.
*/
private static final SecureRandom secureRandom = new SecureRandom();
/**
* Creates a new session for the given user.
* @param login The username associated with the session.
* @param ip The IP address of the client.
* @param userAgent The User-Agent string of the client.
* @return The generated session ID.
* @throws IOException If an I/O error occurs.
*/
public static String create(String login, String ip, String userAgent) throws IOException {
// Generate a secure random session ID
byte[] bytes = new byte[32];
secureRandom.nextBytes(bytes);
// Encode the bytes to a URL-safe Base64 string
String sessionId = Base64.getUrlEncoder().withoutPadding().encodeToString(bytes) + ProtocolBridge.getInstance().getProtocolWebServer().getUniqueSessionString();
// Create and store the new session
sessions.put(sessionId, new Session(login, ip, userAgent));
return sessionId;
}
/**
* Validates a session ID against the provided IP and User-Agent.
* @param sessionId The session ID to validate.
* @param ip The IP address of the client.
* @param userAgent The User-Agent string of the client.
* @return True if the session is valid, false otherwise.
* @throws IOException If an I/O error occurs.
*/
public static boolean isValid(String sessionId, String ip, String userAgent) throws IOException {
// Retrieve the session associated with the session ID
Session session = sessions.get(sessionId);
// Check if the session exists, is not expired, and matches the IP and User-Agent
if (session == null || session.isExpired() || !session.matches(ip, userAgent)) {
sessions.remove(sessionId);
return false;
}
// Refresh the session expiration time
session.refresh();
return true;
}
/**
* Invalidates a session, removing it from the active sessions.
* @param sessionId The session ID to invalidate.
*/
public static void invalidate(String sessionId) {
sessions.remove(sessionId);
}
/**
* Retrieves the username associated with a valid session ID.
* @param sessionId The session ID to look up.
* @return The username if the session is valid, null otherwise.
*/
public static String getUser(String sessionId) {
// Retrieve the session associated with the session ID
Session session = sessions.get(sessionId);
// Check if the session exists and is not expired
if (session == null || session.isExpired()) {
sessions.remove(sessionId);
return null;
}
// Return the username associated with the session
return session.getLogin();
}
/**
* Cleans up expired sessions from the session map.
* This method should be called periodically to prevent memory leaks.
*/
public static void cleanupExpiredSessions() {
long now = System.currentTimeMillis();
sessions.entrySet().removeIf(entry -> entry.getValue().isExpired());
}
/**
* Represents a user session with associated metadata.
*/
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) ProtocolBridge.getInstance().getProtocolWebServer().getConfigurationManager().getInt("sessionexpireminutes") * 60 * 1000;
}
/**
* Checks if the session has expired.
* @return True if the session is expired, false otherwise.
*/
boolean isExpired() {
return System.currentTimeMillis() > expiresAt;
}
/**
* Checks if the session matches the given IP and User-Agent.
* @param ip The IP address to check.
* @param userAgent The User-Agent string to check.
* @return True if both match, false otherwise.
*/
boolean matches(String ip, String userAgent) {
return this.ip.equals(ip) && this.userAgent.equals(userAgent);
}
/**
* Refreshes the session's expiration time.
* @throws IOException If an I/O error occurs.
*/
void refresh() throws IOException {
this.expiresAt = System.currentTimeMillis() + (long) ProtocolBridge.getInstance().getProtocolWebServer().getConfigurationManager().getInt("sessionexpireminutes") * 60 * 1000;
}
}
}

View File

@@ -0,0 +1,194 @@
package org.openautonomousconnection.protocol.versions;
import lombok.Getter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Enum representing different protocol versions, their types, sides, and compatibility.
*/
public enum ProtocolVersion implements Serializable {
/**
* Support for old OAC-Project => <a href="https://repo.open-autonomous-connection.org/Open-Autonomous-Connection/">*_old</a>
*/
PV_1_0_0_CLASSIC("1.0.0", ProtocolType.CLASSIC, ProtocolSide.WEB_DNS, List.of(Protocol.HTTP)),
/**
* First Beta Version of OAC-Protocol
*/
PV_1_0_0_BETA("1.0.0", ProtocolType.BETA, ProtocolSide.ALL, List.of(Protocol.OAC), PV_1_0_0_CLASSIC);
/**
* The version string of the protocol version.
*/
@Getter
private final String version;
/**
* The type of the protocol version.
*/
@Getter
private final ProtocolType protocolType;
/**
* The side(s) the protocol version is intended for.
*/
@Getter
private final ProtocolSide protocolSide;
/**
* List of protocol versions that are compatible with this version.
*/
@Getter
private final List<ProtocolVersion> compatibleVersions;
/**
* List of supported protocols.
*/
@Getter
private final List<Protocol> supportedProtocols;
/**
* Constructor for ProtocolVersion enum.
*
* @param version The version string.
* @param protocolType The type of the protocol.
* @param protocolSide The side(s) the protocol is intended for.
* @param supportedProtocols List of supported protocols.
* @param compatibleVersions Varargs of compatible protocol versions.
*/
ProtocolVersion(String version, ProtocolType protocolType, ProtocolSide protocolSide, List<Protocol> 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;
}
/**
* Returns a string representation of the protocol version, including its version, type, side, supported protocols, and compatible versions.
* @return a string representation of the protocol version.
*/
@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() + ";supportedProtocols=" + supported + ";compatibleVersions=" + compatible + "}";
}
/**
* Builds a name for the protocol version combining its version and type.
* @return a string representing the name of the protocol version.
*/
public final String buildName() {
return version + "-" + protocolType.toString();
}
/**
* Enum representing different protocols.
*/
public enum Protocol implements Serializable {
HTTP,
HTTPS,
OAC;
/**
* Returns the name of the protocol in uppercase.
* @return the name of the protocol in uppercase.
*/
@Override
public final String toString() {
return name().toUpperCase();
}
}
/**
* Enum representing different types of protocol versions.
*/
public enum ProtocolType implements Serializable {
/**
* Classic Protocol Type, see old OAC-Project: <a href="https://repo.open-autonomous-connection.org/Open-Autonomous-Connection/">*_old</a>
*/
CLASSIC,
/**
* Beta Protocol Type, may be unstable and subject to change.
*/
BETA,
/**
* Stable Protocol Type, recommended for production use.
*/
STABLE;
/**
* Returns the name of the protocol in uppercase.
* @return the name of the protocol in uppercase.
*/
@Override
public final String toString() {
return name().toUpperCase();
}
}
/**
* Enum representing different sides where the protocol version can be used.
*/
public enum ProtocolSide implements Serializable {
/**
* Client Side only
*/
CLIENT, // Protocol version can only used on Client
/**
* DNS Server Side only
*/
DNS,
/**
* Web Server Side only
*/
WEB,
/**
* Both DNS and Web Server Side
*/
WEB_DNS,
/**
* Both Client and DNS Server Side
*/
CLIENT_DNS,
/**
* Both Client and Web Server Side
*/
CLIENT_WEB,
/**
* All Sides
*/
ALL
;
/**
* Returns the name of the protocol in uppercase.
* @return the name of the protocol in uppercase.
*/
@Override
public final String toString() {
return name().toUpperCase();
}
}
}

View File

@@ -1,45 +1,82 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.beta;
package org.openautonomousconnection.protocol.versions.v1_0_0.beta;
import lombok.Getter;
import java.io.Serializable;
/**
* Enum representing various DNS response codes and their descriptions.
*/
public enum DNSResponseCode implements Serializable {
/**
* General Responses
*/
RESPONSE_NOT_REQUIRED(0, "Response code not required"),
RESPONSE_INVALID_REQUEST(1, "Invalid request"),
/**
* Authentication Responses
*/
RESPONSE_AUTH_SUCCESS(4, "Auth success"),
RESPONSE_AUTH_FAILED(5, "Auth failed"),
/**
* Domain Responses
*/
RESPONSE_DOMAIN_NAME_EXIST(100, "Domainname exist"),
RESPONSE_DOMAIN_NAME_NOT_EXIST(101, "Domainname does not exist"),
RESPONSE_DOMAIN_NAME_CREATED(105, "Domainname created"),
RESPONSE_DOMAIN_NAME_DELETED(106, "Domainname deleted"),
/**
* Top Level Name Responses
*/
RESPONSE_DOMAIN_TLN_EXIST(110, "TopLevelName exist"),
RESPONSE_DOMAIN_TLN_NOT_EXIST(111, "TopLevelName does not exist"),
RESPONSE_DOMAIN_TLN_CREATED(115, "TopLevelName created"),
RESPONSE_DOMAIN_TLN_DELETED(116, "TopLevelName deleted"),
/**
* Subname Responses
*/
RESPONSE_DOMAIN_SUBNAME_EXIST(120, "Subname exist"),
RESPONSE_DOMAIN_SUBNAME_NOT_EXIST(121, "Subname does not exist"),
RESPONSE_DOMAIN_SUBNAME_CREATED(125, "Subname created"),
RESPONSE_DOMAIN_SUBNAME_DELETED(126, "Subname deleted"),
/**
* Full Domain Responses
*/
RESPONSE_DOMAIN_FULLY_EXIST(130, "Full domain exist"),
RESPONSE_DOMAIN_FULLY_NOT_EXIST(131, "Full domain does not exist");
/**
* The numeric code representing the DNS response.
*/
@Getter
private final int code;
/**
* A brief description of the DNS response code.
*/
@Getter
private final String description;
/**
* Constructor for DNSResponseCode enum.
*
* @param code The numeric code of the response.
* @param description A brief description of the response.
*/
DNSResponseCode(int code, String description) {
this.code = code;
this.description = description;
}
/**
* Returns a string representation of the DNS response code, including its code and description.
* @return a string representation of the DNS response code.
*/
@Override
public String toString() {
return "{code=" + code + ";description=" + description + "}";

View File

@@ -1,27 +1,66 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.beta;
package org.openautonomousconnection.protocol.versions.v1_0_0.beta;
import github.openautonomousconnection.protocol.ProtocolBridge;
import lombok.Getter;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
public class Domain implements Serializable {
/**
* Class representing a domain with its components such as subname, name, top-level name, path, query, fragment, and protocol.
*/
public final class Domain implements Serializable {
/**
* The subname of the domain (e.g., "sub" in "sub.example.com").
*/
@Getter
private final String subname;
/**
* The main name of the domain (e.g., "example" in "sub.example.com").
*/
@Getter
private final String name;
/**
* The top-level name of the domain (e.g., "com" in "sub.example.com").
*/
@Getter
private final String topLevelName;
/**
* The path component of the domain (e.g., "path/to/resource" in "example.com/path/to/resource").
*/
@Getter
private String path;
/**
* The query component of the domain (e.g., "key=value" in "example.com/path?key=value").
*/
@Getter
private String query;
/**
* The fragment component of the domain (e.g., "section1" in "example.com/path#section1").
*/
@Getter
private String fragment;
/**
* The protocol of the domain (e.g., "oac" in "oac://example.com").
*/
@Getter
private String protocol;
/**
* Constructs a Domain object by parsing the provided full domain string.
*
* @param fullDomain The full domain string to parse.
* @throws IllegalArgumentException if the domain is invalid.
*/
public Domain(String fullDomain) {
// Remove protocol
String domainWithPath = fullDomain.contains("://") ? fullDomain.split("://", 2)[1] : fullDomain;
@@ -31,17 +70,21 @@ public class Domain implements Serializable {
// Cut path
String[] domainPartsAndPath = domainWithPath.split("/", 2);
String host = domainPartsAndPath[0]; // z.B. hello.world.com
// Get host and full path
String host = domainPartsAndPath[0];
String fullPath = domainPartsAndPath.length > 1 ? "/" + domainPartsAndPath[1] : "";
// Split domain in labels
List<String> labels = Arrays.asList(host.split("\\."));
if (labels.size() < 2) throw new IllegalArgumentException("Invalid domain: " + host);
// Get subname, name and top-level name
this.topLevelName = labels.getLast();
this.name = labels.get(labels.size() - 2);
this.subname = labels.size() > 2 ? String.join(".", labels.subList(0, labels.size() - 2)) : null;
// Split fragment
if (fullPath.contains("#")) {
this.fragment = "#" + Arrays.stream(fullPath.split("#")).toList().getLast();
fullPath = fullPath.substring(0, fullPath.length() - ("#" + fragment).length());
@@ -57,6 +100,7 @@ public class Domain implements Serializable {
this.query = "";
}
// Clean up path, query and fragment
if (this.path.startsWith("/")) this.path = this.path.substring(1);
if (this.path.endsWith("/")) this.path = this.path.substring(0, this.path.length() - 1);
@@ -64,32 +108,56 @@ public class Domain implements Serializable {
if (this.fragment.startsWith("#")) this.fragment = this.fragment.substring(1);
}
/**
* Checks if the domain has a subname.
* @return true if the domain has a subname, false otherwise.
*/
public final boolean hasSubname() {
return subname != null;
}
/**
* Checks if this domain is equal to another object.
* Two domains are considered equal if their subname, name, top-level name, and protocol are equal (case-insensitive).
* @return true if the domains are equal, false otherwise.
*/
@Override
public final boolean equals(Object obj) {
// Check if the object is an instance of Domain
if (!(obj instanceof Domain domain)) return false;
// Compare subname, name, top-level name, and protocol (case-insensitive)
return domain.getSubname().equalsIgnoreCase(this.subname) && domain.getName().equalsIgnoreCase(this.name) &&
domain.getTopLevelName().equalsIgnoreCase(this.topLevelName) && domain.getProtocol().equalsIgnoreCase(this.protocol);
}
/**
* Returns the destination associated with this domain.
* The destination is determined based on the domain's components and the current protocol context.
* @return the destination as a string.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.DNS)
public final String getDestination() {
if (ProtocolBridge.getInstance().isRunningAsClient())
// If running as client or web server, return invalid request
if (ProtocolBridge.getInstance().isRunningAsClient() || ProtocolBridge.getInstance().isRunningAsWebServer())
return DNSResponseCode.RESPONSE_INVALID_REQUEST.toString();
// Handle special default domains
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 destination based on whether subname exists
return !hasSubname() ? ProtocolBridge.getInstance().getProtocolDNSServer().getDomainDestination(this) : ProtocolBridge.getInstance().getProtocolDNSServer().getSubnameDestination(this, subname);
}
/**
* Returns a string representation of the domain, including its protocol, subname, name, top-level name, path, query, and fragment.
* @return a string representation of the domain.
*/
public static class DefaultDomains {
public static final Domain DNS_INFO_SITE = new Domain("oac://about.oac/");
public static final Domain DNS_REGISTER_SITE = new Domain("oac://register.oac/");

View File

@@ -0,0 +1,50 @@
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.events;
import dev.unlegitdqrk.unlegitlibrary.event.impl.Event;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_Domain;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils.Classic_ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_RequestDomain;
/**
* This event is fired when a classic domain packet is received.
* This event is deprecated and will be marked for removal in future versions.
* @see org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerDNSServer
* @see org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerClient
* @see org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerWebServer
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
public final class Classic_DomainPacketReceivedEvent extends Event {
public final Classic_ProtocolVersion protocolVersion;
public final Classic_Domain domain;
public final Classic_RequestDomain requestDomain;
public final int clientID;
public Classic_DomainPacketReceivedEvent(Classic_ProtocolVersion protocolVersion, Classic_Domain domain, Classic_RequestDomain requestDomain, int clientID) {
this.protocolVersion = protocolVersion;
this.domain = domain;
this.requestDomain = requestDomain;
this.clientID = clientID;
}
@Override
protected final Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public final boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public final String toString() {
return super.toString();
}
@Override
public final int hashCode() {
return super.hashCode();
}
}

View File

@@ -0,0 +1,50 @@
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.events;
import dev.unlegitdqrk.unlegitlibrary.event.impl.Event;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_Domain;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils.Classic_ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_RequestDomain;
/**
* This event is fired when a classic ping packet is received.
* This event is deprecated and will be marked for removal in future versions.
* @see org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerDNSServer
* @see org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerClient
* @see org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerWebServer
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
public final class Classic_PingPacketReceivedEvent extends Event {
public final Classic_ProtocolVersion protocolVersion;
public final Classic_Domain domain;
public final Classic_RequestDomain requestDomain;
public final boolean reachable;
public final int clientID;
public Classic_PingPacketReceivedEvent(Classic_ProtocolVersion protocolVersion, Classic_Domain domain, Classic_RequestDomain requestDomain, boolean reachable, int clientID) {
this.protocolVersion = protocolVersion;
this.domain = domain;
this.requestDomain = requestDomain;
this.reachable = reachable;
this.clientID = clientID;
}
@Override
protected final Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public final boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public final String toString() {
return super.toString();
}
@Override
public final int hashCode() {
return super.hashCode();
}
}

View File

@@ -0,0 +1,28 @@
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_MessagePacket;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_Domain;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.site.Classic_SiteType;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils.Classic_ProtocolVersion;
import java.io.IOException;
/**
* Abstract class defining the client-side handler for Classic protocol operations.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.CLIENT)
public abstract class ClassicHandlerClient {
public abstract void unsupportedClassicPacket(String classicPacketClassName, Object[] content);
public abstract void handleHTMLContent(Classic_SiteType siteType, Classic_Domain domain, String html);
public abstract void handleMessage(String message, Classic_ProtocolVersion protocolVersion);
public final void sendMessage(String message) throws IOException, ClassNotFoundException {
ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().sendPacket(new Classic_MessagePacket(message, 0));
}
}

View File

@@ -0,0 +1,24 @@
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.side.dns.ConnectedProtocolClient;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_Domain;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils.Classic_ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_RequestDomain;
import java.sql.SQLException;
/**
* Abstract class defining the DNS server-side handler for Classic protocol operations.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.DNS)
public abstract class ClassicHandlerDNSServer {
public abstract void handleMessage(ConnectedProtocolClient client, String message, Classic_ProtocolVersion protocolVersion);
public abstract Classic_Domain getDomain(Classic_RequestDomain requestDomain) throws SQLException;
public abstract Classic_Domain ping(Classic_RequestDomain requestDomain) throws SQLException;
public abstract void unsupportedClassicPacket(String className, Object[] content, ConnectedProtocolClient client);
}

View File

@@ -0,0 +1,16 @@
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers;
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
import org.openautonomousconnection.protocol.side.dns.ConnectedProtocolClient;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils.Classic_ProtocolVersion;
/**
* Abstract class defining the web server-side handler for Classic protocol operations.
*/
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.WEB)
public abstract class ClassicHandlerWebServer {
public abstract void handleMessage(ConnectedProtocolClient client, String message, Classic_ProtocolVersion protocolVersion);
public abstract void unsupportedClassicPacket(String className, Object[] content, ConnectedProtocolClient client);
}

View File

@@ -0,0 +1,70 @@
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects;
import lombok.Getter;
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain;
import java.io.Serializable;
/**
* Classic_Domain is an old representation of a domain, maintained for backward compatibility.
* It encapsulates the domain's name, top-level domain, path, and destination.
* This class is deprecated and users are encouraged to use the Domain class instead.
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
public final class Classic_Domain implements Serializable {
/**
* The name of the domain (e.g., "example" in "example.com").
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3 | Will be replaced with a getter")
public final String name;
/**
* The top-level domain (e.g., "com" in "example.com").
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3 | Will be replaced with a getter")
public final String topLevelDomain;
/**
* The path component of the domain (e.g., "/path/to/resource" in "example.com/path/to/resource").
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3 | Will be replaced with a getter")
public final String path;
/**
* The destination of the domain, typically the full URL or address.
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3 | Will be replaced with a getter")
private final String destination;
/**
* The encapsulated Domain object for modern usage.
*/
@Getter
private final Domain domain;
public Classic_Domain(String name, String topLevelDomain, String destination, String path) {
this.domain = new Domain(name + "." + topLevelDomain + "/" + (path.startsWith("/") ? path : "/" + path));
this.name = domain.getName();
this.topLevelDomain = domain.getTopLevelName();
this.destination = domain.getDestination();
this.path = domain.getPath();
}
@Override
protected final Object clone() throws CloneNotSupportedException {
return new Classic_Domain(name, topLevelDomain, destination, path);
}
@Override
public final boolean equals(Object obj) {
if (!(obj instanceof Classic_Domain other)) return false;
return other.name.equalsIgnoreCase(name) && other.topLevelDomain.equalsIgnoreCase(topLevelDomain);
}
@Override
public final int hashCode() {
return super.hashCode();
}
}

View File

@@ -0,0 +1,12 @@
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects;
/**
* Class representing a local domain in the Classic protocol.
* This class extends Classic_Domain and is used for local domain representation.
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
public final class Classic_LocalDomain extends Classic_Domain {
public Classic_LocalDomain(String name, String endName, String path) {
super(name, endName, null, path);
}
}

View File

@@ -0,0 +1,15 @@
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects;
import java.io.Serializable;
/**
* Class representing a request for a domain in the Classic protocol.
* This class extends Classic_Domain and is used for requesting domain information.
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
public final class Classic_RequestDomain extends Classic_Domain implements Serializable {
public Classic_RequestDomain(String name, String topLevelDomain, String path) {
super(name, topLevelDomain, null, path);
}
}

View File

@@ -0,0 +1,44 @@
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.site;
import java.io.Serializable;
/**
* Enum representing different types of sites in the Classic protocol.
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
public enum Classic_SiteType implements Serializable {
/**
* Client site type.
*/
CLIENT("oac-client"),
/**
* Web server site type.
*/
SERVER("oac-server"),
/**
* DNS server site type.
*/
PUBLIC("oac"),
/**
* Protocol site type.
*/
PROTOCOL("oac-protocol"),
/**
* Local site type.
*/
LOCAL("oac-local");
/**
* The name of the site type.
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3 | Will be replaced with a getter")
public final String name;
Classic_SiteType(String name) {
this.name = name;
}
}

View File

@@ -1,8 +1,12 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.site;
import me.finn.unlegitlibrary.utils.DefaultMethodsOverrider;
import dev.unlegitdqrk.unlegitlibrary.utils.DefaultMethodsOverrider;
public class Classic_WebsitesContent extends DefaultMethodsOverrider {
/**
* This class contains predefined HTML content for various website responses in the Classic protocol.
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
public final class Classic_WebsitesContent extends DefaultMethodsOverrider {
public static final String DOMAIN_NOT_FOUND = """
<html>

View File

@@ -0,0 +1,53 @@
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.Domain;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_Domain;
/**
* Utility class for converting between Classic protocol objects and new protocol objects.
*/
public final class ClassicConverter {
/**
* Converts a Classic_Domain object to a Domain object.
* @param classicDomain the Classic_Domain object to convert
* @return the converted Domain object
*/
@SuppressWarnings(value = "deprecation")
public static Domain classicDomainToNewDomain(Classic_Domain classicDomain) {
return new Domain(classicDomain.name + "." + classicDomain.topLevelDomain + (classicDomain.path.startsWith("/") ? classicDomain.path : "/" + classicDomain.path));
}
/**
* Converts a Domain object to a Classic_Domain object.
* @param newDomain the Domain object to convert
* @return the converted Classic_Domain object
*/
@SuppressWarnings(value = "deprecation")
public static Classic_Domain newDomainToClassicDomain(Domain newDomain) {
return new Classic_Domain(newDomain.getName(), newDomain.getTopLevelName(), newDomain.getDestination(), newDomain.getPath());
}
/**
* Converts a Classic_ProtocolVersion to a ProtocolVersion.
* @param classicProtocolVersion the Classic_ProtocolVersion to convert
* @return the converted ProtocolVersion
*/
@SuppressWarnings(value = "deprecation")
public static ProtocolVersion classicProtocolVersionToNewProtocolVersion(Classic_ProtocolVersion classicProtocolVersion) {
if (classicProtocolVersion == Classic_ProtocolVersion.PV_1_0_0) return ProtocolVersion.PV_1_0_0_CLASSIC;
return null;
}
/**
* Converts a ProtocolVersion to a Classic_ProtocolVersion.
* @param newProtocolVersion the ProtocolVersion to convert
* @return the converted Classic_ProtocolVersion
*/
@SuppressWarnings(value = "deprecation")
public static Classic_ProtocolVersion newProtocolVersionToClassicProtocolVersion(ProtocolVersion newProtocolVersion) {
return Classic_ProtocolVersion.PV_1_0_0;
}
}

View File

@@ -1,9 +1,14 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils;
import github.openautonomousconnection.protocol.ProtocolBridge;
import github.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_PingPacket;
import me.finn.unlegitlibrary.event.EventListener;
import me.finn.unlegitlibrary.event.Listener;
import dev.unlegitdqrk.unlegitlibrary.event.EventListener;
import dev.unlegitdqrk.unlegitlibrary.event.Listener;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_PingPacket;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.events.Classic_DomainPacketReceivedEvent;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.events.Classic_PingPacketReceivedEvent;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_LocalDomain;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.site.Classic_SiteType;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.site.Classic_WebsitesContent;
import java.io.BufferedReader;
import java.io.IOException;
@@ -11,48 +16,77 @@ import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class Classic_ClientListener extends EventListener {
/**
* This class listens for events related to Classic protocol operations on the client side.
* It handles domain resolution and ping responses, facilitating communication with the DNS server
* and web content retrieval.
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
public final class Classic_ClientListener extends EventListener {
/**
* Handles the event when a domain packet is received.
* It checks if the domain exists and sends a ping request to the DNS server.
* If the domain does not exist, it handles the error accordingly.
* @param event The event containing domain information.
*/
@Listener
public void onDomain(Classic_DomainPacketReceivedEvent event) {
// Check if the domain exists
boolean exists = event.domain != null;
if (exists) {
try {
if (!ProtocolBridge.getInstance().getProtocolClient().getNetworkClient().sendPacket(new Classic_PingPacket(event.requestDomain, event.domain, false))) {
// Send a ping request to the DNS server
if (!ProtocolBridge.getInstance().getProtocolClient().getClientDNSConnection().sendPacket(new Classic_PingPacket(event.requestDomain, event.domain, false))) {
// If sending the packet fails, handle the error
ProtocolBridge.getInstance().getClassicHandlerClient().handleHTMLContent(Classic_SiteType.PROTOCOL, new Classic_LocalDomain("error-occurred", "html", ""),
Classic_WebsitesContent.ERROR_OCCURRED(event.domain + "/" + event.domain.path));
}
} catch (IOException | ClassNotFoundException e) {
// Handle any exceptions that occur during the process
ProtocolBridge.getInstance().getClassicHandlerClient().handleHTMLContent(Classic_SiteType.PROTOCOL, new Classic_LocalDomain("error-occurred", "html", ""),
Classic_WebsitesContent.ERROR_OCCURRED(event.domain + "/" + event.domain.path + ":\n" + e.getMessage()));
}
} else
// If the domain does not exist, handle the error
ProtocolBridge.getInstance().getClassicHandlerClient().handleHTMLContent(Classic_SiteType.PROTOCOL, new Classic_LocalDomain("domain-not-found", "html", ""), Classic_WebsitesContent.DOMAIN_NOT_FOUND);
}
/**
* Handles the event when a ping packet is received.
* If the domain is reachable, it fetches the HTML content from the domain.
* If not reachable, it handles the error accordingly.
* @param event The event containing ping response information.
*/
@Listener
public void onPing(Classic_PingPacketReceivedEvent event) {
// If the domain is reachable, fetch the HTML content
if (event.reachable) {
String destination = event.domain.getDomain().getDestination();
try {
// Create a URL object
URL url = new URL(destination);
HttpURLConnection connection2 = (HttpURLConnection) url.openConnection();
connection2.setRequestMethod("GET");
// Read the response
StringBuilder content = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection2.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) content.append(line);
}
// Handle the HTML content
ProtocolBridge.getInstance().getClassicHandlerClient().handleHTMLContent(Classic_SiteType.PUBLIC, event.domain, content.toString());
} catch (IOException exception) {
// Handle any exceptions that occur during the process
ProtocolBridge.getInstance().getClassicHandlerClient().handleHTMLContent(Classic_SiteType.PROTOCOL, new Classic_LocalDomain("error-occurred", "html", ""),
Classic_WebsitesContent.ERROR_OCCURRED(exception.getMessage().replace(event.domain.getDomain().getDestination(), event.domain + "/" + event.domain.path)));
}
} else
// If the domain is not reachable, handle the error
ProtocolBridge.getInstance().getClassicHandlerClient().handleHTMLContent(Classic_SiteType.PROTOCOL, new Classic_LocalDomain("error-not-reached", "html", ""), Classic_WebsitesContent.DOMAIN_NOT_REACHABLE);
}

View File

@@ -1,14 +1,25 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils;
import me.finn.unlegitlibrary.utils.DefaultMethodsOverrider;
import dev.unlegitdqrk.unlegitlibrary.utils.DefaultMethodsOverrider;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.site.Classic_SiteType;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
/**
* Utility class for domain-related operations in the Classic protocol.
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
class Classic_DomainUtils extends DefaultMethodsOverrider {
/**
* Extracts the top-level domain (TLD) from a given URL.
* @param url The URL from which to extract the TLD.
* @return The top-level domain as a string.
* @throws MalformedURLException If the URL is malformed.
*/
public static String getTopLevelDomain(String url) throws MalformedURLException {
URL uri = null;
String tldString = null;
@@ -33,6 +44,13 @@ class Classic_DomainUtils extends DefaultMethodsOverrider {
return tldString;
}
/**
* Extracts the domain name (excluding the TLD) from a given URL.
* @param url The URL from which to extract the domain name.
* @return The domain name as a string.
* @throws URISyntaxException If the URL syntax is incorrect.
* @throws MalformedURLException If the URL is malformed.
*/
public static String getDomainName(String url) throws URISyntaxException, MalformedURLException {
if (url.startsWith(Classic_SiteType.PUBLIC.name + "://"))
url = url.substring((Classic_SiteType.PUBLIC.name + "://").length());
@@ -48,11 +66,14 @@ class Classic_DomainUtils extends DefaultMethodsOverrider {
if (!url.startsWith("https://") && !url.startsWith("http://")) url = "https://" + url;
URI uri = new URI(url);
String domain = uri.getHost().replace("." + getTopLevelDomain(url), "");
return domain;
return uri.getHost().replace("." + getTopLevelDomain(url), "");
}
/**
* Extracts the path component from a given URL.
* @param url The URL from which to extract the path.
* @return The path as a string.
*/
public static String getPath(String url) {
if (!url.startsWith(Classic_SiteType.PUBLIC.name + "://") && !url.startsWith(Classic_SiteType.CLIENT.name + "://") &&
!url.startsWith(Classic_SiteType.SERVER.name + "://") && !url.startsWith(Classic_SiteType.PROTOCOL.name + "://") &&

View File

@@ -1,7 +1,11 @@
package github.openautonomousconnection.protocol.versions.v1_0_0.classic;
package org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils;
import java.io.Serializable;
/**
* Enum representing the protocol versions for the Classic protocol.
*/
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
public enum Classic_ProtocolVersion implements Serializable {
PV_1_0_0("1.0.0");
public final String version;