package org.openautonomousconnection.protocol; import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientAuthMode; 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.CustomServerListener; 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.web.WebRequestPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.WebResponsePacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.stream.WebStreamChunkPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.stream.WebStreamEndPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.stream.WebStreamStartPacket; import org.openautonomousconnection.protocol.side.client.ProtocolClient; import org.openautonomousconnection.protocol.side.ins.ProtocolINSServer; import org.openautonomousconnection.protocol.side.server.ProtocolCustomServer; import org.openautonomousconnection.protocol.side.web.ProtocolWebServer; import org.openautonomousconnection.protocol.versions.ProtocolVersion; 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 ProtocolValues protocolValues; /** * 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 ProtocolClient protocolClient; /** * The protocol side instances */ @Getter private ProtocolCustomServer protocolServer; /** * The proxy for client side */ @Getter @Setter private Proxy proxy; /** * Initialize the ProtocolBridge instance for the client side * * @param protocolServer The ProtocolCustomServer instance * @param protocolValues 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 */ public ProtocolBridge(ProtocolCustomServer protocolServer, ProtocolValues protocolValues, ProtocolVersion protocolVersion, File logFolder) throws Exception { // Assign the parameters to the class fields this.protocolServer = protocolServer; this.protocolValues = protocolValues; this.protocolVersion = protocolVersion; if (protocolServer instanceof ProtocolINSServer) { protocolServer.attachBridge(this, null, false, ClientAuthMode.NONE); } else protocolServer.attachBridge(this, protocolValues.keyPass, protocolValues.ssl, protocolValues.authMode); // 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 protocolValues 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, ProtocolValues protocolValues, ProtocolVersion protocolVersion, File logFolder) throws Exception { // Assign the parameters to the class fields this.protocolClient = protocolClient; this.protocolValues = protocolValues; this.protocolVersion = protocolVersion; protocolClient.attachBridge(this); // 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() { // 1.0.0-BETA packets if (isPacketSupported(new AuthPacket(this))) protocolValues.packetHandler.registerPacket(() -> new AuthPacket(this)); if (isPacketSupported(new INSQueryPacket())) protocolValues.packetHandler.registerPacket(INSQueryPacket::new); if (isPacketSupported(new INSResponsePacket(this))) protocolValues.packetHandler.registerPacket(() -> new INSResponsePacket(this)); if (isPacketSupported(new WebRequestPacket())) protocolValues.packetHandler.registerPacket(WebRequestPacket::new); if (isPacketSupported(new WebResponsePacket())) protocolValues.packetHandler.registerPacket(WebResponsePacket::new); if (isPacketSupported(new WebStreamChunkPacket())) protocolValues.packetHandler.registerPacket(WebStreamChunkPacket::new); if (isPacketSupported(new WebStreamStartPacket())) protocolValues.packetHandler.registerPacket(WebStreamStartPacket::new); if (isPacketSupported(new WebStreamEndPacket())) protocolValues.packetHandler.registerPacket(WebStreamEndPacket::new); } /** * Register the appropriate listeners based on the current side * * @throws Exception if an error occurs while registering the listeners */ private void registerListeners() throws Exception { // Client Listeners if (isRunningAsClient()) { protocolValues.eventManager.registerListener(new ClientListener(protocolClient)); protocolValues.eventManager.unregisterListener(CustomServerListener.class); } // Server Listeners if (isRunningAsServer()) { protocolValues.eventManager.registerListener(new CustomServerListener(protocolServer)); protocolValues.eventManager.unregisterListener(ClientListener.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) || (isRunningAsServer() && 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 isRunningAsServer() && protocolServer instanceof ProtocolINSServer; } /** * 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 isRunningAsServer() && protocolServer instanceof ProtocolWebServer; } /** * Check if the current instance is running as a custom server * * @return true if the current instance is running as a custom server, false otherwise */ public boolean isRunningAsServer() { return protocolServer != null; } }