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