+ * This implementation expects a table schema similar to: + *
+ * CREATE TABLE ins_records (
+ * id BIGINT PRIMARY KEY AUTO_INCREMENT,
+ * tln VARCHAR(64) NOT NULL,
+ * name VARCHAR(255) NOT NULL,
+ * sub VARCHAR(255) NULL,
+ * type VARCHAR(16) NOT NULL, -- matches {@link INSRecordType#name()}
+ * value VARCHAR(1024) NOT NULL,
+ * priority INT NOT NULL,
+ * weight INT NOT NULL,
+ * port INT NOT NULL,
+ * ttl INT NOT NULL
+ * );
+ *
+ * CREATE TABLE ins_tln_info (
+ * tln VARCHAR(64) PRIMARY KEY,
+ * host VARCHAR(255) NOT NULL,
+ * port INT NOT NULL
+ * );
+ *
+ */
+public final class DatabaseINSServer extends ProtocolINSServer {
+
+ private final String jdbcUrl;
+ private final String jdbcUser;
+ private final String jdbcPassword;
+
+ private final ConfigurationManager configurationManager;
+
+ /**
+ * Creates a new database-backed INS server.
+ *
+ * @throws IOException If the base server initialization fails.
+ * @throws CertificateException If required certificate files are missing or invalid.
+ */
+ public DatabaseINSServer() throws IOException, CertificateException {
+ super(new File("config.properties"));
+
+ configurationManager = new ConfigurationManager(new File("config.properties"));
+ configurationManager.loadProperties();
+
+ if (!configurationManager.isSet("db.url")) {
+ configurationManager.set("db.url", "jdbc:mysql://localhost:3306/DB_NAME?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC\n");
+ configurationManager.saveProperties();
+ }
+
+ if (!configurationManager.isSet("db.user")) {
+ configurationManager.set("db.user", "username");
+ configurationManager.saveProperties();
+ }
+
+ if (!configurationManager.isSet("db.password")) {
+ configurationManager.set("db.password", "password");
+ configurationManager.saveProperties();
+ }
+
+ jdbcUrl = configurationManager.getString("db.url");
+ jdbcUser = configurationManager.getString("db.user");
+ jdbcPassword = configurationManager.getString("db.password");
+ }
+
+ private Connection openConnection() throws SQLException {
+ return DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
+ }
+
+ /**
+ * Resolves records for the given INS name from the database.
+ *
+ * This method does a single lookup and returns exactly the records that
+ * match the given query (no CNAME recursion here – that is handled on a
+ * higher level, e.g. via {@code INSRecordTools.resolveWithCNAME(...)}).
+ *
+ * @param tln Top-level-name.
+ * @param name InfoName.
+ * @param sub Optional sub-name. May be {@code null}.
+ * @param type Desired record type.
+ *
+ * @return List of matching {@link INSRecord}s, or an empty list if none exist.
+ */
+ @Override
+ public List
+ * The result must be returned as {@code "host:port"}.
+ *
+ * @param tln The TLN the client is asking about.
+ *
+ * @return A {@code "host:port"} string or {@code null} if no TLN info site is configured.
+ */
+ @Override
+ public String resolveTLNInfoSite(String tln) {
+ String sql = "SELECT host, port FROM ins_tln_info WHERE tln = ?";
+
+ try (Connection conn = openConnection();
+ PreparedStatement ps = conn.prepareStatement(sql)) {
+
+ ps.setString(1, tln);
+
+ try (ResultSet rs = ps.executeQuery()) {
+ if (rs.next()) {
+ String host = rs.getString("host");
+ int port = rs.getInt("port");
+ return host + ":" + port;
+ }
+ }
+ } catch (SQLException ex) {
+ getProtocolBridge().getLogger().exception("Failed to resolve TLN info site for tln=" + tln, ex);
+ }
+
+ return null;
+ }
+}
diff --git a/src/main/java/org/openautonomousconnection/dns/Listener.java b/src/main/java/org/openautonomousconnection/ins/Listener.java
similarity index 95%
rename from src/main/java/org/openautonomousconnection/dns/Listener.java
rename to src/main/java/org/openautonomousconnection/ins/Listener.java
index 825f007..69d01e4 100644
--- a/src/main/java/org/openautonomousconnection/dns/Listener.java
+++ b/src/main/java/org/openautonomousconnection/ins/Listener.java
@@ -1,4 +1,4 @@
-package org.openautonomousconnection.dns;
+package org.openautonomousconnection.ins;
import dev.unlegitdqrk.unlegitlibrary.command.events.CommandExecutorMissingPermissionEvent;
import dev.unlegitdqrk.unlegitlibrary.command.events.CommandNotFoundEvent;
diff --git a/src/main/java/org/openautonomousconnection/dns/Main.java b/src/main/java/org/openautonomousconnection/ins/Main.java
similarity index 69%
rename from src/main/java/org/openautonomousconnection/dns/Main.java
rename to src/main/java/org/openautonomousconnection/ins/Main.java
index aed2689..35d424d 100644
--- a/src/main/java/org/openautonomousconnection/dns/Main.java
+++ b/src/main/java/org/openautonomousconnection/ins/Main.java
@@ -1,16 +1,16 @@
-package org.openautonomousconnection.dns;
+package org.openautonomousconnection.ins;
import dev.unlegitdqrk.unlegitlibrary.command.CommandExecutor;
import dev.unlegitdqrk.unlegitlibrary.command.CommandManager;
import dev.unlegitdqrk.unlegitlibrary.command.CommandPermission;
-import dev.unlegitdqrk.unlegitlibrary.utils.Logger;
+import lombok.Getter;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.ProtocolSettings;
+import org.openautonomousconnection.protocol.side.ins.ProtocolINSServer;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
+import javax.annotation.processing.Generated;
import java.io.File;
-import java.io.IOException;
-import java.security.cert.CertificateException;
import java.util.Scanner;
public class Main {
@@ -18,11 +18,13 @@ public class Main {
private static final CommandExecutor commandExecutor = new CommandExecutor("DNS", PERMISSION_ALL) {};
private static CommandManager commandManager;
+ @Getter
+ private static ProtocolBridge protocolBridge;
+
public static void main(String[] args) throws Exception {
ProtocolSettings settings = new ProtocolSettings();
- new ProtocolBridge(new Server(), settings, ProtocolVersion.PV_1_0_0_BETA, new File("logs"));
- ProtocolBridge.getInstance().setClassicHandlerDNSServer(new ClassicHandler());
- commandManager = new CommandManager(ProtocolBridge.getInstance().getProtocolSettings().eventManager);
+ protocolBridge = new ProtocolBridge(new DatabaseINSServer(), settings, ProtocolVersion.PV_1_0_0_BETA, new File("logs"));
+ commandManager = new CommandManager(protocolBridge.getProtocolSettings().eventManager);
Scanner scanner = new Scanner(System.in);
while (true) {
diff --git a/src/main/java/org/openautonomousconnection/ins/utils/ClassicHelper.java b/src/main/java/org/openautonomousconnection/ins/utils/ClassicHelper.java
new file mode 100644
index 0000000..4927764
--- /dev/null
+++ b/src/main/java/org/openautonomousconnection/ins/utils/ClassicHelper.java
@@ -0,0 +1,38 @@
+package org.openautonomousconnection.ins.utils;
+
+import org.openautonomousconnection.ins.Main;
+import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord;
+import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_Domain;
+import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_RequestDomain;
+
+public class ClassicHelper {
+ public static Classic_Domain buildClassicDomain(ParsedDomain req, INSRecord rec) {
+ Classic_Domain info = new Classic_Domain(req.name, req.tln, req.sub, req.path, Main.getProtocolBridge());
+
+ String host = rec.value;
+ int port = rec.port > 0 ? rec.port : 80;
+
+ return new Classic_Domain(
+ req.name, req.tln,
+ host.contains(":") ? host : host + ":" + port,
+ req.path, Main.getProtocolBridge());
+ }
+
+ public static ParsedDomain parseDomain(Classic_RequestDomain req) {
+ String tln = req.topLevelDomain; // example: "net"
+ String full = req.name; // example: "api.v1.example"
+
+ String[] parts = full.split("\\.");
+
+ if (parts.length == 1) {
+ return new ParsedDomain(tln, full, null, req.path);
+ }
+
+ String name = parts[parts.length - 1];
+ String sub = parts.length > 1
+ ? String.join(".", java.util.Arrays.copyOfRange(parts, 0, parts.length - 1))
+ : null;
+
+ return new ParsedDomain(tln, name, sub, req.path);
+ }
+}
diff --git a/src/main/java/org/openautonomousconnection/ins/utils/ParsedDomain.java b/src/main/java/org/openautonomousconnection/ins/utils/ParsedDomain.java
new file mode 100644
index 0000000..3089d15
--- /dev/null
+++ b/src/main/java/org/openautonomousconnection/ins/utils/ParsedDomain.java
@@ -0,0 +1,15 @@
+package org.openautonomousconnection.ins.utils;
+
+public final class ParsedDomain {
+ public final String tln;
+ public final String name;
+ public final String sub;
+ public final String path;
+
+ public ParsedDomain(String tln, String name, String sub, String path) {
+ this.tln = tln;
+ this.name = name;
+ this.sub = sub;
+ this.path = path;
+ }
+}
\ No newline at end of file