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.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.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.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; import org.openautonomousconnection.protocol.side.client.ProtocolClient; import org.openautonomousconnection.protocol.side.ins.ProtocolINSServer; 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.ClassicHandlerINSServer; 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.net.Proxy; /** * The main bridge class for the protocol connection. * It manages the protocol settings, version, and side instances. */ public final class ProtocolBridge { /** * 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 ProtocolINSServer protocolINSServer; /** * The protocol side instances */ @Getter private ProtocolClient protocolClient; /** * The protocol side instances */ @Getter private ProtocolWebServer protocolWebServer; /** * The classic protocol handlers for INS server side */ @Getter @Setter private ClassicHandlerINSServer classicHandlerINSServer; /** * 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; /** * The proxy for client side */ @Getter @Setter private Proxy proxy; /** * Initialize the ProtocolBridge instance for the INS server side * * @param protocolINSServer The ProtocolINSServer 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.INS) public ProtocolBridge(ProtocolINSServer protocolINSServer, ProtocolSettings protocolSettings, ProtocolVersion protocolVersion, File logFolder) throws Exception { // Assign the parameters to the class fields this.protocolINSServer = protocolINSServer; this.protocolSettings = protocolSettings; this.protocolVersion = protocolVersion; // Initialize the logger and protocol version initializeLogger(logFolder); initializeProtocolVersion(); // Register the appropriate listeners and packets registerListeners(); registerPackets(); } /** * 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(); } /** * 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(); } /** * Register the appropriate packets based on the current protocol version */ private void registerPackets() { // Classic packets Classic_DomainPacket cDomainPacket = new Classic_DomainPacket(); Classic_MessagePacket cMessagePacket = new Classic_MessagePacket(); Classic_PingPacket cPingPacket = new Classic_PingPacket(); 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(); 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(v100BINSQueryPacket)) protocolSettings.packetHandler.registerPacket(v100BINSQueryPacket); if (isPacketSupported(v100BINSResponsePacket)) protocolSettings.packetHandler.registerPacket(v100BINSResponsePacket); } /** * 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()) { Classic_ClientListener classicListener = new Classic_ClientListener(); classicListener.setProtocolBridge(this); protocolSettings.eventManager.registerListener(classicListener.getClass()); } else protocolSettings.eventManager.unregisterListener(Classic_ClientListener.class); // INS Listeners if (isRunningAsINSServer()) { INSServerListener serverListener = new INSServerListener(); serverListener.setINSServer(protocolINSServer); protocolSettings.eventManager.registerListener(serverListener.getClass()); protocolSettings.eventManager.unregisterListener(WebServerListener.class); protocolSettings.eventManager.unregisterListener(ClientListener.class); } // Web Listeners if (isRunningAsWebServer()) { WebServerListener serverListener = new WebServerListener(); serverListener.setWebServer(protocolWebServer); protocolSettings.eventManager.registerListener(serverListener.getClass()); protocolSettings.eventManager.unregisterListener(INSServerListener.class); protocolSettings.eventManager.unregisterListener(ClientListener.class); } // Client Listeners if (isRunningAsClient()) { ClientListener clientListener = new ClientListener(); clientListener.setClient(protocolClient); protocolSettings.eventManager.registerListener(clientListener.getClass()); protocolSettings.eventManager.unregisterListener(INSServerListener.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 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 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 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 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_INS) || (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_INS) || (isRunningAsWebServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL) || (isRunningAsINSServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.INS) || (isRunningAsINSServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.WEB_INS) || (isRunningAsINSServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_INS) || (isRunningAsINSServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL); } /** * Check if the current instance is running as a INS server * * @return true if the current instance is running as a INS server, false otherwise */ public boolean isRunningAsINSServer() { return protocolINSServer != 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 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 boolean isRunningAsWebServer() { return protocolWebServer != null; } }