Advanced InfoNameSystem
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>org.openautonomousconnection</groupId>
|
||||
<artifactId>protocol</artifactId>
|
||||
<version>1.0.0-BETA.9</version>
|
||||
<version>1.0.0-BETA.10</version>
|
||||
<organization>
|
||||
<name>Open Autonomous Connection</name>
|
||||
<url>https://open-autonomous-connection.org/</url>
|
||||
|
||||
@@ -9,9 +9,9 @@ import org.openautonomousconnection.protocol.listeners.INSServerListener;
|
||||
import org.openautonomousconnection.protocol.listeners.WebServerListener;
|
||||
import org.openautonomousconnection.protocol.packets.OACPacket;
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.AuthPacket;
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.GetDestinationPacket;
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.INSQueryPacket;
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.INSResponsePacket;
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.UnsupportedClassicPacket;
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.ValidateInfoNamePacket;
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_DomainPacket;
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_MessagePacket;
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.classic.Classic_PingPacket;
|
||||
@@ -188,16 +188,16 @@ public final class ProtocolBridge {
|
||||
// 1.0.0-BETA packets
|
||||
AuthPacket v100bAuthPath = new AuthPacket();
|
||||
UnsupportedClassicPacket v100bUnsupportedClassicPacket = new UnsupportedClassicPacket();
|
||||
ValidateInfoNamePacket v100BValidateInfoNamePacket = new ValidateInfoNamePacket();
|
||||
GetDestinationPacket v100bGetDestinationPacket = new GetDestinationPacket();
|
||||
INSQueryPacket v100BINSQueryPacket = new INSQueryPacket();
|
||||
INSResponsePacket v100BINSResponsePacket = new INSResponsePacket(this);
|
||||
|
||||
if (isPacketSupported(v100bAuthPath)) protocolSettings.packetHandler.registerPacket(v100bAuthPath);
|
||||
if (isPacketSupported(v100bUnsupportedClassicPacket))
|
||||
protocolSettings.packetHandler.registerPacket(v100bUnsupportedClassicPacket);
|
||||
if (isPacketSupported(v100BValidateInfoNamePacket))
|
||||
protocolSettings.packetHandler.registerPacket(v100BValidateInfoNamePacket);
|
||||
if (isPacketSupported(v100bGetDestinationPacket))
|
||||
protocolSettings.packetHandler.registerPacket(v100bGetDestinationPacket);
|
||||
if (isPacketSupported(v100BINSQueryPacket))
|
||||
protocolSettings.packetHandler.registerPacket(v100BINSQueryPacket);
|
||||
if (isPacketSupported(v100BINSResponsePacket))
|
||||
protocolSettings.packetHandler.registerPacket(v100BINSResponsePacket);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,11 +4,19 @@ 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 dev.unlegitdqrk.unlegitlibrary.network.system.server.events.S_PacketReceivedEvent;
|
||||
import lombok.Getter;
|
||||
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.INSQueryPacket;
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.INSResponsePacket;
|
||||
import org.openautonomousconnection.protocol.side.ins.ConnectedProtocolClient;
|
||||
import org.openautonomousconnection.protocol.side.ins.ProtocolINSServer;
|
||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Listener for INS server connection events.
|
||||
@@ -54,4 +62,38 @@ public final class INSServerListener extends EventListener {
|
||||
insServer.getClients().removeIf(client -> client.getConnectionHandler().getClientID() == -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles incoming INS query packets from connected clients.
|
||||
* <p>
|
||||
* This method performs the following steps:
|
||||
* <ul>
|
||||
* <li>Checks whether the received packet is an {@link INSQueryPacket}</li>
|
||||
* <li>Notifies the INS server through {@code onQueryReceived}</li>
|
||||
* <li>Resolves the request via {@code resolve()}</li>
|
||||
* <li>Wraps the result in an {@link INSResponsePacket}</li>
|
||||
* <li>Sends the response back to the requesting client</li>
|
||||
* </ul>
|
||||
* If sending the response fails, the INS server receives an
|
||||
* {@code onResponseSentFailed(...)} callback.
|
||||
*
|
||||
* @param event The packet event received by the network system.
|
||||
*/
|
||||
@Listener
|
||||
public void onPacket(S_PacketReceivedEvent event) {
|
||||
if (!(event.getPacket() instanceof INSQueryPacket q)) return;
|
||||
|
||||
insServer.onQueryReceived(q.tln, q.name, q.sub, q.type);
|
||||
List<INSRecord> resolved = insServer.resolve(q.tln, q.name, q.sub, q.type);
|
||||
|
||||
INSResponseStatus status = resolved.isEmpty() ? INSResponseStatus.NOT_FOUND : INSResponseStatus.OK;
|
||||
INSResponsePacket response = new INSResponsePacket(status, resolved, q.clientId, insServer.getProtocolBridge());
|
||||
|
||||
try {
|
||||
event.getConnectionHandler().sendPacket(response);
|
||||
insServer.onResponseSent(q.tln, q.name, q.sub, q.type, resolved);
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
insServer.onResponseSentFailed(q.tln, q.name, q.sub, q.type, resolved, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ 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.INSResponseCode;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
@@ -25,7 +25,7 @@ public abstract class OACPacket extends Packet {
|
||||
/**
|
||||
* The response code for the packet, defaulting to RESPONSE_NOT_REQUIRED.
|
||||
*/
|
||||
private INSResponseCode responseCode = INSResponseCode.RESPONSE_NOT_REQUIRED;
|
||||
private INSResponseStatus responseCode = INSResponseStatus.RESPONSE_NOT_REQUIRED;
|
||||
|
||||
/**
|
||||
* Constructor for OACPacket.
|
||||
@@ -43,7 +43,7 @@ public abstract class OACPacket extends Packet {
|
||||
*
|
||||
* @return The INSResponseCode associated with the packet.
|
||||
*/
|
||||
protected final INSResponseCode getResponseCode() {
|
||||
protected final INSResponseStatus getResponseCode() {
|
||||
return responseCode;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public abstract class OACPacket extends Packet {
|
||||
*
|
||||
* @param responseCode The INSResponseCode to set for the packet.
|
||||
*/
|
||||
protected final void setResponseCode(INSResponseCode responseCode) {
|
||||
protected final void setResponseCode(INSResponseStatus responseCode) {
|
||||
this.responseCode = responseCode;
|
||||
}
|
||||
|
||||
@@ -80,8 +80,8 @@ public abstract class OACPacket extends Packet {
|
||||
|
||||
// Read the response code if the protocol version is not classic
|
||||
if (protocolVersion != ProtocolVersion.PV_1_0_0_CLASSIC)
|
||||
responseCode = (INSResponseCode) objectInputStream.readObject();
|
||||
else responseCode = INSResponseCode.RESPONSE_NOT_REQUIRED;
|
||||
responseCode = (INSResponseStatus) objectInputStream.readObject();
|
||||
else responseCode = INSResponseStatus.RESPONSE_NOT_REQUIRED;
|
||||
|
||||
// Call the response code read handler
|
||||
onResponseCodeRead(packetHandler, objectInputStream);
|
||||
|
||||
@@ -11,26 +11,54 @@ import org.openautonomousconnection.protocol.side.ins.ConnectedProtocolClient;
|
||||
import org.openautonomousconnection.protocol.side.ins.events.ConnectedProtocolClientEvent;
|
||||
import org.openautonomousconnection.protocol.side.web.ConnectedWebClient;
|
||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseCode;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
/**
|
||||
* Authentication packet used between client and INS/Web servers.
|
||||
* <p>
|
||||
* Responsibilities:
|
||||
* <ul>
|
||||
* <li>Client → Server: Sends client ID and protocol version</li>
|
||||
* <li>Server → Client: Sends CA key, CA certificate and CA serial files</li>
|
||||
* <li>Performs version compatibility validation</li>
|
||||
* <li>Triggers authentication callbacks on both sides</li>
|
||||
* </ul>
|
||||
*/
|
||||
public final class AuthPacket extends OACPacket {
|
||||
|
||||
private ProtocolBridge protocolBridge;
|
||||
|
||||
/**
|
||||
* Creates a new authentication packet for sending CA data or client identity.
|
||||
*
|
||||
* @param protocolBridge The protocol context of the current instance.
|
||||
*/
|
||||
public AuthPacket(ProtocolBridge protocolBridge) {
|
||||
this();
|
||||
this.protocolBridge = protocolBridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registration constructor
|
||||
*/
|
||||
public AuthPacket() {
|
||||
super(4, ProtocolVersion.PV_1_0_0_BETA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes authentication data to the output stream.
|
||||
* <p>
|
||||
* Behavior differs based on the running side:
|
||||
* <ul>
|
||||
* <li>INS Server → sends CA bundle to the client</li>
|
||||
* <li>Client → sends client ID + protocol version</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException {
|
||||
if (protocolBridge.isRunningAsINSServer()) {
|
||||
@@ -56,7 +84,7 @@ public final class AuthPacket extends OACPacket {
|
||||
protocolBridge.getProtocolINSServer().getFolderStructure().caPrefix + NetworkUtils.getPublicIPAddress() + ".srl"));
|
||||
} catch (Exception exception) {
|
||||
protocolBridge.getLogger().exception("Failed to read ca-files", exception);
|
||||
setResponseCode(INSResponseCode.RESPONSE_AUTH_FAILED);
|
||||
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||
}
|
||||
|
||||
// Send ca data
|
||||
@@ -69,6 +97,15 @@ public final class AuthPacket extends OACPacket {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads authentication data and updates protocol state.
|
||||
* <p>
|
||||
* Behavior:
|
||||
* <ul>
|
||||
* <li>Server validates version and registers new connected client</li>
|
||||
* <li>Client saves received CA files and completes TLS initialization</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
|
||||
if (protocolBridge.isRunningAsINSServer() || protocolBridge.isRunningAsWebServer()) {
|
||||
@@ -77,10 +114,10 @@ public final class AuthPacket extends OACPacket {
|
||||
ConnectionHandler connectionHandler = protocolBridge.getProtocolINSServer().getNetworkServer().getConnectionHandlerByID(clientID);
|
||||
|
||||
if (!protocolBridge.isVersionSupported(clientVersion)) {
|
||||
setResponseCode(INSResponseCode.RESPONSE_AUTH_FAILED);
|
||||
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||
connectionHandler.disconnect();
|
||||
return;
|
||||
} else setResponseCode(INSResponseCode.RESPONSE_AUTH_SUCCESS);
|
||||
} else setResponseCode(INSResponseStatus.RESPONSE_AUTH_SUCCESS);
|
||||
|
||||
|
||||
if (protocolBridge.isRunningAsINSServer()) {
|
||||
@@ -95,10 +132,10 @@ public final class AuthPacket extends OACPacket {
|
||||
ProtocolVersion serverVersion = (ProtocolVersion) objectInputStream.readObject();
|
||||
|
||||
if (!protocolBridge.isVersionSupported(serverVersion)) {
|
||||
setResponseCode(INSResponseCode.RESPONSE_AUTH_FAILED);
|
||||
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||
protocolBridge.getProtocolClient().getClientINSConnection().disconnect();
|
||||
return;
|
||||
} else setResponseCode(INSResponseCode.RESPONSE_AUTH_SUCCESS);
|
||||
} else setResponseCode(INSResponseStatus.RESPONSE_AUTH_SUCCESS);
|
||||
|
||||
String caPrefix = objectInputStream.readUTF();
|
||||
|
||||
@@ -107,7 +144,7 @@ public final class AuthPacket extends OACPacket {
|
||||
String caSrl = objectInputStream.readUTF();
|
||||
|
||||
if (caKey.equalsIgnoreCase("N/A") || caPem.equalsIgnoreCase("N/A") || caSrl.equalsIgnoreCase("N/A"))
|
||||
setResponseCode(INSResponseCode.RESPONSE_AUTH_FAILED);
|
||||
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||
else {
|
||||
|
||||
File caPemFile = new File(protocolBridge.getProtocolClient().getFolderStructure().publicCAFolder, caPrefix + ".pem");
|
||||
@@ -124,7 +161,7 @@ public final class AuthPacket extends OACPacket {
|
||||
FileUtils.writeFile(caKeyFile, caSrl);
|
||||
} catch (Exception exception) {
|
||||
protocolBridge.getLogger().exception("Failed to create/save ca-files", exception);
|
||||
setResponseCode(INSResponseCode.RESPONSE_AUTH_FAILED);
|
||||
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
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.INSResponseCode;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.InfoName;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
public final class GetDestinationPacket extends OACPacket {
|
||||
private InfoName infoName;
|
||||
private int clientID;
|
||||
private INSResponseCode validationResponse;
|
||||
private String destination;
|
||||
private ProtocolBridge protocolBridge;
|
||||
|
||||
// INS-Server Constructor
|
||||
public GetDestinationPacket(InfoName infoName, INSResponseCode validationResponse, String destination, ProtocolBridge protocolBridge) {
|
||||
this();
|
||||
this.infoName = infoName;
|
||||
this.validationResponse = validationResponse;
|
||||
this.destination = destination;
|
||||
this.protocolBridge = protocolBridge;
|
||||
}
|
||||
|
||||
// Client Constructor
|
||||
public GetDestinationPacket(InfoName infoName, INSResponseCode validationResponse, ProtocolBridge protocolBridge) {
|
||||
this();
|
||||
this.infoName = infoName;
|
||||
this.validationResponse = validationResponse;
|
||||
this.destination = destination;
|
||||
this.protocolBridge = protocolBridge;
|
||||
}
|
||||
|
||||
// Registration Constructor
|
||||
public GetDestinationPacket() {
|
||||
super(6, ProtocolVersion.PV_1_0_0_BETA);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException {
|
||||
if (protocolBridge.isRunningAsClient()) {
|
||||
if (validationResponse != INSResponseCode.RESPONSE_INFONAME_FULLY_EXIST) return;
|
||||
|
||||
objectOutputStream.writeInt(protocolBridge.getProtocolClient().getClientINSConnection().getClientID());
|
||||
objectOutputStream.writeObject(infoName);
|
||||
objectOutputStream.writeObject(validationResponse);
|
||||
} else if (protocolBridge.isRunningAsINSServer()) {
|
||||
objectOutputStream.writeObject(infoName);
|
||||
objectOutputStream.writeObject(validationResponse);
|
||||
objectOutputStream.writeUTF(destination);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
|
||||
if (protocolBridge.isRunningAsINSServer()) {
|
||||
clientID = objectInputStream.readInt();
|
||||
infoName = (InfoName) objectInputStream.readObject();
|
||||
validationResponse = (INSResponseCode) objectInputStream.readObject();
|
||||
} else if (protocolBridge.isRunningAsClient()) {
|
||||
infoName = (InfoName) objectInputStream.readObject();
|
||||
validationResponse = (INSResponseCode) objectInputStream.readObject();
|
||||
destination = objectInputStream.readUTF();
|
||||
|
||||
protocolBridge.getProtocolClient().getDestinationCompleted(infoName, destination, validationResponse);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseCodeRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) {
|
||||
super.onResponseCodeRead(packetHandler, objectInputStream);
|
||||
|
||||
if (protocolBridge.isRunningAsINSServer()) {
|
||||
if (validationResponse != INSResponseCode.RESPONSE_INFONAME_FULLY_EXIST) return;
|
||||
destination = infoName.getDestination(protocolBridge);
|
||||
|
||||
try {
|
||||
protocolBridge.getProtocolINSServer().getClientByID(clientID).getConnectionHandler().sendPacket(new GetDestinationPacket(infoName, validationResponse, destination, protocolBridge));
|
||||
} catch (IOException | ClassNotFoundException exception) {
|
||||
protocolBridge.getProtocolINSServer().infoNameDestinationPacketFailedSend(protocolBridge.getProtocolINSServer().getClientByID(clientID), infoName, validationResponse, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.openautonomousconnection.protocol.packets.v1_0_0.beta;
|
||||
|
||||
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
|
||||
import org.openautonomousconnection.protocol.packets.OACPacket;
|
||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecordType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
/**
|
||||
* Packet used by clients to query INS records from an INS server.
|
||||
* <p>
|
||||
* Contains all information required for resolving an InfoName:
|
||||
* <ul>
|
||||
* <li>TLN</li>
|
||||
* <li>Name</li>
|
||||
* <li>Optional subname </li>
|
||||
* <li>Record type</li>
|
||||
* <li>Client ID for routing responses</li>
|
||||
* </ul>
|
||||
*/
|
||||
public final class INSQueryPacket extends OACPacket {
|
||||
|
||||
public String tln;
|
||||
public String name;
|
||||
public String sub;
|
||||
public INSRecordType type;
|
||||
public int clientId;
|
||||
|
||||
/**
|
||||
* Creates a new INS query packet with all required parameters.
|
||||
*
|
||||
* @param tln The top-level namespace.
|
||||
* @param name The InfoName.
|
||||
* @param sub Optional subname ("www") or null.
|
||||
* @param type Record type requested.
|
||||
* @param clientId Sender client ID for routing.
|
||||
*/
|
||||
public INSQueryPacket(String tln, String name, String sub, INSRecordType type, int clientId) {
|
||||
super(6, ProtocolVersion.PV_1_0_0_BETA);
|
||||
this.tln = tln;
|
||||
this.name = name;
|
||||
this.sub = sub;
|
||||
this.type = type;
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registration constructor
|
||||
*/
|
||||
public INSQueryPacket() {
|
||||
super(6, ProtocolVersion.PV_1_0_0_BETA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the INS query into the stream.
|
||||
*/
|
||||
@Override
|
||||
public void onWrite(PacketHandler handler, ObjectOutputStream out) throws IOException {
|
||||
out.writeUTF(tln);
|
||||
out.writeUTF(name);
|
||||
|
||||
out.writeBoolean(sub != null);
|
||||
if (sub != null) out.writeUTF(sub);
|
||||
|
||||
out.writeObject(type);
|
||||
out.writeInt(clientId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the INS query from the stream.
|
||||
*/
|
||||
@Override
|
||||
public void onRead(PacketHandler handler, ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
tln = in.readUTF();
|
||||
name = in.readUTF();
|
||||
|
||||
boolean hasSub = in.readBoolean();
|
||||
sub = hasSub ? in.readUTF() : null;
|
||||
|
||||
type = (INSRecordType) in.readObject();
|
||||
clientId = in.readInt();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
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.INSRecord;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Response packet returned by an INS server after resolving a query.
|
||||
* <p>
|
||||
* Contains:
|
||||
* <ul>
|
||||
* <li>Status code ({@link INSResponseStatus})</li>
|
||||
* <li>List of resolved {@link INSRecord} entries</li>
|
||||
* <li>The ID of the requesting client</li>
|
||||
* </ul>
|
||||
* On the client side, {@link org.openautonomousconnection.protocol.side.client.ProtocolClient#onResponse(INSResponseStatus, List)}
|
||||
* is automatically invoked through {@link #onResponseCodeRead}.
|
||||
*/
|
||||
public final class INSResponsePacket extends OACPacket {
|
||||
|
||||
private final ProtocolBridge bridge;
|
||||
public INSResponseStatus status;
|
||||
public List<INSRecord> records;
|
||||
public int clientId;
|
||||
|
||||
/**
|
||||
* Creates a populated response packet.
|
||||
*
|
||||
* @param status The resolution status.
|
||||
* @param records List of resolved records.
|
||||
* @param clientId ID of requesting client.
|
||||
* @param bridge Protocol runtime context.
|
||||
*/
|
||||
public INSResponsePacket(INSResponseStatus status, List<INSRecord> records, int clientId, ProtocolBridge bridge) {
|
||||
super(7, ProtocolVersion.PV_1_0_0_BETA);
|
||||
this.status = status;
|
||||
this.records = records;
|
||||
this.clientId = clientId;
|
||||
this.bridge = bridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registration Constructor
|
||||
*
|
||||
* @param bridge Protocol runtime context.
|
||||
*/
|
||||
public INSResponsePacket(ProtocolBridge bridge) {
|
||||
super(7, ProtocolVersion.PV_1_0_0_BETA);
|
||||
this.bridge = bridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the response status, records and client ID.
|
||||
*/
|
||||
@Override
|
||||
public void onWrite(PacketHandler handler, ObjectOutputStream out) throws IOException {
|
||||
out.writeObject(status);
|
||||
out.writeInt(records.size());
|
||||
|
||||
for (INSRecord rec : records) {
|
||||
out.writeObject(rec);
|
||||
}
|
||||
|
||||
out.writeInt(clientId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the response, reconstructing the record list.
|
||||
*/
|
||||
@Override
|
||||
public void onRead(PacketHandler handler, ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
status = (INSResponseStatus) in.readObject();
|
||||
|
||||
int size = in.readInt();
|
||||
records = new ArrayList<>(size);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
records.add((INSRecord) in.readObject());
|
||||
}
|
||||
|
||||
clientId = in.readInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after reading the server's response code.
|
||||
* <p>
|
||||
* If running on a client, forwards the result to the client-side API.
|
||||
*/
|
||||
@Override
|
||||
protected void onResponseCodeRead(PacketHandler handler, ObjectInputStream in) {
|
||||
if (bridge.isRunningAsClient()) {
|
||||
bridge.getProtocolClient().onResponse(status, records);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,36 @@ 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.INSResponseCode;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
/**
|
||||
* Internal compatibility packet used when a classic-protocol packet is received
|
||||
* but not supported by the current protocol version.
|
||||
* <p>
|
||||
* Instead of rejecting the packet entirely, the content and class name are forwarded
|
||||
* to the appropriate compatibility handler:
|
||||
* <ul>
|
||||
* <li>{@link org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerINSServer}</li>
|
||||
* <li>{@link org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerClient}</li>
|
||||
* <li>{@link org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerWebServer}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public final class UnsupportedClassicPacket extends OACPacket {
|
||||
private Class<? extends OACPacket> unsupportedClassicPacket;
|
||||
private Object[] content;
|
||||
private ProtocolBridge protocolBridge;
|
||||
|
||||
// Constructor with more information
|
||||
/**
|
||||
* Constructs a packet describing the unsupported classic packet and its content.
|
||||
*
|
||||
* @param unsupportedClassicPacket The packet class that was not understood.
|
||||
* @param content Serialized field values.
|
||||
* @param protocolBridge The protocol context.
|
||||
*/
|
||||
public UnsupportedClassicPacket(Class<? extends OACPacket> unsupportedClassicPacket, Object[] content, ProtocolBridge protocolBridge) {
|
||||
this();
|
||||
this.unsupportedClassicPacket = unsupportedClassicPacket;
|
||||
@@ -23,11 +41,16 @@ public final class UnsupportedClassicPacket extends OACPacket {
|
||||
this.protocolBridge = protocolBridge;
|
||||
}
|
||||
|
||||
// Registration Constructor
|
||||
/**
|
||||
* Registration Constructor
|
||||
*/
|
||||
public UnsupportedClassicPacket() {
|
||||
super(5, ProtocolVersion.PV_1_0_0_BETA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the class name and serialized object fields to the stream.
|
||||
*/
|
||||
@Override
|
||||
public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException {
|
||||
if (protocolBridge.isRunningAsClient())
|
||||
@@ -36,9 +59,12 @@ public final class UnsupportedClassicPacket extends OACPacket {
|
||||
objectOutputStream.writeUTF(unsupportedClassicPacket.getName());
|
||||
objectOutputStream.writeInt(content.length);
|
||||
for (Object o : content) objectOutputStream.writeObject(o);
|
||||
setResponseCode(INSResponseCode.RESPONSE_NOT_REQUIRED);
|
||||
setResponseCode(INSResponseStatus.RESPONSE_NOT_REQUIRED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the unsupported packet data and forwards it to the appropriate compatibility handler.
|
||||
*/
|
||||
@Override
|
||||
public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
|
||||
int clientID = 0;
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
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.InfoName;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
public final class ValidateInfoNamePacket extends OACPacket {
|
||||
private InfoName infoName;
|
||||
private int clientID;
|
||||
private ProtocolBridge protocolBridge;
|
||||
|
||||
public ValidateInfoNamePacket(InfoName infoName, ProtocolBridge protocolBridge) {
|
||||
this();
|
||||
this.infoName = infoName;
|
||||
this.protocolBridge = protocolBridge;
|
||||
}
|
||||
|
||||
public ValidateInfoNamePacket() {
|
||||
super(6, ProtocolVersion.PV_1_0_0_BETA);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWrite(PacketHandler packetHandler, ObjectOutputStream objectOutputStream) throws IOException, ClassNotFoundException {
|
||||
if (protocolBridge.isRunningAsClient())
|
||||
objectOutputStream.writeInt(protocolBridge.getProtocolClient().getClientINSConnection().getClientID());
|
||||
else if (protocolBridge.isRunningAsINSServer())
|
||||
setResponseCode(protocolBridge.getProtocolINSServer().validateInfoName(infoName));
|
||||
|
||||
objectOutputStream.writeObject(infoName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
|
||||
if (protocolBridge.isRunningAsINSServer()) clientID = objectInputStream.readInt();
|
||||
infoName = (InfoName) objectInputStream.readObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseCodeRead(PacketHandler packetHandler, ObjectInputStream objectInputStream) {
|
||||
super.onResponseCodeRead(packetHandler, objectInputStream);
|
||||
|
||||
if (protocolBridge.isRunningAsINSServer()) {
|
||||
try {
|
||||
protocolBridge.getProtocolINSServer().getClientByID(clientID).getConnectionHandler().sendPacket(new ValidateInfoNamePacket(infoName, protocolBridge));
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
protocolBridge.getProtocolINSServer().validationPacketSendFailed(infoName, protocolBridge.getProtocolINSServer().getClientByID(clientID), e);
|
||||
}
|
||||
|
||||
} else if (protocolBridge.isRunningAsClient())
|
||||
protocolBridge.getProtocolClient().validationCompleted(infoName, getResponseCode());
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ 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.INSResponseCode;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.events.Classic_PingPacketReceivedEvent;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_Domain;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_RequestDomain;
|
||||
|
||||
@@ -7,21 +7,18 @@ 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.ValidateInfoNamePacket;
|
||||
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.packets.v1_0_0.beta.INSQueryPacket;
|
||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseCode;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.InfoName;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_RequestDomain;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecordType;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Abstract class defining the client-side protocol operations and interactions with INS and web servers.
|
||||
@@ -38,23 +35,15 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider {
|
||||
*/
|
||||
@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;
|
||||
|
||||
/**
|
||||
* The reference to the ProtocolBridge Object
|
||||
*/
|
||||
@Getter
|
||||
private final ProtocolBridge protocolBridge;
|
||||
/**
|
||||
* Stores the protocol version of the connected server.
|
||||
*/
|
||||
private ProtocolVersion serverVersion = null;
|
||||
|
||||
/**
|
||||
* Initializes the ProtocolClient, setting up certificate folders and the INS client connection.
|
||||
@@ -85,33 +74,6 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider {
|
||||
return clientToINS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a web connection to the specified InfoName and ports.
|
||||
*
|
||||
* @param infoName the target InfoName 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(InfoName infoName, int pipelinePort, int webPort) throws Exception {
|
||||
// Ensure the protocol supports web connections
|
||||
if (!protocolBridge.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.getLogger().exception("Failed to close connection to web server", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify necessary certificate files exist
|
||||
webClient = new WebClient(infoName, pipelinePort, webPort, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the required certificate files exist in the specified folder.
|
||||
*
|
||||
@@ -172,15 +134,6 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider {
|
||||
public final void onINSDisconnect(ClientDisconnectedEvent event) {
|
||||
// Reset server version on INS disconnect
|
||||
serverVersion = null;
|
||||
|
||||
// Close web client connection if it exists
|
||||
if (webClient != null) {
|
||||
try {
|
||||
webClient.closeConnection();
|
||||
} catch (IOException e) {
|
||||
protocolBridge.getLogger().exception("Failed to close connection to web server", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -305,55 +258,46 @@ public abstract class ProtocolClient extends DefaultMethodsOverrider {
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the specified InfoName by sending a validation request to the INS server.
|
||||
* Sends an INS query to the INS server.
|
||||
* <p>
|
||||
* The client requests a specific record type for a given TLN, name and optional subname.
|
||||
* After sending the packet, {@link #onQuerySent(String, String, String, INSRecordType)} is invoked.
|
||||
*
|
||||
* @param infoName the InfoName 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.
|
||||
* @param tln The TLN.
|
||||
* @param name The InfoName.
|
||||
* @param sub Optional subname or {@code null}.
|
||||
* @param type The requested record type.
|
||||
* @throws IOException If sending the packet fails.
|
||||
* @throws ClassNotFoundException If packet serialization fails.
|
||||
*/
|
||||
public final void validateInfoName(InfoName infoName) throws IOException, ClassNotFoundException {
|
||||
// Send Classic_PingPacket if classic protocol is supported
|
||||
Classic_PingPacket cPingPacket = new Classic_PingPacket(new Classic_RequestDomain(infoName.getName(), infoName.getTopLevelName(), infoName.getPath(), protocolBridge), null, false, protocolBridge);
|
||||
if (protocolBridge.isClassicSupported()) clientToINS.sendPacket(cPingPacket);
|
||||
public final void sendINSQuery(String tln, String name, String sub, INSRecordType type) throws IOException, ClassNotFoundException {
|
||||
if (!protocolBridge.isRunningAsClient()) return;
|
||||
|
||||
// Send ValidateInfoNamePacket
|
||||
clientToINS.sendPacket(new ValidateInfoNamePacket(infoName, protocolBridge));
|
||||
getClientINSConnection().sendPacket(new INSQueryPacket(tln, name, sub, type, getClientINSConnection().getClientID()));
|
||||
onQuerySent(tln, name, sub, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the destination for the specified InfoName from the INS server.
|
||||
* Called when the client receives an INS response from the server.
|
||||
* <p>
|
||||
*
|
||||
* @param infoName the InfoName for which to request the destination.
|
||||
* @param responseCode the expected INSResponseCode 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.
|
||||
* @param status The response status from the server.
|
||||
* @param records The list of records returned by the server.
|
||||
*/
|
||||
public final void requestInfoName(InfoName infoName, INSResponseCode responseCode) throws IOException, ClassNotFoundException {
|
||||
// Send Classic_DomainPacket if classic protocol is supported
|
||||
Classic_DomainPacket cDomainPacket = new Classic_DomainPacket(0, new Classic_RequestDomain(infoName.getName(), infoName.getTopLevelName(), infoName.getPath(), protocolBridge), null, protocolBridge);
|
||||
if (protocolBridge.isClassicSupported()) clientToINS.sendPacket(cDomainPacket);
|
||||
public abstract void onResponse(INSResponseStatus status, List<INSRecord> records);
|
||||
|
||||
// Send GetDestinationPacket
|
||||
clientToINS.sendPacket(new GetDestinationPacket(infoName, responseCode, protocolBridge));
|
||||
/**
|
||||
* Called after a query was sent to the INS server.
|
||||
* <p>
|
||||
*
|
||||
* @param tln The TLN requested.
|
||||
* @param name The InfoName.
|
||||
* @param sub Optional subname.
|
||||
* @param type The requested record type.
|
||||
*/
|
||||
public void onQuerySent(String tln, String name, String sub, INSRecordType type) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method invoked when InfoName validation is completed.
|
||||
*
|
||||
* @param infoName the InfoName that was validated.
|
||||
* @param responseCode the INSResponseCode resulting from the validation.
|
||||
*/
|
||||
public abstract void validationCompleted(InfoName infoName, INSResponseCode responseCode);
|
||||
|
||||
/**
|
||||
* Callback method invoked when the destination retrieval is completed.
|
||||
*
|
||||
* @param infoName the InfoName for which the destination was requested.
|
||||
* @param destination the retrieved destination as a string.
|
||||
* @param validationResponse the INSResponseCode resulting from the destination retrieval.
|
||||
*/
|
||||
public abstract void getDestinationCompleted(InfoName infoName, String destination, INSResponseCode validationResponse);
|
||||
|
||||
/**
|
||||
* Manages the folder structure for client certificates.
|
||||
*/
|
||||
|
||||
@@ -1,239 +0,0 @@
|
||||
package org.openautonomousconnection.protocol.side.client;
|
||||
|
||||
import dev.unlegitdqrk.unlegitlibrary.network.system.client.NetworkClient;
|
||||
import lombok.Getter;
|
||||
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
|
||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.InfoName;
|
||||
|
||||
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.INS)
|
||||
public final class WebClient {
|
||||
/**
|
||||
* NetworkClient instance for managing the pipeline connection to the web server.
|
||||
*/
|
||||
private final NetworkClient clientToWebPipeline;
|
||||
/**
|
||||
* The Protocol Client associated with this protocol client.
|
||||
*/
|
||||
@Getter
|
||||
private final ProtocolClient protocolClient;
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Constructs a WebClient instance and establishes a secure connection to the web server.
|
||||
*
|
||||
* @param infoName The InfoName information for the web server.
|
||||
* @param pipelinePort The port for the pipeline connection.
|
||||
* @param webPort The port for the web server connection.
|
||||
* @param protocolClient The Protocol Client associated with this protocol client.
|
||||
* @throws Exception If an error occurs during connection setup.
|
||||
*/
|
||||
public WebClient(InfoName infoName, int pipelinePort, int webPort, ProtocolClient protocolClient) throws Exception {
|
||||
this.protocolClient = protocolClient;
|
||||
|
||||
// Initialize and connect the pipeline client
|
||||
clientToWebPipeline = new NetworkClient.ClientBuilder().
|
||||
// Set logger from ProtocolBridge
|
||||
setLogger(protocolClient.getProtocolBridge().getLogger()).
|
||||
// Set the destination and port for the pipeline connection
|
||||
setHost(infoName.getDestination(protocolClient.getProtocolBridge())).setPort(pipelinePort).
|
||||
|
||||
// Configure packet handler and event manager
|
||||
setPacketHandler(protocolClient.getProtocolBridge().getProtocolSettings().packetHandler).
|
||||
setEventManager(protocolClient.getProtocolBridge().getProtocolSettings().eventManager).
|
||||
|
||||
// Set proxy and ssl parameters from INS connection settings
|
||||
setProxy(protocolClient.getProtocolBridge().getProtocolClient().getClientINSConnection().getProxy()).
|
||||
setSSLParameters(protocolClient.getProtocolBridge().getProtocolClient().getClientINSConnection().getSocket().getSSLParameters()).
|
||||
|
||||
// Set certificates and folders for SSL
|
||||
setRootCAFolder(protocolClient.getProtocolBridge().getProtocolClient().getFolderStructure().publicCAFolder).
|
||||
setClientCertificatesFolder(protocolClient.getProtocolBridge().getProtocolClient().getFolderStructure().publicClientFolder,
|
||||
protocolClient.getProtocolBridge().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(protocolClient.getProtocolBridge().getProtocolClient().getFolderStructure().publicCAFolder,
|
||||
protocolClient.getProtocolBridge().getProtocolClient().getFolderStructure().publicClientFolder,
|
||||
protocolClient.getProtocolBridge().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(infoName.getDestination(protocolClient.getProtocolBridge()), webPort), 0);
|
||||
tempSocket = (SSLSocket) sslSocketFactory.createSocket(rawSocket, infoName.getDestination(protocolClient.getProtocolBridge()), webPort, true);
|
||||
} else {
|
||||
tempSocket = (SSLSocket) sslSocketFactory.createSocket(infoName.getDestination(protocolClient.getProtocolBridge()), 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;
|
||||
} /**
|
||||
* Thread for receiving data from the web server.
|
||||
*/
|
||||
private final Thread receiveThread = new Thread(this::receive);
|
||||
|
||||
/**
|
||||
* 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() &&
|
||||
protocolClient.getProtocolBridge().getProtocolClient().getClientINSConnection().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) {
|
||||
protocolClient.getProtocolBridge().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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -8,8 +8,8 @@ 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.INSResponseCode;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.InfoName;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecordType;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
@@ -33,24 +33,21 @@ public abstract class ProtocolINSServer extends DefaultMethodsOverrider {
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The reference to the ProtocolBridge Object
|
||||
*/
|
||||
@Getter
|
||||
private final ProtocolBridge protocolBridge;
|
||||
/**
|
||||
* List of connected protocol clients.
|
||||
*/
|
||||
@Getter
|
||||
private List<ConnectedProtocolClient> clients;
|
||||
/**
|
||||
* The folder structure for server certificates.
|
||||
*/
|
||||
@Getter
|
||||
private ServerCertificateFolderStructure folderStructure;
|
||||
|
||||
/**
|
||||
* Constructs a ProtocolINSServer with the specified configuration file.
|
||||
@@ -164,6 +161,61 @@ public abstract class ProtocolINSServer extends DefaultMethodsOverrider {
|
||||
return configurationManager.getString("server.site.info");
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a request for an INS record based on TLN, name, subname and record type.
|
||||
* <p>
|
||||
* The implementation should:
|
||||
* <ul>
|
||||
* <li>Locate the corresponding InfoName in storage</li>
|
||||
* <li>Return all matching {@link INSRecord} entries</li>
|
||||
* <li>Handle CNAME recursion, TTL rules, and filtering for the requested type</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param tln The top-level name.
|
||||
* @param name The InfoName.
|
||||
* @param sub The optional subname , may be {@code null}.
|
||||
* @param type The INS record type being requested.
|
||||
* @return A list of resolved INS records. May be empty if no record exists.
|
||||
*/
|
||||
public abstract List<INSRecord> resolve(String tln, String name, String sub, INSRecordType type);
|
||||
|
||||
/**
|
||||
* Callback fired whenever the INS server receives a query packet.
|
||||
* <p>This method is optional.</p>
|
||||
*
|
||||
* @param tln The top-level name of the request.
|
||||
* @param name The InfoName being queried.
|
||||
* @param sub An optional subname, or {@code null}.
|
||||
* @param type The record type requested.
|
||||
*/
|
||||
public void onQueryReceived(String tln, String name, String sub, INSRecordType type) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback fired after an INS response was successfully sent to the client.
|
||||
*
|
||||
* @param tln The requested TLN.
|
||||
* @param name The InfoName.
|
||||
* @param sub Optional subname or {@code null}.
|
||||
* @param type The requested record type.
|
||||
* @param results The records returned to the client.
|
||||
*/
|
||||
public void onResponseSent(String tln, String name, String sub, INSRecordType type, List<INSRecord> results) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback fired when an INS response could not be delivered to the client.
|
||||
*
|
||||
* @param tln The requested TLN.
|
||||
* @param name The InfoName.
|
||||
* @param sub Optional subname.
|
||||
* @param type The record type requested.
|
||||
* @param results The records that would have been sent.
|
||||
* @param exception The exception describing the failure.
|
||||
*/
|
||||
public void onResponseSentFailed(String tln, String name, String sub, INSRecordType type, List<INSRecord> results, Exception exception) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the INS registration site URL from the configuration.
|
||||
*
|
||||
@@ -173,65 +225,6 @@ public abstract class ProtocolINSServer extends DefaultMethodsOverrider {
|
||||
return configurationManager.getString("server.site.register");
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method to retrieve the list of InfoNames managed by the INS server.
|
||||
*
|
||||
* @return A list of InfoName objects.
|
||||
*/
|
||||
public abstract List<InfoName> getInfoNames();
|
||||
|
||||
/**
|
||||
* @param infoName The InfoName to look up.
|
||||
* @return The destination associated with the InfoName.
|
||||
* @see InfoName#getDestination(ProtocolBridge)
|
||||
* Abstract method to get the destination for a given InfoName.
|
||||
*/
|
||||
public abstract String getInfoNameDestination(InfoName infoName);
|
||||
|
||||
/**
|
||||
* @param infoName The parent InfoName.
|
||||
* @param subname The subname to look up.
|
||||
* @return The destination associated with the subname.
|
||||
* @see InfoName#getDestination(ProtocolBridge)
|
||||
* Abstract method to get the destination for a given subname under a specific InfoName.
|
||||
*/
|
||||
public abstract String getSubnameDestination(InfoName infoName, String subname);
|
||||
|
||||
/**
|
||||
* @param topLevelName The top-level name.
|
||||
* @return The information site URL for the specified top-level name.
|
||||
* @see InfoName#getDestination(ProtocolBridge)
|
||||
* Abstract method to get the top-level name information site URL.
|
||||
*/
|
||||
public abstract String getTLNInfoSite(String topLevelName);
|
||||
|
||||
/**
|
||||
* Abstract method to validate a requested InfoName.
|
||||
*
|
||||
* @param requestedInfoName The InfoName to validate.
|
||||
* @return A INSResponseCode indicating the result of the validation.
|
||||
*/
|
||||
public abstract INSResponseCode validateInfoName(InfoName requestedInfoName);
|
||||
|
||||
/**
|
||||
* Abstract method called when a validation packet fails to send.
|
||||
*
|
||||
* @param infoName The InfoName associated with the validation.
|
||||
* @param client The connected protocol client.
|
||||
* @param exception The exception that occurred during sending.
|
||||
*/
|
||||
public abstract void validationPacketSendFailed(InfoName infoName, ConnectedProtocolClient client, Exception exception);
|
||||
|
||||
/**
|
||||
* Abstract method called when a InfoName destination packet fails to send.
|
||||
*
|
||||
* @param client The connected protocol client.
|
||||
* @param infoName The InfoName associated with the packet.
|
||||
* @param validationResponse The INS response code from validation.
|
||||
* @param exception The exception that occurred during sending.
|
||||
*/
|
||||
public abstract void infoNameDestinationPacketFailedSend(ConnectedProtocolClient client, InfoName infoName, INSResponseCode validationResponse, Exception exception);
|
||||
|
||||
/**
|
||||
* Class representing the folder structure for server certificates.
|
||||
*/
|
||||
|
||||
@@ -68,10 +68,7 @@ public final class ConnectedWebClient {
|
||||
*/
|
||||
public ConnectedWebClient(ConnectionHandler pipelineConnection) {
|
||||
this.pipelineConnection = pipelineConnection;
|
||||
} /**
|
||||
* Thread for receiving data from the client.
|
||||
*/
|
||||
private final Thread receiveThread = new Thread(this::receive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an HTTP redirect response to the client.
|
||||
@@ -96,7 +93,10 @@ public final class ConnectedWebClient {
|
||||
// End of headers
|
||||
out.write("\r\n".getBytes());
|
||||
out.flush();
|
||||
}
|
||||
} /**
|
||||
* Thread for receiving data from the client.
|
||||
*/
|
||||
private final Thread receiveThread = new Thread(this::receive);
|
||||
|
||||
/**
|
||||
* Parses POST parameters from the input stream.
|
||||
|
||||
@@ -62,6 +62,11 @@ public final class ProtocolWebServer {
|
||||
* The configuration file for the web server.
|
||||
*/
|
||||
private final File configFile;
|
||||
/**
|
||||
* The reference to the ProtocolBridge Object
|
||||
*/
|
||||
@Getter
|
||||
private final ProtocolBridge protocolBridge;
|
||||
/**
|
||||
* The network server handling pipeline connections.
|
||||
*/
|
||||
@@ -83,12 +88,6 @@ public final class ProtocolWebServer {
|
||||
@Getter
|
||||
private String uniqueSessionString;
|
||||
|
||||
/**
|
||||
* The reference to the ProtocolBridge Object
|
||||
*/
|
||||
@Getter
|
||||
private final ProtocolBridge protocolBridge;
|
||||
|
||||
/**
|
||||
* Initializes the web server with the given configuration, authentication, and rules files.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@ public enum ProtocolVersion implements Serializable {
|
||||
/**
|
||||
* 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);
|
||||
PV_1_0_0_BETA("1.0.0", ProtocolType.BETA, ProtocolSide.ALL, List.of(Protocol.OAC));
|
||||
|
||||
/**
|
||||
* The version string of the protocol version.
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.openautonomousconnection.protocol.versions.v1_0_0.beta;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represents a INS record inside the INS system.
|
||||
* <p>
|
||||
* This is the transport format used in responses and packets.
|
||||
* Each record contains:
|
||||
* <ul>
|
||||
* <li>The record type (A, AAAA, CNAME, TXT, ...)</li>
|
||||
* <li>A value (IPv4, IPv6, hostname, text, ...)</li>
|
||||
* <li>Optional priority and weight fields (MX, SRV)</li>
|
||||
* <li>Optional port field (SRV)</li>
|
||||
* <li>A TTL defining how long the record may be cached</li>
|
||||
* </ul>
|
||||
*/
|
||||
public final class INSRecord implements Serializable {
|
||||
|
||||
public INSRecordType type;
|
||||
public String value;
|
||||
public int priority;
|
||||
public int weight;
|
||||
public int port;
|
||||
public int ttl;
|
||||
|
||||
/**
|
||||
* Creates an INS record object.
|
||||
*
|
||||
* @param type The INS record type.
|
||||
* @param value The record’s data (IPv4, IPv6, hostname, text, etc.).
|
||||
* @param priority MX / SRV priority value (ignored for other types).
|
||||
* @param weight SRV weight (ignored for other types).
|
||||
* @param port SRV port (ignored for other types).
|
||||
* @param ttl Time-to-live for caching.
|
||||
*/
|
||||
public INSRecord(INSRecordType type, String value, int priority, int weight, int port, int ttl) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
this.priority = priority;
|
||||
this.weight = weight;
|
||||
this.port = port;
|
||||
this.ttl = ttl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type + ":" + value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.openautonomousconnection.protocol.versions.v1_0_0.beta;
|
||||
|
||||
/**
|
||||
* Represents INS record types for the INS protocol.
|
||||
* <p>
|
||||
* Supported types:
|
||||
* <ul>
|
||||
* <li>A — IPv4 address</li>
|
||||
* <li>AAAA — IPv6 address</li>
|
||||
* <li>CNAME — Canonical name redirect</li>
|
||||
* <li>TXT — Arbitrary text</li>
|
||||
* <li>MX — Mail exchanger</li>
|
||||
* <li>SRV — Service locator</li>
|
||||
* <li>NS — Nameserver delegation</li>
|
||||
* <li>PTR — Reverse pointer record</li>
|
||||
* <li>CAA — Certificate authority authorization</li>
|
||||
* </ul>
|
||||
*/
|
||||
public enum INSRecordType {
|
||||
A,
|
||||
AAAA,
|
||||
CNAME,
|
||||
TXT,
|
||||
MX,
|
||||
SRV,
|
||||
NS,
|
||||
PTR,
|
||||
CAA
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package org.openautonomousconnection.protocol.versions.v1_0_0.beta;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Enum representing various INS response codes and their descriptions.
|
||||
*/
|
||||
public enum INSResponseCode 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"),
|
||||
|
||||
/**
|
||||
* InfoName Responses
|
||||
*/
|
||||
RESPONSE_INFONAME_NAME_EXIST(100, "Infoname exist"),
|
||||
RESPONSE_INFONAME_NAME_NOT_EXIST(101, "Infoname does not exist"),
|
||||
RESPONSE_INFONAME_NAME_CREATED(105, "Infoname created"),
|
||||
RESPONSE_INFONAME_NAME_DELETED(106, "Infoname deleted"),
|
||||
|
||||
/**
|
||||
* Top Level Name Responses
|
||||
*/
|
||||
RESPONSE_INFONAME_TLN_EXIST(110, "TopLevelName exist"),
|
||||
RESPONSE_INFONAME_TLN_NOT_EXIST(111, "TopLevelName does not exist"),
|
||||
RESPONSE_INFONAME_TLN_CREATED(115, "TopLevelName created"),
|
||||
RESPONSE_INFONAME_TLN_DELETED(116, "TopLevelName deleted"),
|
||||
|
||||
/**
|
||||
* Subname Responses
|
||||
*/
|
||||
RESPONSE_INFONAME_SUBNAME_EXIST(120, "Subname exist"),
|
||||
RESPONSE_INFONAME_SUBNAME_NOT_EXIST(121, "Subname does not exist"),
|
||||
RESPONSE_INFONAME_SUBNAME_CREATED(125, "Subname created"),
|
||||
RESPONSE_INFONAME_SUBNAME_DELETED(126, "Subname deleted"),
|
||||
|
||||
/**
|
||||
* Full InfoName Responses
|
||||
*/
|
||||
RESPONSE_INFONAME_FULLY_EXIST(130, "Full Infoname exist"),
|
||||
RESPONSE_INFONAME_FULLY_NOT_EXIST(131, "Full Infoname does not exist");
|
||||
|
||||
/**
|
||||
* The numeric code representing the INS response.
|
||||
*/
|
||||
@Getter
|
||||
private final int code;
|
||||
|
||||
/**
|
||||
* A brief description of the INS response code.
|
||||
*/
|
||||
@Getter
|
||||
private final String description;
|
||||
|
||||
/**
|
||||
* Constructor for INSResponseCode enum.
|
||||
*
|
||||
* @param code The numeric code of the response.
|
||||
* @param description A brief description of the response.
|
||||
*/
|
||||
INSResponseCode(int code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the INS response code, including its code and description.
|
||||
*
|
||||
* @return a string representation of the INS response code.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{code=" + code + ";description=" + description + "}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.openautonomousconnection.protocol.versions.v1_0_0.beta;
|
||||
|
||||
/**
|
||||
* Defines the possible response states returned by the INS server.
|
||||
*/
|
||||
public enum INSResponseStatus {
|
||||
/**
|
||||
* Request succeeded and matching records were found.
|
||||
*/
|
||||
OK,
|
||||
|
||||
/**
|
||||
* No records exist for the queried TLN/name/sub/type combination.
|
||||
*/
|
||||
NOT_FOUND,
|
||||
|
||||
/**
|
||||
* The query was malformed or missing required parameters.
|
||||
*/
|
||||
INVALID_REQUEST,
|
||||
|
||||
/**
|
||||
* Internal server error occurred while resolving the request.
|
||||
*/
|
||||
SERVER_ERROR,
|
||||
|
||||
/**
|
||||
* Response is not required for the specific request type.
|
||||
*/
|
||||
RESPONSE_NOT_REQUIRED,
|
||||
|
||||
/**
|
||||
* Authentication failed.
|
||||
*/
|
||||
RESPONSE_AUTH_FAILED,
|
||||
|
||||
/**
|
||||
* Authentication succeeded.
|
||||
*/
|
||||
RESPONSE_AUTH_SUCCESS
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
package org.openautonomousconnection.protocol.versions.v1_0_0.beta;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Class representing a InfoName with its components such as subname, name, top-level name, path, query, fragment, and protocol.
|
||||
*/
|
||||
public final class InfoName implements Serializable {
|
||||
/**
|
||||
* The subname of the InfoName (e.g., "sub" in "sub.example.com").
|
||||
*/
|
||||
@Getter
|
||||
private final String subname;
|
||||
|
||||
/**
|
||||
* The main name of the InfoName (e.g., "example" in "sub.example.com").
|
||||
*/
|
||||
@Getter
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The top-level name of the InfoName (e.g., "com" in "sub.example.com").
|
||||
*/
|
||||
@Getter
|
||||
private final String topLevelName;
|
||||
|
||||
/**
|
||||
* The path component of the InfoName (e.g., "path/to/resource" in "example.com/path/to/resource").
|
||||
*/
|
||||
@Getter
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* The query component of the InfoName (e.g., "key=value" in "example.com/path?key=value").
|
||||
*/
|
||||
@Getter
|
||||
private String query;
|
||||
|
||||
/**
|
||||
* The fragment component of the InfoName (e.g., "section1" in "example.com/path#section1").
|
||||
*/
|
||||
@Getter
|
||||
private String fragment;
|
||||
|
||||
/**
|
||||
* The protocol of the InfoName (e.g., "oac" in "oac://example.com").
|
||||
*/
|
||||
@Getter
|
||||
private String protocol;
|
||||
|
||||
/**
|
||||
* Constructs a InfoName object by parsing the provided full InfoName string.
|
||||
*
|
||||
* @param fullInfoName The full InfoName string to parse.
|
||||
* @throws IllegalArgumentException if the InfoName is invalid.
|
||||
*/
|
||||
public InfoName(String fullInfoName) {
|
||||
// Remove protocol
|
||||
String infoNameWithPath = fullInfoName.contains("://") ? fullInfoName.split("://", 2)[1] : fullInfoName;
|
||||
this.protocol = fullInfoName.contains("://") ? fullInfoName.split("://", 2)[0] : "";
|
||||
if (this.protocol.endsWith("://"))
|
||||
this.protocol = this.protocol.substring(0, this.protocol.length() - "://".length());
|
||||
|
||||
// Cut path
|
||||
String[] infoNamePartsAndPath = infoNameWithPath.split("/", 2);
|
||||
|
||||
// Get host and full path
|
||||
String host = infoNamePartsAndPath[0];
|
||||
String fullPath = infoNamePartsAndPath.length > 1 ? "/" + infoNamePartsAndPath[1] : "";
|
||||
|
||||
// Split InfoName in labels
|
||||
List<String> labels = Arrays.asList(host.split("\\."));
|
||||
if (labels.size() < 2) throw new IllegalArgumentException("Invalid InfoName: " + 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());
|
||||
} else this.fragment = "";
|
||||
|
||||
// Split path and query
|
||||
if (fullPath.contains("?")) {
|
||||
String[] parts = fullPath.split("\\?", 2);
|
||||
this.path = parts[0];
|
||||
this.query = parts[1];
|
||||
} else {
|
||||
this.path = fullPath;
|
||||
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);
|
||||
|
||||
if (this.query.startsWith("?")) this.query = this.query.substring(1);
|
||||
if (this.fragment.startsWith("#")) this.fragment = this.fragment.substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the InfoName has a subname.
|
||||
*
|
||||
* @return true if the InfoName has a subname, false otherwise.
|
||||
*/
|
||||
public boolean hasSubname() {
|
||||
return subname != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this InfoName is equal to another object.
|
||||
* Two InfoNames are considered equal if their subname, name, top-level name, and protocol are equal (case-insensitive).
|
||||
*
|
||||
* @return true if the InfoNames are equal, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// Check if the object is an instance of InfoName
|
||||
if (!(obj instanceof InfoName infoName)) return false;
|
||||
|
||||
// Compare subname, name, top-level name, and protocol (case-insensitive)
|
||||
return infoName.getSubname().equalsIgnoreCase(this.subname) && infoName.getName().equalsIgnoreCase(this.name) &&
|
||||
infoName.getTopLevelName().equalsIgnoreCase(this.topLevelName) && infoName.getProtocol().equalsIgnoreCase(this.protocol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the destination associated with this InfoName.
|
||||
* The destination is determined based on the InfoName's components and the current protocol context.
|
||||
*
|
||||
* @return the destination as a string.
|
||||
*/
|
||||
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.INS)
|
||||
public String getDestination(ProtocolBridge protocolBridge) {
|
||||
// If running as client or web server, return invalid request
|
||||
if (protocolBridge.isRunningAsClient() || protocolBridge.isRunningAsWebServer())
|
||||
return INSResponseCode.RESPONSE_INVALID_REQUEST.toString();
|
||||
|
||||
// Handle special default InfoNames
|
||||
if (this.equals(DefaultInfoNames.INS_INFO_SITE))
|
||||
return protocolBridge.getProtocolINSServer().getINSInfoSite();
|
||||
if (this.equals(DefaultInfoNames.INS_REGISTER_SITE))
|
||||
return protocolBridge.getProtocolINSServer().getINSRegisterSite();
|
||||
if (this.equals(DefaultInfoNames.TLN_INFO_SITE(topLevelName)))
|
||||
return protocolBridge.getProtocolINSServer().getTLNInfoSite(topLevelName);
|
||||
|
||||
// Return destination based on whether subname exists
|
||||
return !hasSubname() ? protocolBridge.getProtocolINSServer().getInfoNameDestination(this) : protocolBridge.getProtocolINSServer().getSubnameDestination(this, subname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the InfoName, including its protocol, subname, name, top-level name, path, query, and fragment.
|
||||
*/
|
||||
public static class DefaultInfoNames {
|
||||
public static final InfoName INS_INFO_SITE = new InfoName("oac://info.oac/");
|
||||
public static final InfoName INS_REGISTER_SITE = new InfoName("oac://register.oac/");
|
||||
|
||||
public static InfoName TLN_INFO_SITE(String topLevelName) {
|
||||
return new InfoName("oac://about." + topLevelName + "/");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.openautonomousconnection.protocol.ProtocolBridge;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.InfoName;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@@ -15,20 +14,20 @@ import java.io.Serializable;
|
||||
public class Classic_Domain implements Serializable {
|
||||
|
||||
/**
|
||||
* The name of the domain (e.g., "example" in "example.com").
|
||||
* The name of the domain.
|
||||
*/
|
||||
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
|
||||
public final String name;
|
||||
|
||||
/**
|
||||
* The top-level domain (e.g., "com" in "example.com").
|
||||
* The top-level domain.
|
||||
*/
|
||||
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
|
||||
public final String topLevelDomain;
|
||||
|
||||
|
||||
/**
|
||||
* The path component of the domain (e.g., "/path/to/resource" in "example.com/path/to/resource").
|
||||
* The path component of the domain.
|
||||
*/
|
||||
@Deprecated(forRemoval = false, since = "1.0.0-BETA.3")
|
||||
public final String path;
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils;
|
||||
|
||||
import org.openautonomousconnection.protocol.ProtocolBridge;
|
||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.InfoName;
|
||||
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_Domain;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user