Advanced InfoNameSystem
This commit is contained in:
@@ -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