Bug fix
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>org.openautonomousconnection</groupId>
|
<groupId>org.openautonomousconnection</groupId>
|
||||||
<artifactId>Protocol</artifactId>
|
<artifactId>Protocol</artifactId>
|
||||||
<version>1.0.1-BETA.0.4</version>
|
<version>1.0.1-BETA.0.5</version>
|
||||||
<organization>
|
<organization>
|
||||||
<name>Open Autonomous Connection</name>
|
<name>Open Autonomous Connection</name>
|
||||||
<url>https://open-autonomous-connection.org/</url>
|
<url>https://open-autonomous-connection.org/</url>
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>dev.unlegitdqrk</groupId>
|
<groupId>dev.unlegitdqrk</groupId>
|
||||||
<artifactId>unlegitlibrary</artifactId>
|
<artifactId>unlegitlibrary</artifactId>
|
||||||
<version>1.8.2</version>
|
<version>1.8.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import org.openautonomousconnection.protocol.versions.v1_0_0.beta.ProtocolWebSer
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,18 +54,6 @@ public final class ProtocolBridge {
|
|||||||
@Getter
|
@Getter
|
||||||
private final ProtocolValues protocolValues;
|
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
|
* The protocol side instances
|
||||||
*/
|
*/
|
||||||
@@ -78,27 +67,17 @@ public final class ProtocolBridge {
|
|||||||
@Getter
|
@Getter
|
||||||
private ProtocolCustomServer protocolServer;
|
private ProtocolCustomServer protocolServer;
|
||||||
|
|
||||||
@Getter
|
|
||||||
private AddonLoader addonLoader;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the ProtocolBridge instance for the client side
|
* Initialize the ProtocolBridge instance for the client side
|
||||||
*
|
*
|
||||||
* @param protocolServer The ProtocolCustomServer instance
|
* @param protocolServer The ProtocolCustomServer instance
|
||||||
* @param protocolValues The ProtocolSettings instance
|
* @param protocolValues The ProtocolSettings instance
|
||||||
* @param protocolVersion The ProtocolVersion instance
|
|
||||||
* @param logger The logger
|
|
||||||
* @param addonLoader The Addon loader to load custom extensions
|
|
||||||
* @throws Exception if an error occurs while initializing the ProtocolBridge
|
* @throws Exception if an error occurs while initializing the ProtocolBridge
|
||||||
*/
|
*/
|
||||||
public ProtocolBridge(ProtocolCustomServer protocolServer, ProtocolValues protocolValues, ProtocolVersion protocolVersion,
|
public ProtocolBridge(ProtocolCustomServer protocolServer, ProtocolValues protocolValues) throws Exception {
|
||||||
Logger logger, AddonLoader addonLoader) throws Exception {
|
|
||||||
// Assign the parameters to the class fields
|
// Assign the parameters to the class fields
|
||||||
this.protocolServer = protocolServer;
|
this.protocolServer = protocolServer;
|
||||||
this.protocolValues = protocolValues;
|
this.protocolValues = protocolValues;
|
||||||
this.protocolVersion = protocolVersion;
|
|
||||||
this.logger = logger;
|
|
||||||
this.addonLoader = addonLoader;
|
|
||||||
|
|
||||||
if (protocolServer instanceof ProtocolINSServer)
|
if (protocolServer instanceof ProtocolINSServer)
|
||||||
protocolServer.attachBridge(this, null, false, ClientAuthMode.NONE);
|
protocolServer.attachBridge(this, null, false, ClientAuthMode.NONE);
|
||||||
@@ -118,20 +97,14 @@ public final class ProtocolBridge {
|
|||||||
*
|
*
|
||||||
* @param protocolClient The ProtocolClient instance
|
* @param protocolClient The ProtocolClient instance
|
||||||
* @param protocolValues The ProtocolSettings instance
|
* @param protocolValues The ProtocolSettings instance
|
||||||
* @param protocolVersion The ProtocolVersion instance
|
|
||||||
* @param logger The logger
|
|
||||||
* @param addonLoader The Addon loader to load custom extensions
|
|
||||||
* @throws Exception if an error occurs while initializing the ProtocolBridge
|
* @throws Exception if an error occurs while initializing the ProtocolBridge
|
||||||
*/
|
*/
|
||||||
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.CLIENT)
|
@ProtocolInfo(protocolSide = ProtocolVersion.ProtocolSide.CLIENT)
|
||||||
public ProtocolBridge(ProtocolClient protocolClient, ProtocolValues protocolValues, ProtocolVersion protocolVersion,
|
public ProtocolBridge(ProtocolClient protocolClient, LibClientImpl_v1_0_1_B libClientImpl,
|
||||||
Logger logger, AddonLoader addonLoader, LibClientImpl_v1_0_1_B libClientImpl) throws Exception {
|
ProtocolValues protocolValues) throws Exception {
|
||||||
// Assign the parameters to the class fields
|
// Assign the parameters to the class fields
|
||||||
this.protocolClient = protocolClient;
|
this.protocolClient = protocolClient;
|
||||||
this.protocolValues = protocolValues;
|
this.protocolValues = protocolValues;
|
||||||
this.protocolVersion = protocolVersion;
|
|
||||||
this.logger = logger;
|
|
||||||
this.addonLoader = addonLoader;
|
|
||||||
|
|
||||||
protocolClient.attachBridge(this);
|
protocolClient.attachBridge(this);
|
||||||
initializeProtocolVersion();
|
initializeProtocolVersion();
|
||||||
@@ -145,11 +118,11 @@ public final class ProtocolBridge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void installUrl(LibClientImpl_v1_0_1_B libClientImpl) {
|
private void installUrl(LibClientImpl_v1_0_1_B libClientImpl) {
|
||||||
if (protocolVersion == ProtocolVersion.PV_1_0_0_BETA) {
|
if (protocolValues.protocolVersion == ProtocolVersion.PV_1_0_0_BETA) {
|
||||||
OacWebUrlInstaller_v1_0_0_B.installOnce(this, libClientImpl);
|
OacWebUrlInstaller_v1_0_0_B.installOnce(this, libClientImpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protocolVersion == ProtocolVersion.PV_1_0_1_BETA) {
|
if (protocolValues.protocolVersion == ProtocolVersion.PV_1_0_1_BETA) {
|
||||||
OacUrlHandlerInstaller_v1_0_1_B.installOnce(this, libClientImpl, libClientImpl, libClientImpl);
|
OacUrlHandlerInstaller_v1_0_1_B.installOnce(this, libClientImpl, libClientImpl, libClientImpl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,12 +184,12 @@ public final class ProtocolBridge {
|
|||||||
registerPacket(WebStreamEndPacket_v1_0_0_B::new);
|
registerPacket(WebStreamEndPacket_v1_0_0_B::new);
|
||||||
|
|
||||||
// 1.0.1-BETA Packets
|
// 1.0.1-BETA Packets
|
||||||
registerPacket(WebDocumentApplyRequestPacket::new);
|
registerPacket(() -> new WebDocumentApplyRequestPacket(this));
|
||||||
registerPacket(WebDocumentApplyResponsePacket::new);
|
registerPacket(WebDocumentApplyResponsePacket::new);
|
||||||
registerPacket(WebDocumentSnapshotEventPacket::new);
|
registerPacket(WebDocumentSnapshotEventPacket::new);
|
||||||
registerPacket(WebNavigateRequestPacket::new);
|
registerPacket(() -> new WebNavigateRequestPacket(this));
|
||||||
registerPacket(WebNavigateAckPacket::new);
|
registerPacket(WebNavigateAckPacket::new);
|
||||||
registerPacket(WebResourceRequestPacket::new);
|
registerPacket(() -> new WebResourceRequestPacket(this));
|
||||||
registerPacket(WebResourceResponsePacket::new);
|
registerPacket(WebResourceResponsePacket::new);
|
||||||
registerPacket(WebStreamStartPacket_v1_0_1_B::new);
|
registerPacket(WebStreamStartPacket_v1_0_1_B::new);
|
||||||
registerPacket(WebStreamChunkPacket_v1_0_1_B::new);
|
registerPacket(WebStreamChunkPacket_v1_0_1_B::new);
|
||||||
@@ -255,7 +228,7 @@ public final class ProtocolBridge {
|
|||||||
// Check if the protocol version is valid for the current side
|
// Check if the protocol version is valid for the current side
|
||||||
// If not, log an error and exit the application
|
// If not, log an error and exit the application
|
||||||
if (!validateProtocolSide()) {
|
if (!validateProtocolSide()) {
|
||||||
this.logger.error("Invalid protocol version '" + protocolVersion.toString() + "'!");
|
protocolValues.logger.error("Invalid protocol version '" + protocolValues.protocolVersion.toString() + "'!");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,14 +240,14 @@ public final class ProtocolBridge {
|
|||||||
*/
|
*/
|
||||||
public boolean isClassicSupported() {
|
public boolean isClassicSupported() {
|
||||||
boolean yes = false;
|
boolean yes = false;
|
||||||
for (ProtocolVersion compatibleVersion : protocolVersion.getCompatibleVersions()) {
|
for (ProtocolVersion compatibleVersion : protocolValues.protocolVersion.getCompatibleVersions()) {
|
||||||
// Check if the compatible version is classic
|
// Check if the compatible version is classic
|
||||||
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
|
yes = compatibleVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC;
|
||||||
if (yes) break;
|
if (yes) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the current protocol version is classic or if it is supported by any of the compatible versions
|
// 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;
|
return protocolValues.protocolVersion.getProtocolType() == ProtocolVersion.ProtocolType.CLASSIC || yes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -286,14 +259,14 @@ public final class ProtocolBridge {
|
|||||||
public boolean isProtocolSupported(ProtocolVersion.Protocol protocol) {
|
public boolean isProtocolSupported(ProtocolVersion.Protocol protocol) {
|
||||||
boolean yes = false;
|
boolean yes = false;
|
||||||
|
|
||||||
for (ProtocolVersion compatibleVersion : protocolVersion.getCompatibleVersions()) {
|
for (ProtocolVersion compatibleVersion : protocolValues.protocolVersion.getCompatibleVersions()) {
|
||||||
// Check if the compatible version supports the target protocol
|
// Check if the compatible version supports the target protocol
|
||||||
yes = compatibleVersion.getSupportedProtocols().contains(protocol);
|
yes = compatibleVersion.getSupportedProtocols().contains(protocol);
|
||||||
if (yes) break;
|
if (yes) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the current protocol version supports the target protocol or if it is supported by any of the compatible versions
|
// 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;
|
return protocolValues.protocolVersion.getSupportedProtocols().contains(protocol) || yes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -320,7 +293,7 @@ public final class ProtocolBridge {
|
|||||||
*/
|
*/
|
||||||
public boolean isVersionSupported(ProtocolVersion targetVersion) {
|
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
|
// 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);
|
return protocolValues.protocolVersion == targetVersion || protocolValues.protocolVersion.getCompatibleVersions().contains(targetVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -330,22 +303,22 @@ public final class ProtocolBridge {
|
|||||||
*/
|
*/
|
||||||
private boolean validateProtocolSide() {
|
private boolean validateProtocolSide() {
|
||||||
return
|
return
|
||||||
(isRunningAsClient() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT) ||
|
(isRunningAsClient() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT) ||
|
||||||
(isRunningAsClient() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_WEB) ||
|
(isRunningAsClient() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_WEB) ||
|
||||||
(isRunningAsClient() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_INS) ||
|
(isRunningAsClient() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_INS) ||
|
||||||
(isRunningAsClient() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL) ||
|
(isRunningAsClient() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL) ||
|
||||||
|
|
||||||
(isRunningAsWebServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.WEB) ||
|
(isRunningAsWebServer() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.WEB) ||
|
||||||
(isRunningAsWebServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_WEB) ||
|
(isRunningAsWebServer() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_WEB) ||
|
||||||
(isRunningAsWebServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.WEB_INS) ||
|
(isRunningAsWebServer() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.WEB_INS) ||
|
||||||
(isRunningAsWebServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL) ||
|
(isRunningAsWebServer() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL) ||
|
||||||
|
|
||||||
(isRunningAsServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL) ||
|
(isRunningAsServer() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL) ||
|
||||||
|
|
||||||
(isRunningAsINSServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.INS) ||
|
(isRunningAsINSServer() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.INS) ||
|
||||||
(isRunningAsINSServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.WEB_INS) ||
|
(isRunningAsINSServer() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.WEB_INS) ||
|
||||||
(isRunningAsINSServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_INS) ||
|
(isRunningAsINSServer() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.CLIENT_INS) ||
|
||||||
(isRunningAsINSServer() && protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL);
|
(isRunningAsINSServer() && protocolValues.protocolVersion.getProtocolSide() == ProtocolVersion.ProtocolSide.ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -372,6 +345,8 @@ public final class ProtocolBridge {
|
|||||||
* @return true if the current instance is running as a web server, false otherwise
|
* @return true if the current instance is running as a web server, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean isRunningAsWebServer() {
|
public boolean isRunningAsWebServer() {
|
||||||
|
if (protocolValues.protocolVersion == ProtocolVersion.PV_1_0_0_BETA)
|
||||||
|
return isRunningAsServer() && protocolServer instanceof ProtocolWebServer_1_0_0_B;
|
||||||
return isRunningAsServer() && protocolServer instanceof ProtocolWebServer;
|
return isRunningAsServer() && protocolServer instanceof ProtocolWebServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
package org.openautonomousconnection.protocol;
|
package org.openautonomousconnection.protocol;
|
||||||
|
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.addon.AddonLoader;
|
||||||
import dev.unlegitdqrk.unlegitlibrary.event.EventManager;
|
import dev.unlegitdqrk.unlegitlibrary.event.EventManager;
|
||||||
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
|
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
|
||||||
import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientAuthMode;
|
import dev.unlegitdqrk.unlegitlibrary.network.system.utils.ClientAuthMode;
|
||||||
import dev.unlegitdqrk.unlegitlibrary.utils.DefaultMethodsOverrider;
|
import dev.unlegitdqrk.unlegitlibrary.utils.DefaultMethodsOverrider;
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.utils.Logger;
|
||||||
|
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings for the protocol connection.
|
* Settings for the protocol connection.
|
||||||
@@ -19,8 +22,14 @@ public final class ProtocolValues extends DefaultMethodsOverrider {
|
|||||||
*/
|
*/
|
||||||
public EventManager eventManager;
|
public EventManager eventManager;
|
||||||
|
|
||||||
|
public AddonLoader addonLoader;
|
||||||
|
|
||||||
|
public Logger logger;
|
||||||
|
|
||||||
public String keyPass = null;
|
public String keyPass = null;
|
||||||
|
|
||||||
|
public ProtocolVersion protocolVersion;
|
||||||
|
|
||||||
public boolean ssl = true;
|
public boolean ssl = true;
|
||||||
public ClientAuthMode authMode = ClientAuthMode.NONE;
|
public ClientAuthMode authMode = ClientAuthMode.NONE;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
/**
|
/**
|
||||||
* Annotation to provide metadata about protocol handlers or classes.
|
* Annotation to provide metadata about protocol handlers or classes.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(forRemoval = false, since = "1.0.1-BETA.0.5")
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface ProtocolInfo {
|
public @interface ProtocolInfo {
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public final class ClientListener extends EventListener {
|
|||||||
try {
|
try {
|
||||||
event.getClient().sendPacket(new AuthPacket(client.getProtocolBridge()), TransportProtocol.TCP);
|
event.getClient().sendPacket(new AuthPacket(client.getProtocolBridge()), TransportProtocol.TCP);
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
client.getProtocolBridge().getLogger().exception("Failed to send auth packet", exception);
|
client.getProtocolBridge().getProtocolValues().logger.exception("Failed to send auth packet", exception);
|
||||||
event.getClient().disconnect();
|
event.getClient().disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public final class CustomServerListener extends EventListener {
|
|||||||
try {
|
try {
|
||||||
server.getClients().add(new CustomConnectedClient(event.getClient(), server));
|
server.getClients().add(new CustomConnectedClient(event.getClient(), server));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
server.getProtocolBridge().getLogger().exception("Failed to add client to server", e);
|
server.getProtocolBridge().getProtocolValues().logger.exception("Failed to add client to server", e);
|
||||||
event.getClient().disconnect();
|
event.getClient().disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ public final class CustomServerListener extends EventListener {
|
|||||||
onWebRequest(server.getClientByID(event.getClient().getUniqueID()), (WebRequestPacket) event.getPacket()),
|
onWebRequest(server.getClientByID(event.getClient().getUniqueID()), (WebRequestPacket) event.getPacket()),
|
||||||
TransportProtocol.TCP);
|
TransportProtocol.TCP);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
server.getProtocolBridge().getLogger().exception("Failed to send web response", e);
|
server.getProtocolBridge().getProtocolValues().logger.exception("Failed to send web response", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public final class AuthPacket extends OACPacket {
|
|||||||
public void onWrite(DataOutputStream objectOutputStream) throws IOException {
|
public void onWrite(DataOutputStream objectOutputStream) throws IOException {
|
||||||
if (protocolBridge.isRunningAsINSServer()) {
|
if (protocolBridge.isRunningAsINSServer()) {
|
||||||
objectOutputStream.writeBoolean(true);
|
objectOutputStream.writeBoolean(true);
|
||||||
objectOutputStream.writeUTF(protocolBridge.getProtocolVersion().name());
|
objectOutputStream.writeUTF(protocolBridge.getProtocolValues().protocolVersion.name());
|
||||||
|
|
||||||
String caPem = "N/A";
|
String caPem = "N/A";
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ public final class AuthPacket extends OACPacket {
|
|||||||
protocolBridge.getProtocolServer().getFolderStructure().publicCAFolder,
|
protocolBridge.getProtocolServer().getFolderStructure().publicCAFolder,
|
||||||
caPrefix + ".pem"));
|
caPrefix + ".pem"));
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
protocolBridge.getLogger().exception("Failed to read ca-files", exception);
|
protocolBridge.getProtocolValues().logger.exception("Failed to read ca-files", exception);
|
||||||
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ public final class AuthPacket extends OACPacket {
|
|||||||
|
|
||||||
if (protocolBridge.isRunningAsServer()) {
|
if (protocolBridge.isRunningAsServer()) {
|
||||||
objectOutputStream.writeBoolean(false);
|
objectOutputStream.writeBoolean(false);
|
||||||
objectOutputStream.writeUTF(protocolBridge.getProtocolVersion().name());
|
objectOutputStream.writeUTF(protocolBridge.getProtocolValues().protocolVersion.name());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ public final class AuthPacket extends OACPacket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
objectOutputStream.writeUTF(clientConnectionId.toString());
|
objectOutputStream.writeUTF(clientConnectionId.toString());
|
||||||
objectOutputStream.writeUTF(protocolBridge.getProtocolVersion().name());
|
objectOutputStream.writeUTF(protocolBridge.getProtocolValues().protocolVersion.name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +197,7 @@ public final class AuthPacket extends OACPacket {
|
|||||||
try {
|
try {
|
||||||
FileUtils.writeFile(caPemFile, caPem);
|
FileUtils.writeFile(caPemFile, caPem);
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
protocolBridge.getLogger().exception("Failed to create/save ca-files", exception);
|
protocolBridge.getProtocolValues().logger.exception("Failed to create/save ca-files", exception);
|
||||||
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
setResponseCode(INSResponseStatus.RESPONSE_AUTH_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.document;
|
package org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.document;
|
||||||
|
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.network.system.utils.TransportProtocol;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.openautonomousconnection.protocol.ProtocolBridge;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.WebPacket;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.WebPacket;
|
||||||
|
import org.openautonomousconnection.protocol.side.server.CustomConnectedClient;
|
||||||
|
import org.openautonomousconnection.protocol.side.web.ProtocolWebServer;
|
||||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketHeader;
|
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketHeader;
|
||||||
|
|
||||||
@@ -16,16 +20,18 @@ import java.util.UUID;
|
|||||||
@Getter
|
@Getter
|
||||||
public final class WebDocumentApplyRequestPacket extends WebPacket {
|
public final class WebDocumentApplyRequestPacket extends WebPacket {
|
||||||
private String fullHtml;
|
private String fullHtml;
|
||||||
|
private final ProtocolBridge protocolBridge;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registration constructor.
|
* Registration constructor.
|
||||||
*/
|
*/
|
||||||
public WebDocumentApplyRequestPacket() {
|
public WebDocumentApplyRequestPacket(ProtocolBridge protocolBridge) {
|
||||||
super(18, ProtocolVersion.PV_1_0_1_BETA);
|
super(18, ProtocolVersion.PV_1_0_1_BETA);
|
||||||
|
this.protocolBridge = protocolBridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebDocumentApplyRequestPacket(WebPacketHeader header, String fullHtml) {
|
public WebDocumentApplyRequestPacket(WebPacketHeader header, String fullHtml, ProtocolBridge protocolBridge) {
|
||||||
this();
|
this(protocolBridge);
|
||||||
setHeader(header);
|
setHeader(header);
|
||||||
this.fullHtml = (fullHtml != null) ? fullHtml : "";
|
this.fullHtml = (fullHtml != null) ? fullHtml : "";
|
||||||
}
|
}
|
||||||
@@ -38,5 +44,11 @@ public final class WebDocumentApplyRequestPacket extends WebPacket {
|
|||||||
@Override
|
@Override
|
||||||
protected void readBody(DataInputStream in, UUID clientID) throws IOException {
|
protected void readBody(DataInputStream in, UUID clientID) throws IOException {
|
||||||
this.fullHtml = in.readUTF();
|
this.fullHtml = in.readUTF();
|
||||||
|
|
||||||
|
if (protocolBridge.isRunningAsWebServer()) {
|
||||||
|
ProtocolWebServer server = (ProtocolWebServer) protocolBridge.getProtocolServer();
|
||||||
|
CustomConnectedClient client = server.getClientByID(clientID);
|
||||||
|
client.getConnection().sendPacket(server.handleDocumentApply(client, this), TransportProtocol.TCP);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
package org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.navigate;
|
package org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.navigate;
|
||||||
|
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.network.system.utils.TransportProtocol;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.openautonomousconnection.protocol.ProtocolBridge;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.WebPacket;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.WebPacket;
|
||||||
|
import org.openautonomousconnection.protocol.side.server.CustomConnectedClient;
|
||||||
|
import org.openautonomousconnection.protocol.side.web.ProtocolWebServer;
|
||||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebCacheMode;
|
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebCacheMode;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketHeader;
|
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketHeader;
|
||||||
@@ -10,6 +14,7 @@ import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebTransitionT
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,12 +27,14 @@ public final class WebNavigateRequestPacket extends WebPacket {
|
|||||||
private WebTransitionType transitionType;
|
private WebTransitionType transitionType;
|
||||||
private long headerProfileId;
|
private long headerProfileId;
|
||||||
private WebCacheMode cacheMode;
|
private WebCacheMode cacheMode;
|
||||||
|
private final ProtocolBridge protocolBridge;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registration constructor.
|
* Registration constructor.
|
||||||
*/
|
*/
|
||||||
public WebNavigateRequestPacket() {
|
public WebNavigateRequestPacket(ProtocolBridge protocolBridge) {
|
||||||
super(1, ProtocolVersion.PV_1_0_1_BETA);
|
super(1, ProtocolVersion.PV_1_0_1_BETA);
|
||||||
|
this.protocolBridge = Objects.requireNonNull(protocolBridge, "protocolBridge");
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebNavigateRequestPacket(
|
public WebNavigateRequestPacket(
|
||||||
@@ -36,9 +43,9 @@ public final class WebNavigateRequestPacket extends WebPacket {
|
|||||||
String referrer,
|
String referrer,
|
||||||
WebTransitionType transitionType,
|
WebTransitionType transitionType,
|
||||||
long headerProfileId,
|
long headerProfileId,
|
||||||
WebCacheMode cacheMode
|
WebCacheMode cacheMode, ProtocolBridge protocolBridge
|
||||||
) {
|
) {
|
||||||
this();
|
this(protocolBridge);
|
||||||
setHeader(header);
|
setHeader(header);
|
||||||
this.url = (url != null) ? url : "";
|
this.url = (url != null) ? url : "";
|
||||||
this.referrer = referrer;
|
this.referrer = referrer;
|
||||||
@@ -68,5 +75,11 @@ public final class WebNavigateRequestPacket extends WebPacket {
|
|||||||
this.transitionType = WebTransitionType.valueOf(in.readUTF());
|
this.transitionType = WebTransitionType.valueOf(in.readUTF());
|
||||||
this.headerProfileId = in.readLong();
|
this.headerProfileId = in.readLong();
|
||||||
this.cacheMode = WebCacheMode.valueOf(in.readUTF());
|
this.cacheMode = WebCacheMode.valueOf(in.readUTF());
|
||||||
|
|
||||||
|
if (protocolBridge.isRunningAsWebServer()) {
|
||||||
|
ProtocolWebServer server = (ProtocolWebServer) protocolBridge.getProtocolServer();
|
||||||
|
CustomConnectedClient client = server.getClientByID(clientID);
|
||||||
|
client.getConnection().sendPacket(server.handleNavigate(client, this), TransportProtocol.TCP);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
package org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.resource;
|
package org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.resource;
|
||||||
|
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.network.system.utils.TransportProtocol;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.openautonomousconnection.protocol.ProtocolBridge;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.WebPacket;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.WebPacket;
|
||||||
|
import org.openautonomousconnection.protocol.side.server.CustomConnectedClient;
|
||||||
|
import org.openautonomousconnection.protocol.side.web.ProtocolWebServer;
|
||||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebCacheMode;
|
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebCacheMode;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebInitiatorType;
|
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebInitiatorType;
|
||||||
@@ -27,12 +31,14 @@ public final class WebResourceRequestPacket extends WebPacket {
|
|||||||
private String bodyContentType;
|
private String bodyContentType;
|
||||||
private WebInitiatorType initiatorType;
|
private WebInitiatorType initiatorType;
|
||||||
private WebCacheMode cacheMode;
|
private WebCacheMode cacheMode;
|
||||||
|
private final ProtocolBridge protocolBridge;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registration constructor.
|
* Registration constructor.
|
||||||
*/
|
*/
|
||||||
public WebResourceRequestPacket() {
|
public WebResourceRequestPacket(ProtocolBridge protocolBridge) {
|
||||||
super(3, ProtocolVersion.PV_1_0_1_BETA);
|
super(3, ProtocolVersion.PV_1_0_1_BETA);
|
||||||
|
this.protocolBridge = protocolBridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebResourceRequestPacket(
|
public WebResourceRequestPacket(
|
||||||
@@ -43,9 +49,9 @@ public final class WebResourceRequestPacket extends WebPacket {
|
|||||||
byte[] body,
|
byte[] body,
|
||||||
String bodyContentType,
|
String bodyContentType,
|
||||||
WebInitiatorType initiatorType,
|
WebInitiatorType initiatorType,
|
||||||
WebCacheMode cacheMode
|
WebCacheMode cacheMode, ProtocolBridge protocolBridge
|
||||||
) {
|
) {
|
||||||
this();
|
this(protocolBridge);
|
||||||
setHeader(header);
|
setHeader(header);
|
||||||
this.url = (url != null) ? url : "";
|
this.url = (url != null) ? url : "";
|
||||||
this.method = (method != null) ? method : "GET";
|
this.method = (method != null) ? method : "GET";
|
||||||
@@ -90,5 +96,11 @@ public final class WebResourceRequestPacket extends WebPacket {
|
|||||||
int len = in.readInt();
|
int len = in.readInt();
|
||||||
if (len < 0) throw new IOException("Negative body length in WebResourceRequestPacket");
|
if (len < 0) throw new IOException("Negative body length in WebResourceRequestPacket");
|
||||||
this.body = in.readNBytes(len);
|
this.body = in.readNBytes(len);
|
||||||
|
|
||||||
|
if (protocolBridge.isRunningAsWebServer()) {
|
||||||
|
ProtocolWebServer server = (ProtocolWebServer) protocolBridge.getProtocolServer();
|
||||||
|
CustomConnectedClient client = server.getClientByID(clientID);
|
||||||
|
client.getConnection().sendPacket(server.handleResource(client, this), TransportProtocol.TCP);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream
|
|||||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.WebRequestMethod;
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.WebRequestMethod;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.*;
|
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.*;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.compat.WebCompatMapper;
|
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebCompatMapper;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -140,7 +140,7 @@ public abstract class ProtocolWebClient extends ProtocolClient {
|
|||||||
referrer,
|
referrer,
|
||||||
transition,
|
transition,
|
||||||
headerProfileId,
|
headerProfileId,
|
||||||
cacheMode
|
cacheMode, getProtocolBridge()
|
||||||
);
|
);
|
||||||
|
|
||||||
getClientServerConnection().sendPacket(pkt, TransportProtocol.TCP);
|
getClientServerConnection().sendPacket(pkt, TransportProtocol.TCP);
|
||||||
@@ -195,7 +195,7 @@ public abstract class ProtocolWebClient extends ProtocolClient {
|
|||||||
body,
|
body,
|
||||||
bodyContentType,
|
bodyContentType,
|
||||||
initiator,
|
initiator,
|
||||||
cacheMode
|
cacheMode, getProtocolBridge()
|
||||||
);
|
);
|
||||||
|
|
||||||
getClientServerConnection().sendPacket(pkt, TransportProtocol.TCP);
|
getClientServerConnection().sendPacket(pkt, TransportProtocol.TCP);
|
||||||
@@ -221,7 +221,7 @@ public abstract class ProtocolWebClient extends ProtocolClient {
|
|||||||
base.getTimestampMs()
|
base.getTimestampMs()
|
||||||
);
|
);
|
||||||
|
|
||||||
WebDocumentApplyRequestPacket pkt = new WebDocumentApplyRequestPacket(header, fullHtml);
|
WebDocumentApplyRequestPacket pkt = new WebDocumentApplyRequestPacket(header, fullHtml, getProtocolBridge());
|
||||||
getClientServerConnection().sendPacket(pkt, TransportProtocol.TCP);
|
getClientServerConnection().sendPacket(pkt, TransportProtocol.TCP);
|
||||||
onWebRequestSent(pkt);
|
onWebRequestSent(pkt);
|
||||||
return pkt.getHeader().getRequestId();
|
return pkt.getHeader().getRequestId();
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public abstract class ProtocolINSServer extends ProtocolCustomServer {
|
|||||||
java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-256");
|
java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-256");
|
||||||
String fp = java.util.HexFormat.of().formatHex(md.digest(caBytes));
|
String fp = java.util.HexFormat.of().formatHex(md.digest(caBytes));
|
||||||
|
|
||||||
getProtocolBridge().getLogger().info("CA Fingerprint: " + fp);
|
getProtocolBridge().getProtocolValues().logger.info("CA Fingerprint: " + fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package org.openautonomousconnection.protocol.side.web;
|
package org.openautonomousconnection.protocol.side.web;
|
||||||
|
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.event.EventPriority;
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.event.Listener;
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.packets.C_PacketReadEvent;
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.network.system.utils.TransportProtocol;
|
||||||
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
|
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.WebRequestPacket;
|
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.WebResponsePacket;
|
||||||
@@ -17,7 +21,7 @@ import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
|||||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.ProtocolWebServer_1_0_0_B;
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.ProtocolWebServer_1_0_0_B;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketFlags;
|
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketFlags;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketHeader;
|
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketHeader;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.compat.WebCompatMapper;
|
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebCompatMapper;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@@ -59,6 +63,38 @@ public abstract class ProtocolWebServer extends ProtocolWebServer_1_0_0_B {
|
|||||||
super(authFile, rulesFile, sessionExpire, uploadSize);
|
super(authFile, rulesFile, sessionExpire, uploadSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Listener(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onPacketRead(C_PacketReadEvent event) {
|
||||||
|
Objects.requireNonNull(event, "event");
|
||||||
|
|
||||||
|
Object packet = event.getPacket();
|
||||||
|
if (packet == null) return;
|
||||||
|
|
||||||
|
CustomConnectedClient client = getClientByID(event.getClient().getUniqueID());
|
||||||
|
if (client == null) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (packet instanceof WebNavigateRequestPacket nav) {
|
||||||
|
WebNavigateAckPacket ack = handleNavigate(client, nav);
|
||||||
|
client.getConnection().sendPacket(ack, TransportProtocol.TCP);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet instanceof WebResourceRequestPacket req) {
|
||||||
|
WebResourceResponsePacket resp = handleResource(client, req);
|
||||||
|
client.getConnection().sendPacket(resp, TransportProtocol.TCP);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet instanceof WebDocumentApplyRequestPacket apply) {
|
||||||
|
WebDocumentApplyResponsePacket resp = handleDocumentApply(client, apply);
|
||||||
|
client.getConnection().sendPacket(resp, TransportProtocol.TCP);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
getProtocolBridge().getProtocolValues().logger.exception("Failed to handle packet", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server-side dispatcher entry point for a navigation request (packet id 01).
|
* Server-side dispatcher entry point for a navigation request (packet id 01).
|
||||||
*
|
*
|
||||||
@@ -184,7 +220,7 @@ public abstract class ProtocolWebServer extends ProtocolWebServer_1_0_0_B {
|
|||||||
long tabId = LEGACY_TAB_ID;
|
long tabId = LEGACY_TAB_ID;
|
||||||
long pageId = LEGACY_PAGE_ID;
|
long pageId = LEGACY_PAGE_ID;
|
||||||
|
|
||||||
WebResourceRequestPacket mapped = WebCompatMapper.toResourceRequest(requestId, tabId, pageId, request);
|
WebResourceRequestPacket mapped = WebCompatMapper.toResourceRequest(requestId, tabId, pageId, request, getProtocolBridge());
|
||||||
WebResourceResponsePacket resp = onResourceRequest(client, mapped);
|
WebResourceResponsePacket resp = onResourceRequest(client, mapped);
|
||||||
|
|
||||||
if (resp == null) {
|
if (resp == null) {
|
||||||
|
|||||||
@@ -417,21 +417,12 @@ public final class OacWebRequestBroker {
|
|||||||
|
|
||||||
connectionLatch = new CountDownLatch(1);
|
connectionLatch = new CountDownLatch(1);
|
||||||
|
|
||||||
INSQueryPacket query = new INSQueryPacket(
|
|
||||||
tln,
|
|
||||||
name,
|
|
||||||
sub,
|
|
||||||
INSRecordType.A,
|
|
||||||
client.getClientINSConnection().getUniqueID()
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client.getClientINSConnection().sendPacket(query, TransportProtocol.TCP);
|
client.sendINSQuery(tln, name, sub, INSRecordType.A);
|
||||||
|
awaitConnectionIfPending();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalStateException("Failed to send INSQueryPacket for " + infoName, e);
|
throw new IllegalStateException("Failed to send INSQueryPacket for " + infoName, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
awaitConnectionIfPending();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void awaitConnectionIfPending() {
|
private void awaitConnectionIfPending() {
|
||||||
|
|||||||
@@ -0,0 +1,293 @@
|
|||||||
|
package org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta;
|
||||||
|
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.event.EventListener;
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.event.EventPriority;
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.event.Listener;
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.packets.C_PacketReadEvent;
|
||||||
|
import org.openautonomousconnection.protocol.ProtocolBridge;
|
||||||
|
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.INSResponsePacket;
|
||||||
|
import org.openautonomousconnection.protocol.side.client.ProtocolClient;
|
||||||
|
import org.openautonomousconnection.protocol.side.client.events.ConnectedToProtocolINSServerEvent;
|
||||||
|
import org.openautonomousconnection.protocol.side.client.events.ConnectedToProtocolServerEvent;
|
||||||
|
import org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.web.OacWebRequestBroker;
|
||||||
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord;
|
||||||
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecordType;
|
||||||
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coordinates INS resolution for WEB requests and connects to the resolved server endpoint.
|
||||||
|
*
|
||||||
|
* <p>No {@code sendIns()} exists. This coordinator sends INS queries directly:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link #requestResolve(String)} is called on every WEB request.</li>
|
||||||
|
* <li>Requests for the currently connected InfoName reuse the active server connection.</li>
|
||||||
|
* <li>If INS is connected, unresolved hosts immediately trigger {@code sendINSQuery(tln,name,sub,A)}.</li>
|
||||||
|
* <li>If INS is not connected yet, it stores the pending host and sends on {@link ConnectedToProtocolINSServerEvent}.</li>
|
||||||
|
* <li>On {@link INSResponsePacket} it connects the server connection.</li>
|
||||||
|
* <li>On {@link ConnectedToProtocolServerEvent} it opens the broker gate.</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public final class InsResolutionCoordinator_v1_0_1_B extends EventListener {
|
||||||
|
|
||||||
|
private static final InsResolutionCoordinator_v1_0_1_B INSTANCE = new InsResolutionCoordinator_v1_0_1_B();
|
||||||
|
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
|
private volatile ProtocolBridge bridge;
|
||||||
|
|
||||||
|
private volatile ProtocolClient insClient; // from ConnectedToProtocolINSServerEvent
|
||||||
|
private volatile boolean insConnected;
|
||||||
|
|
||||||
|
private volatile String activeInfoName;
|
||||||
|
private volatile String pendingInfoName;
|
||||||
|
|
||||||
|
private InsResolutionCoordinator_v1_0_1_B() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return global singleton instance
|
||||||
|
*/
|
||||||
|
public static InsResolutionCoordinator_v1_0_1_B get() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches runtime dependencies.
|
||||||
|
*
|
||||||
|
* @param protocolBridge protocol bridge
|
||||||
|
*/
|
||||||
|
public synchronized void attach(ProtocolBridge protocolBridge) {
|
||||||
|
Objects.requireNonNull(protocolBridge, "protocolBridge");
|
||||||
|
|
||||||
|
if (this.bridge == null) {
|
||||||
|
this.bridge = protocolBridge;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.bridge == protocolBridge) return;
|
||||||
|
|
||||||
|
throw new IllegalStateException("InsResolutionCoordinator runtime already initialized with different instances");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the WEB broker for EVERY outgoing request.
|
||||||
|
*
|
||||||
|
* <p>If the requested InfoName is already connected, the current server connection is reused.
|
||||||
|
* Otherwise an INS query is triggered for the URL host. If INS is not connected yet, the host is stored
|
||||||
|
* and will be sent once INS connects.</p>
|
||||||
|
*
|
||||||
|
* @param infoName host from {@code web://<infoName>/...}
|
||||||
|
*/
|
||||||
|
public void requestResolve(String infoName) {
|
||||||
|
String in = (infoName == null) ? "" : infoName.trim();
|
||||||
|
if (in.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("InfoName is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canReuseCurrentServerConnection(in)) {
|
||||||
|
OacWebRequestBroker.get().notifyServerConnected();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (lock) {
|
||||||
|
pendingInfoName = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unresolved or changed hosts reset the server gate and trigger INS -> connect -> request.
|
||||||
|
OacWebRequestBroker.get().beginServerConnectAttempt();
|
||||||
|
|
||||||
|
// If INS already connected, send immediately
|
||||||
|
trySendPendingInsNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* INS is now connected -> we can send pending INS immediately.
|
||||||
|
*
|
||||||
|
* @param event ins connected event
|
||||||
|
*/
|
||||||
|
@Listener(priority = EventPriority.HIGHEST)
|
||||||
|
public void onConnectedToIns(ConnectedToProtocolINSServerEvent event) {
|
||||||
|
Objects.requireNonNull(event, "event");
|
||||||
|
|
||||||
|
this.insClient = Objects.requireNonNull(event.getClient(), "event.getClient()");
|
||||||
|
this.insConnected = true;
|
||||||
|
|
||||||
|
// Send pending (if any) now that INS is connected
|
||||||
|
trySendPendingInsNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives INS resolution response and starts the WEB server connect attempt.
|
||||||
|
*
|
||||||
|
* @param event packet read event
|
||||||
|
*/
|
||||||
|
@Listener(priority = EventPriority.HIGHEST)
|
||||||
|
public void onInsResponse(C_PacketReadEvent event) {
|
||||||
|
Objects.requireNonNull(event, "event");
|
||||||
|
if (!(event.getPacket() instanceof INSResponsePacket packet)) return;
|
||||||
|
|
||||||
|
final String infoName;
|
||||||
|
final String hostname;
|
||||||
|
final int port;
|
||||||
|
|
||||||
|
try {
|
||||||
|
synchronized (lock) {
|
||||||
|
infoName = pendingInfoName;
|
||||||
|
}
|
||||||
|
if (infoName == null || infoName.isBlank()) {
|
||||||
|
throw new IllegalStateException("INS response received without pending info name");
|
||||||
|
}
|
||||||
|
|
||||||
|
INSResponseStatus status = packet.getStatus();
|
||||||
|
List<INSRecord> records = packet.getRecords();
|
||||||
|
|
||||||
|
if (status != INSResponseStatus.OK) {
|
||||||
|
throw new IllegalStateException("INS resolution failed: " + status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (records == null || records.isEmpty() || records.getFirst() == null || records.getFirst().value == null) {
|
||||||
|
throw new IllegalStateException("INS resolution returned no usable records");
|
||||||
|
}
|
||||||
|
|
||||||
|
String host = records.getFirst().value.trim();
|
||||||
|
if (host.isEmpty()) {
|
||||||
|
throw new IllegalStateException("INS record value is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!host.contains(":")) {
|
||||||
|
hostname = host;
|
||||||
|
|
||||||
|
int recordPort = records.getFirst().port;
|
||||||
|
port = (recordPort == 0) ? 1028 : recordPort;
|
||||||
|
} else {
|
||||||
|
String[] split = host.split(":", 2);
|
||||||
|
String h = split[0].trim();
|
||||||
|
String p1 = split[1].trim();
|
||||||
|
|
||||||
|
if (h.isEmpty() || p1.isEmpty()) {
|
||||||
|
throw new IllegalStateException("Invalid INS host:port value: " + host);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
port = Integer.parseInt(p1);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new IllegalStateException("Invalid port in INS record: " + host, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
hostname = h;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
OacWebRequestBroker.get().notifyServerConnectionFailed(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread t = new Thread(() -> connectServer(infoName, hostname, port), "oac-web-server-connect");
|
||||||
|
t.setDaemon(true);
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server connected -> open broker gate.
|
||||||
|
*
|
||||||
|
* @param event server connected event
|
||||||
|
*/
|
||||||
|
@Listener(priority = EventPriority.HIGHEST)
|
||||||
|
public void onConnectedToServer(ConnectedToProtocolServerEvent event) {
|
||||||
|
Objects.requireNonNull(event, "event");
|
||||||
|
OacWebRequestBroker.get().notifyServerConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canReuseCurrentServerConnection(String infoName) {
|
||||||
|
ProtocolBridge b = this.bridge;
|
||||||
|
if (b == null) return false;
|
||||||
|
|
||||||
|
ProtocolClient client = b.getProtocolClient();
|
||||||
|
if (client == null || client.getClientServerConnection() == null || !client.getClientServerConnection().isConnected()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return infoName.equalsIgnoreCase(activeInfoName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trySendPendingInsNow() {
|
||||||
|
ProtocolClient c = this.insClient;
|
||||||
|
if (c == null) return;
|
||||||
|
|
||||||
|
final String infoName;
|
||||||
|
synchronized (lock) {
|
||||||
|
infoName = pendingInfoName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (infoName == null || infoName.isBlank()) return;
|
||||||
|
|
||||||
|
InsParts parts = InsParts.parse(infoName);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// IMPORTANT: direct INS query, no impl.sendIns()
|
||||||
|
c.sendINSQuery(parts.tln(), parts.name(), parts.sub(), INSRecordType.A);
|
||||||
|
} catch (Exception e) {
|
||||||
|
OacWebRequestBroker.get().notifyServerConnectionFailed(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void connectServer(String infoName, String hostname, int port) {
|
||||||
|
ProtocolBridge b = this.bridge;
|
||||||
|
if (b == null) return;
|
||||||
|
if (canReuseCurrentServerConnection(infoName)) {
|
||||||
|
OacWebRequestBroker.get().notifyServerConnected();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ProtocolClient client = b.getProtocolClient();
|
||||||
|
|
||||||
|
if (client.getClientServerConnection() != null && client.getClientServerConnection().isConnected()) {
|
||||||
|
client.getClientServerConnection().disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
client.buildServerConnection(
|
||||||
|
null,
|
||||||
|
client.getProtocolBridge().getProtocolValues().ssl
|
||||||
|
);
|
||||||
|
|
||||||
|
client.getClientServerConnection().connect(hostname, port);
|
||||||
|
this.activeInfoName = infoName;
|
||||||
|
// Broker gate is opened by ConnectedToProtocolServerEvent.
|
||||||
|
} catch (Exception e) {
|
||||||
|
OacWebRequestBroker.get().notifyServerConnectionFailed(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses name.tln or sub.name.tln.
|
||||||
|
*/
|
||||||
|
public record InsParts(String tln, String name, String sub) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses an InfoName into INS parts.
|
||||||
|
*
|
||||||
|
* @param infoName infoName (name.tln or sub.name.tln)
|
||||||
|
* @return parts
|
||||||
|
*/
|
||||||
|
public static InsParts parse(String infoName) {
|
||||||
|
String in = Objects.requireNonNull(infoName, "infoName").trim();
|
||||||
|
if (in.isEmpty()) throw new IllegalArgumentException("infoName is empty");
|
||||||
|
|
||||||
|
String[] parts = in.split("\\.");
|
||||||
|
if (parts.length < 2 || parts.length > 3) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Invalid INS address format: " + infoName + " (expected name.tln or sub.name.tln)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String tln = parts[parts.length - 1];
|
||||||
|
String name = parts[parts.length - 2];
|
||||||
|
String sub = (parts.length == 3) ? parts[0] : null;
|
||||||
|
|
||||||
|
return new InsParts(tln, name, sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta;
|
|||||||
|
|
||||||
import org.openautonomousconnection.protocol.ProtocolBridge;
|
import org.openautonomousconnection.protocol.ProtocolBridge;
|
||||||
import org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.web.OacWebProtocolModule_v1_0_1_B;
|
import org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.web.OacWebProtocolModule_v1_0_1_B;
|
||||||
|
import org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.web.OacWebRequestBroker;
|
||||||
import org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.web.WebFlagInspector;
|
import org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.web.WebFlagInspector;
|
||||||
import org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.web.WebRequestContextProvider;
|
import org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.web.WebRequestContextProvider;
|
||||||
|
|
||||||
@@ -11,6 +12,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
/**
|
/**
|
||||||
* Installs OAC URL protocol modules for v1.0.1-BETA.
|
* Installs OAC URL protocol modules for v1.0.1-BETA.
|
||||||
*
|
*
|
||||||
|
* <p>Runtime behavior required by this installer:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>Every WEB request triggers an INS resolve attempt (via {@link InsResolutionCoordinator_v1_0_1_B}).</li>
|
||||||
|
* <li>Once an INS response arrives, the client connects to the resolved server endpoint.</li>
|
||||||
|
* <li>Only after the server connection is established, WEB packets may be sent (broker gate).</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
* <p>Call once during startup (before creating {@link java.net.URL} instances).</p>
|
* <p>Call once during startup (before creating {@link java.net.URL} instances).</p>
|
||||||
*/
|
*/
|
||||||
public final class OacUrlHandlerInstaller_v1_0_1_B {
|
public final class OacUrlHandlerInstaller_v1_0_1_B {
|
||||||
@@ -24,9 +32,9 @@ public final class OacUrlHandlerInstaller_v1_0_1_B {
|
|||||||
* Installs the URL handler package path and registers the WEB module.
|
* Installs the URL handler package path and registers the WEB module.
|
||||||
*
|
*
|
||||||
* @param protocolBridge protocol bridge
|
* @param protocolBridge protocol bridge
|
||||||
* @param impl callback implementation
|
* @param impl callback implementation
|
||||||
* @param ctxProvider provides tab/page/frame correlation for each request
|
* @param ctxProvider provides tab/page/frame correlation for each request
|
||||||
* @param flagInspector interprets {@code WebPacketHeader.flags} (e.g. stream bit)
|
* @param flagInspector interprets {@code WebPacketHeader.flags} (e.g. stream bit)
|
||||||
*/
|
*/
|
||||||
public static void installOnce(
|
public static void installOnce(
|
||||||
ProtocolBridge protocolBridge,
|
ProtocolBridge protocolBridge,
|
||||||
@@ -43,8 +51,18 @@ public final class OacUrlHandlerInstaller_v1_0_1_B {
|
|||||||
|
|
||||||
ProtocolHandlerPackages.installPackage("org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta");
|
ProtocolHandlerPackages.installPackage("org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta");
|
||||||
|
|
||||||
OacWebProtocolModule_v1_0_1_B web = new OacWebProtocolModule_v1_0_1_B(ctxProvider, flagInspector);
|
// WEB module (URLConnection + web packet listener -> broker)
|
||||||
|
OacWebProtocolModule_v1_0_1_B web = new OacWebProtocolModule_v1_0_1_B(ctxProvider, flagInspector, protocolBridge);
|
||||||
OacUrlProtocolRegistry.register(web);
|
OacUrlProtocolRegistry.register(web);
|
||||||
web.install(protocolBridge, impl);
|
web.install(protocolBridge, impl);
|
||||||
|
|
||||||
|
// INS coordination (request -> send INS -> connect server -> open broker gate)
|
||||||
|
InsResolutionCoordinator_v1_0_1_B coordinator = InsResolutionCoordinator_v1_0_1_B.get();
|
||||||
|
coordinator.attach(protocolBridge);
|
||||||
|
|
||||||
|
protocolBridge.getProtocolValues().eventManager.registerListener(coordinator);
|
||||||
|
|
||||||
|
// Broker needs to wait for "server connected" gate. Coordinator will open/fail this gate.
|
||||||
|
OacWebRequestBroker.get().attachCoordinator(coordinator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.web;
|
package org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.web;
|
||||||
|
|
||||||
|
import org.openautonomousconnection.protocol.ProtocolBridge;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.ProtocolException;
|
import java.net.ProtocolException;
|
||||||
@@ -18,6 +20,7 @@ public final class OacWebHttpURLConnection extends HttpURLConnection {
|
|||||||
private final OacWebRequestBroker broker;
|
private final OacWebRequestBroker broker;
|
||||||
private final OacSessionJar sessionJar;
|
private final OacSessionJar sessionJar;
|
||||||
private final WebRequestContextProvider ctxProvider;
|
private final WebRequestContextProvider ctxProvider;
|
||||||
|
private final ProtocolBridge bridge;
|
||||||
|
|
||||||
private final Map<String, String> requestHeaders = new LinkedHashMap<>();
|
private final Map<String, String> requestHeaders = new LinkedHashMap<>();
|
||||||
private final ByteArrayOutputStream requestBody = new ByteArrayOutputStream(1024);
|
private final ByteArrayOutputStream requestBody = new ByteArrayOutputStream(1024);
|
||||||
@@ -25,11 +28,12 @@ public final class OacWebHttpURLConnection extends HttpURLConnection {
|
|||||||
private boolean requestSent;
|
private boolean requestSent;
|
||||||
private OacWebResponse response;
|
private OacWebResponse response;
|
||||||
|
|
||||||
public OacWebHttpURLConnection(URL url, OacWebRequestBroker broker, OacSessionJar sessionJar, WebRequestContextProvider ctxProvider) {
|
public OacWebHttpURLConnection(URL url, OacWebRequestBroker broker, OacSessionJar sessionJar, WebRequestContextProvider ctxProvider, ProtocolBridge protocolBridge) {
|
||||||
super(url);
|
super(url);
|
||||||
this.broker = Objects.requireNonNull(broker, "broker");
|
this.broker = Objects.requireNonNull(broker, "broker");
|
||||||
this.sessionJar = Objects.requireNonNull(sessionJar, "sessionJar");
|
this.sessionJar = Objects.requireNonNull(sessionJar, "sessionJar");
|
||||||
this.ctxProvider = Objects.requireNonNull(ctxProvider, "ctxProvider");
|
this.ctxProvider = Objects.requireNonNull(ctxProvider, "ctxProvider");
|
||||||
|
this.bridge = Objects.requireNonNull(protocolBridge, "bridge");
|
||||||
this.method = "GET";
|
this.method = "GET";
|
||||||
setInstanceFollowRedirects(true);
|
setInstanceFollowRedirects(true);
|
||||||
}
|
}
|
||||||
@@ -131,7 +135,7 @@ public final class OacWebHttpURLConnection extends HttpURLConnection {
|
|||||||
carryBody,
|
carryBody,
|
||||||
ctx.tabId(),
|
ctx.tabId(),
|
||||||
ctx.pageId(),
|
ctx.pageId(),
|
||||||
ctx.frameId()
|
ctx.frameId(), bridge
|
||||||
);
|
);
|
||||||
|
|
||||||
String newSession = broker.extractSession(resp.headers());
|
String newSession = broker.extractSession(resp.headers());
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import dev.unlegitdqrk.unlegitlibrary.event.EventListener;
|
|||||||
import dev.unlegitdqrk.unlegitlibrary.event.EventPriority;
|
import dev.unlegitdqrk.unlegitlibrary.event.EventPriority;
|
||||||
import dev.unlegitdqrk.unlegitlibrary.event.Listener;
|
import dev.unlegitdqrk.unlegitlibrary.event.Listener;
|
||||||
import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.packets.C_PacketReadEvent;
|
import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.packets.C_PacketReadEvent;
|
||||||
|
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.Packet;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.resource.WebResourceResponsePacket;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.resource.WebResourceResponsePacket;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamChunkPacket_v1_0_1_B;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamChunkPacket_v1_0_1_B;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamEndPacket_v1_0_1_B;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamEndPacket_v1_0_1_B;
|
||||||
@@ -34,8 +35,7 @@ public final class OacWebPacketListener extends EventListener {
|
|||||||
|
|
||||||
@Listener(priority = EventPriority.HIGHEST)
|
@Listener(priority = EventPriority.HIGHEST)
|
||||||
public void onPacketRead(C_PacketReadEvent event) {
|
public void onPacketRead(C_PacketReadEvent event) {
|
||||||
Object p = event.getPacket();
|
Packet p = event.getPacket();
|
||||||
|
|
||||||
if (p instanceof WebResourceResponsePacket resp) {
|
if (p instanceof WebResourceResponsePacket resp) {
|
||||||
broker.onResourceResponse(resp);
|
broker.onResourceResponse(resp);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -17,10 +17,12 @@ public final class OacWebProtocolModule_v1_0_1_B implements OacUrlProtocolModule
|
|||||||
private final OacSessionJar sessionJar = new OacSessionJar();
|
private final OacSessionJar sessionJar = new OacSessionJar();
|
||||||
private final WebRequestContextProvider ctxProvider;
|
private final WebRequestContextProvider ctxProvider;
|
||||||
private final WebFlagInspector flagInspector;
|
private final WebFlagInspector flagInspector;
|
||||||
|
private final ProtocolBridge bridge;
|
||||||
|
|
||||||
public OacWebProtocolModule_v1_0_1_B(WebRequestContextProvider ctxProvider, WebFlagInspector flagInspector) {
|
public OacWebProtocolModule_v1_0_1_B(WebRequestContextProvider ctxProvider, WebFlagInspector flagInspector, ProtocolBridge protocolBridge) {
|
||||||
this.ctxProvider = Objects.requireNonNull(ctxProvider, "ctxProvider");
|
this.ctxProvider = Objects.requireNonNull(ctxProvider, "ctxProvider");
|
||||||
this.flagInspector = Objects.requireNonNull(flagInspector, "flagInspector");
|
this.flagInspector = Objects.requireNonNull(flagInspector, "flagInspector");
|
||||||
|
this.bridge = Objects.requireNonNull(protocolBridge, "protocolBridge");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -34,7 +36,7 @@ public final class OacWebProtocolModule_v1_0_1_B implements OacUrlProtocolModule
|
|||||||
if (!"web".equalsIgnoreCase(url.getProtocol())) {
|
if (!"web".equalsIgnoreCase(url.getProtocol())) {
|
||||||
throw new IOException("Unsupported scheme for this module: " + url.getProtocol());
|
throw new IOException("Unsupported scheme for this module: " + url.getProtocol());
|
||||||
}
|
}
|
||||||
return new OacWebHttpURLConnection(url, OacWebRequestBroker.get(), sessionJar, ctxProvider);
|
return new OacWebHttpURLConnection(url, OacWebRequestBroker.get(), sessionJar, ctxProvider, bridge);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.web;
|
package org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.web;
|
||||||
|
|
||||||
import dev.unlegitdqrk.unlegitlibrary.network.system.utils.TransportProtocol;
|
import dev.unlegitdqrk.unlegitlibrary.network.system.utils.TransportProtocol;
|
||||||
|
import org.openautonomousconnection.protocol.ProtocolBridge;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.resource.WebResourceRequestPacket;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.resource.WebResourceRequestPacket;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.resource.WebResourceResponsePacket;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.resource.WebResourceResponsePacket;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamChunkPacket_v1_0_1_B;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamChunkPacket_v1_0_1_B;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamEndPacket_v1_0_1_B;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamEndPacket_v1_0_1_B;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamStartPacket_v1_0_1_B;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamStartPacket_v1_0_1_B;
|
||||||
import org.openautonomousconnection.protocol.side.client.ProtocolClient;
|
import org.openautonomousconnection.protocol.side.client.ProtocolClient;
|
||||||
|
import org.openautonomousconnection.protocol.urlhandler.v1_0_1.beta.InsResolutionCoordinator_v1_0_1_B;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketFlags;
|
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketFlags;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketHeader;
|
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketHeader;
|
||||||
|
|
||||||
@@ -14,31 +16,34 @@ import java.io.*;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multi-flight broker for WEB v1.0.1-BETA with best-effort streaming and temp-file assembly.
|
* Multi-flight broker for WEB v1.0.1-BETA with best-effort streaming and temp-file assembly.
|
||||||
*
|
*
|
||||||
* <p>Range support: request headers are passed through unchanged (e.g. "Range").</p>
|
* <p><b>Gate behavior:</b> Before any WEB packet is sent, the broker triggers INS resolve (every request),
|
||||||
*
|
* then blocks until server connection is established (opened by {@link #notifyServerConnected()}).</p>
|
||||||
* <p>Streaming is best-effort: missing sequence numbers are ignored.</p>
|
|
||||||
* <p>Chunks are spooled to temp chunk files and merged into a final temp file on stream end.</p>
|
|
||||||
*/
|
*/
|
||||||
public final class OacWebRequestBroker {
|
public final class OacWebRequestBroker {
|
||||||
|
|
||||||
private static final OacWebRequestBroker INSTANCE = new OacWebRequestBroker();
|
private static final OacWebRequestBroker INSTANCE = new OacWebRequestBroker();
|
||||||
|
|
||||||
private static final long RESPONSE_TIMEOUT_SECONDS = 30;
|
private static final long RESPONSE_TIMEOUT_SECONDS = 30;
|
||||||
|
private static final long CONNECT_TIMEOUT_SECONDS = 30;
|
||||||
|
|
||||||
private final ConcurrentHashMap<Long, ResponseState> inFlight = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<Long, ResponseState> inFlight = new ConcurrentHashMap<>();
|
||||||
private final AtomicLong requestCounter = new AtomicLong(1);
|
private final AtomicLong requestCounter = new AtomicLong(1);
|
||||||
|
|
||||||
|
private final Object connectLock = new Object();
|
||||||
|
private volatile CompletableFuture<Void> serverReady = new CompletableFuture<>();
|
||||||
|
private volatile Throwable serverFailure;
|
||||||
|
|
||||||
private volatile ProtocolClient client;
|
private volatile ProtocolClient client;
|
||||||
private volatile WebFlagInspector flagInspector;
|
private volatile WebFlagInspector flagInspector;
|
||||||
|
|
||||||
|
private volatile InsResolutionCoordinator_v1_0_1_B coordinator;
|
||||||
|
|
||||||
private OacWebRequestBroker() {
|
private OacWebRequestBroker() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,8 +57,6 @@ public final class OacWebRequestBroker {
|
|||||||
/**
|
/**
|
||||||
* Attaches runtime dependencies required for dispatching requests and interpreting flags.
|
* Attaches runtime dependencies required for dispatching requests and interpreting flags.
|
||||||
*
|
*
|
||||||
* <p>Safe to call multiple times with the same instances. Different instances are rejected.</p>
|
|
||||||
*
|
|
||||||
* @param client protocol client used to send packets
|
* @param client protocol client used to send packets
|
||||||
* @param flagInspector inspector for header flags (STREAM bit)
|
* @param flagInspector inspector for header flags (STREAM bit)
|
||||||
*/
|
*/
|
||||||
@@ -67,24 +70,100 @@ public final class OacWebRequestBroker {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.client == client && this.flagInspector == flagInspector) {
|
if (this.client == client && this.flagInspector == flagInspector) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalStateException("OacWebRequestBroker runtime already initialized with different instances");
|
throw new IllegalStateException("OacWebRequestBroker runtime already initialized with different instances");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches the INS coordinator used for per-request INS resolution.
|
||||||
|
*
|
||||||
|
* @param coordinator coordinator
|
||||||
|
*/
|
||||||
|
public synchronized void attachCoordinator(InsResolutionCoordinator_v1_0_1_B coordinator) {
|
||||||
|
Objects.requireNonNull(coordinator, "coordinator");
|
||||||
|
if (this.coordinator == null) {
|
||||||
|
this.coordinator = coordinator;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.coordinator == coordinator) return;
|
||||||
|
throw new IllegalStateException("Coordinator already attached with different instance");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the server connection gate to "not ready".
|
||||||
|
*/
|
||||||
|
public void beginServerConnectAttempt() {
|
||||||
|
synchronized (connectLock) {
|
||||||
|
this.serverFailure = null;
|
||||||
|
this.serverReady = new CompletableFuture<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the server connection gate.
|
||||||
|
*/
|
||||||
|
public void notifyServerConnected() {
|
||||||
|
synchronized (connectLock) {
|
||||||
|
this.serverFailure = null;
|
||||||
|
CompletableFuture<Void> f = this.serverReady;
|
||||||
|
if (!f.isDone()) f.complete(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fails the server connection gate and unblocks waiters.
|
||||||
|
*
|
||||||
|
* @param t failure cause
|
||||||
|
*/
|
||||||
|
public void notifyServerConnectionFailed(Throwable t) {
|
||||||
|
Objects.requireNonNull(t, "t");
|
||||||
|
synchronized (connectLock) {
|
||||||
|
this.serverFailure = t;
|
||||||
|
CompletableFuture<Void> f = this.serverReady;
|
||||||
|
if (!f.isDone()) f.completeExceptionally(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void awaitServerConnection() throws IOException {
|
||||||
|
ProtocolClient c = this.client;
|
||||||
|
if (c == null) {
|
||||||
|
throw new IllegalStateException("ProtocolClient not attached. Call OacWebRequestBroker.attachRuntime(...) during install.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.getClientServerConnection() != null && c.getClientServerConnection().isConnected()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompletableFuture<Void> f = this.serverReady;
|
||||||
|
try {
|
||||||
|
f.get(CONNECT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
throw new IOException("Timeout waiting for server connection after " + CONNECT_TIMEOUT_SECONDS + "s", e);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
Throwable cause = (e.getCause() == null) ? e : e.getCause();
|
||||||
|
throw new IOException("Server connection failed: " + cause.getMessage(), cause);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new IOException("Interrupted while waiting for server connection", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.getClientServerConnection() == null || !c.getClientServerConnection().isConnected()) {
|
||||||
|
Throwable fail = this.serverFailure;
|
||||||
|
if (fail != null) throw new IOException("Server connection failed: " + fail.getMessage(), fail);
|
||||||
|
throw new IOException("Server gate opened but connection is not connected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a resource request and blocks until completion.
|
* Sends a resource request and blocks until completion.
|
||||||
*
|
*
|
||||||
* @param url requested URL
|
* <p><b>Required flow:</b></p>
|
||||||
* @param method HTTP-like method (GET/POST/...)
|
* <ol>
|
||||||
* @param headers request headers (passed through unchanged; includes Range)
|
* <li>Trigger INS query for URL host (EVERY request).</li>
|
||||||
* @param body request body (nullable)
|
* <li>Wait for INS response -> connect -> server connected gate.</li>
|
||||||
* @param tabId tab id
|
* <li>Send WEB request packet.</li>
|
||||||
* @param pageId page id
|
* </ol>
|
||||||
* @param frameId frame id
|
|
||||||
* @return resolved response
|
|
||||||
*/
|
*/
|
||||||
public OacWebResponse fetch(
|
public OacWebResponse fetch(
|
||||||
URL url,
|
URL url,
|
||||||
@@ -93,10 +172,26 @@ public final class OacWebRequestBroker {
|
|||||||
byte[] body,
|
byte[] body,
|
||||||
long tabId,
|
long tabId,
|
||||||
long pageId,
|
long pageId,
|
||||||
long frameId
|
long frameId, ProtocolBridge bridge
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
Objects.requireNonNull(url, "url");
|
Objects.requireNonNull(url, "url");
|
||||||
|
|
||||||
|
String host = url.getHost();
|
||||||
|
if (host == null || host.isBlank()) {
|
||||||
|
throw new IOException("Missing InfoName in URL host: " + url);
|
||||||
|
}
|
||||||
|
|
||||||
|
InsResolutionCoordinator_v1_0_1_B coord = this.coordinator;
|
||||||
|
if (coord == null) {
|
||||||
|
throw new IllegalStateException("INS coordinator not attached. Ensure installer was called.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requirement: trigger INS on EVERY request.
|
||||||
|
coord.requestResolve(host);
|
||||||
|
|
||||||
|
// Block until server is connected
|
||||||
|
awaitServerConnection();
|
||||||
|
|
||||||
ProtocolClient c = this.client;
|
ProtocolClient c = this.client;
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
throw new IllegalStateException("ProtocolClient not attached. Call OacWebRequestBroker.attachRuntime(...) during install.");
|
throw new IllegalStateException("ProtocolClient not attached. Call OacWebRequestBroker.attachRuntime(...) during install.");
|
||||||
@@ -105,7 +200,6 @@ public final class OacWebRequestBroker {
|
|||||||
String m = (method == null || method.isBlank()) ? "GET" : method.trim().toUpperCase(Locale.ROOT);
|
String m = (method == null || method.isBlank()) ? "GET" : method.trim().toUpperCase(Locale.ROOT);
|
||||||
|
|
||||||
long requestId = requestCounter.getAndIncrement();
|
long requestId = requestCounter.getAndIncrement();
|
||||||
|
|
||||||
int flags = WebPacketFlags.RESOURCE;
|
int flags = WebPacketFlags.RESOURCE;
|
||||||
|
|
||||||
WebPacketHeader header = new WebPacketHeader(
|
WebPacketHeader header = new WebPacketHeader(
|
||||||
@@ -131,7 +225,7 @@ public final class OacWebRequestBroker {
|
|||||||
safeBody,
|
safeBody,
|
||||||
safeHeaders.get("content-type"),
|
safeHeaders.get("content-type"),
|
||||||
null,
|
null,
|
||||||
null
|
null, bridge
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -149,23 +243,10 @@ public final class OacWebRequestBroker {
|
|||||||
return awaitAndBuildResponse(st);
|
return awaitAndBuildResponse(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the session token from response headers (case-insensitive).
|
|
||||||
*
|
|
||||||
* @param headers headers
|
|
||||||
* @return session token or null
|
|
||||||
*/
|
|
||||||
public String extractSession(Map<String, String> headers) {
|
public String extractSession(Map<String, String> headers) {
|
||||||
return headerValue(headers, "session");
|
return headerValue(headers, "session");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a WebResourceResponsePacket.
|
|
||||||
*
|
|
||||||
* <p>If STREAM flag is set in header, body is expected to be streamed via start/chunk/end packets.</p>
|
|
||||||
*
|
|
||||||
* @param p packet
|
|
||||||
*/
|
|
||||||
public void onResourceResponse(WebResourceResponsePacket p) {
|
public void onResourceResponse(WebResourceResponsePacket p) {
|
||||||
if (p == null || p.getHeader() == null) return;
|
if (p == null || p.getHeader() == null) return;
|
||||||
|
|
||||||
@@ -195,16 +276,9 @@ public final class OacWebRequestBroker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
st.streamExpected = true;
|
st.streamExpected = true;
|
||||||
|
|
||||||
// Some servers may already include metadata here; do not complete until stream end.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles stream start.
|
|
||||||
*
|
|
||||||
* @param p start packet
|
|
||||||
*/
|
|
||||||
public void onStreamStart(WebStreamStartPacket_v1_0_1_B p) {
|
public void onStreamStart(WebStreamStartPacket_v1_0_1_B p) {
|
||||||
if (p == null || p.getHeader() == null) return;
|
if (p == null || p.getHeader() == null) return;
|
||||||
|
|
||||||
@@ -232,11 +306,6 @@ public final class OacWebRequestBroker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles stream chunk (best-effort; stores chunk by seq).
|
|
||||||
*
|
|
||||||
* @param p chunk packet
|
|
||||||
*/
|
|
||||||
public void onStreamChunk(WebStreamChunkPacket_v1_0_1_B p) {
|
public void onStreamChunk(WebStreamChunkPacket_v1_0_1_B p) {
|
||||||
if (p == null || p.getHeader() == null) return;
|
if (p == null || p.getHeader() == null) return;
|
||||||
|
|
||||||
@@ -273,14 +342,6 @@ public final class OacWebRequestBroker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles stream end and assembles best-effort output.
|
|
||||||
*
|
|
||||||
* <p>On success, assembles final temp file and returns full content bytes (optional; may be large).</p>
|
|
||||||
*
|
|
||||||
* @param p end packet
|
|
||||||
* @return full content bytes (best-effort) or null on failure
|
|
||||||
*/
|
|
||||||
public byte[] onStreamEndAndAssemble(WebStreamEndPacket_v1_0_1_B p) {
|
public byte[] onStreamEndAndAssemble(WebStreamEndPacket_v1_0_1_B p) {
|
||||||
if (p == null || p.getHeader() == null) return null;
|
if (p == null || p.getHeader() == null) return null;
|
||||||
|
|
||||||
@@ -300,7 +361,6 @@ public final class OacWebRequestBroker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (st.spooler == null) {
|
if (st.spooler == null) {
|
||||||
// No chunks received; treat as empty success.
|
|
||||||
st.finalFile = null;
|
st.finalFile = null;
|
||||||
st.completed = true;
|
st.completed = true;
|
||||||
st.done.countDown();
|
st.done.countDown();
|
||||||
@@ -324,14 +384,11 @@ public final class OacWebRequestBroker {
|
|||||||
st.completed = true;
|
st.completed = true;
|
||||||
st.done.countDown();
|
st.done.countDown();
|
||||||
|
|
||||||
// Optional: deliver full bytes to callback (requested).
|
|
||||||
// WARNING: This can be large. You explicitly requested it, so we do it.
|
|
||||||
if (st.finalFile == null) return new byte[0];
|
if (st.finalFile == null) return new byte[0];
|
||||||
|
|
||||||
try (InputStream in = Files.newInputStream(st.finalFile)) {
|
try (InputStream in = Files.newInputStream(st.finalFile)) {
|
||||||
return in.readAllBytes();
|
return in.readAllBytes();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// Assembly is still fine; just no full byte[].
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -349,7 +406,6 @@ public final class OacWebRequestBroker {
|
|||||||
throw new IOException("Interrupted while waiting for web response (requestId=" + st.requestId + ")", e);
|
throw new IOException("Interrupted while waiting for web response (requestId=" + st.requestId + ")", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from map; response is completed now.
|
|
||||||
inFlight.remove(st.requestId);
|
inFlight.remove(st.requestId);
|
||||||
|
|
||||||
synchronized (st.lock) {
|
synchronized (st.lock) {
|
||||||
@@ -359,7 +415,6 @@ public final class OacWebRequestBroker {
|
|||||||
throw new IOException(msg);
|
throw new IOException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-stream response
|
|
||||||
if (!st.streamExpected && st.finalFile == null) {
|
if (!st.streamExpected && st.finalFile == null) {
|
||||||
byte[] b = (st.memoryBody == null) ? new byte[0] : st.memoryBody;
|
byte[] b = (st.memoryBody == null) ? new byte[0] : st.memoryBody;
|
||||||
return new OacWebResponse(
|
return new OacWebResponse(
|
||||||
@@ -371,9 +426,7 @@ public final class OacWebRequestBroker {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stream response -> return InputStream backed by final temp file (delete-on-close)
|
|
||||||
if (st.finalFile == null) {
|
if (st.finalFile == null) {
|
||||||
// Valid empty stream
|
|
||||||
return new OacWebResponse(
|
return new OacWebResponse(
|
||||||
st.statusCode,
|
st.statusCode,
|
||||||
safeContentType(st.contentType),
|
safeContentType(st.contentType),
|
||||||
@@ -384,7 +437,6 @@ public final class OacWebRequestBroker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InputStream fileIn = Files.newInputStream(st.finalFile, StandardOpenOption.READ);
|
InputStream fileIn = Files.newInputStream(st.finalFile, StandardOpenOption.READ);
|
||||||
// Delete final file + spool directory when WebView/URLConnection closes the stream.
|
|
||||||
return new OacWebResponse(
|
return new OacWebResponse(
|
||||||
st.statusCode,
|
st.statusCode,
|
||||||
safeContentType(st.contentType),
|
safeContentType(st.contentType),
|
||||||
@@ -419,10 +471,7 @@ public final class OacWebRequestBroker {
|
|||||||
}
|
}
|
||||||
if (st.spoolDir != null) {
|
if (st.spoolDir != null) {
|
||||||
try {
|
try {
|
||||||
// Let DeleteOnCloseInputStream handle recursive deletion in success path,
|
|
||||||
// but ensure cleanup on failure/timeout.
|
|
||||||
if (Files.exists(st.spoolDir)) {
|
if (Files.exists(st.spoolDir)) {
|
||||||
// best-effort delete
|
|
||||||
try (DirectoryStream<Path> ds = Files.newDirectoryStream(st.spoolDir)) {
|
try (DirectoryStream<Path> ds = Files.newDirectoryStream(st.spoolDir)) {
|
||||||
for (Path p : ds) {
|
for (Path p : ds) {
|
||||||
try {
|
try {
|
||||||
@@ -477,9 +526,6 @@ public final class OacWebRequestBroker {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Per-request state (multi-flight, correlated by requestId).
|
|
||||||
*/
|
|
||||||
private static final class ResponseState {
|
private static final class ResponseState {
|
||||||
private final long requestId;
|
private final long requestId;
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
@@ -509,9 +555,6 @@ public final class OacWebRequestBroker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Spools stream chunks to temp files and assembles best-effort output on end.
|
|
||||||
*/
|
|
||||||
private static final class TempChunkSpooler implements Closeable {
|
private static final class TempChunkSpooler implements Closeable {
|
||||||
|
|
||||||
private final Path dir;
|
private final Path dir;
|
||||||
@@ -526,7 +569,6 @@ public final class OacWebRequestBroker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void writeChunk(int seq, byte[] data) throws IOException {
|
void writeChunk(int seq, byte[] data) throws IOException {
|
||||||
// One file per seq -> no offset assumptions needed.
|
|
||||||
Path p = dir.resolve(seq + ".chunk");
|
Path p = dir.resolve(seq + ".chunk");
|
||||||
Files.write(p, data, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
|
Files.write(p, data, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
|
||||||
}
|
}
|
||||||
@@ -537,9 +579,7 @@ public final class OacWebRequestBroker {
|
|||||||
try (OutputStream os = Files.newOutputStream(out, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)) {
|
try (OutputStream os = Files.newOutputStream(out, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)) {
|
||||||
for (int seq = 0; seq <= maxSeqSeen; seq++) {
|
for (int seq = 0; seq <= maxSeqSeen; seq++) {
|
||||||
Path p = dir.resolve(seq + ".chunk");
|
Path p = dir.resolve(seq + ".chunk");
|
||||||
if (!Files.exists(p)) {
|
if (!Files.exists(p)) continue;
|
||||||
continue; // best-effort: skip gaps
|
|
||||||
}
|
|
||||||
try (InputStream in = Files.newInputStream(p, StandardOpenOption.READ)) {
|
try (InputStream in = Files.newInputStream(p, StandardOpenOption.READ)) {
|
||||||
in.transferTo(os);
|
in.transferTo(os);
|
||||||
}
|
}
|
||||||
@@ -556,7 +596,6 @@ public final class OacWebRequestBroker {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
// Cleanup remaining chunk files (best-effort).
|
|
||||||
if (!Files.exists(dir)) return;
|
if (!Files.exists(dir)) return;
|
||||||
|
|
||||||
try (DirectoryStream<Path> ds = Files.newDirectoryStream(dir)) {
|
try (DirectoryStream<Path> ds = Files.newDirectoryStream(dir)) {
|
||||||
|
|||||||
@@ -63,14 +63,14 @@ public final class INSRecordTools {
|
|||||||
private static List<INSRecord> followCNAME(ProtocolINSServer server, String tln, String name, String sub, INSRecordType targetType, int depth, Set<String> visited) {
|
private static List<INSRecord> followCNAME(ProtocolINSServer server, String tln, String name, String sub, INSRecordType targetType, int depth, Set<String> visited) {
|
||||||
|
|
||||||
if (depth > MAX_CNAME_DEPTH) {
|
if (depth > MAX_CNAME_DEPTH) {
|
||||||
server.getProtocolBridge().getLogger().warn("Max CNAME depth exceeded for " + fqdn(tln, name, sub));
|
server.getProtocolBridge().getProtocolValues().logger.warn("Max CNAME depth exceeded for " + fqdn(tln, name, sub));
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = fqdn(tln, name, sub);
|
String key = fqdn(tln, name, sub);
|
||||||
if (!visited.add(key)) {
|
if (!visited.add(key)) {
|
||||||
// Loop detected
|
// Loop detected
|
||||||
server.getProtocolBridge().getLogger().warn("CNAME loop detected for " + key);
|
server.getProtocolBridge().getProtocolValues().logger.warn("CNAME loop detected for " + key);
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package org.openautonomousconnection.protocol.versions.v1_0_1.beta;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parsed INS address components.
|
||||||
|
*
|
||||||
|
* <p>Supported formats:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code name.tln}</li>
|
||||||
|
* <li>{@code sub.name.tln}</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public record InsParts(String tln, String name, String sub) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses an InfoName into INS query parts.
|
||||||
|
*
|
||||||
|
* @param infoName InfoName host string
|
||||||
|
* @return parsed parts
|
||||||
|
* @throws IllegalArgumentException if format is invalid
|
||||||
|
*/
|
||||||
|
public static InsParts parse(String infoName) {
|
||||||
|
String in = Objects.requireNonNull(infoName, "infoName").trim();
|
||||||
|
if (in.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("InfoName is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] parts = in.split("\\.");
|
||||||
|
if (parts.length < 2 || parts.length > 3) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Invalid INS address format: " + infoName + " (expected name.tln or sub.name.tln)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String tln = parts[parts.length - 1].trim();
|
||||||
|
String name = parts[parts.length - 2].trim();
|
||||||
|
String sub = (parts.length == 3) ? parts[0].trim() : null;
|
||||||
|
|
||||||
|
if (tln.isEmpty() || name.isEmpty() || (sub != null && sub.isEmpty())) {
|
||||||
|
throw new IllegalArgumentException("Invalid INS address parts in: " + infoName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new InsParts(tln, name, sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.openautonomousconnection.protocol.versions.v1_0_1.beta.compat;
|
package org.openautonomousconnection.protocol.versions.v1_0_1.beta;
|
||||||
|
|
||||||
|
import org.openautonomousconnection.protocol.ProtocolBridge;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.WebRequestPacket;
|
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.WebResponsePacket;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.stream.WebStreamChunkPacket_v1_0_0_B;
|
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.stream.WebStreamChunkPacket_v1_0_0_B;
|
||||||
@@ -11,10 +12,6 @@ import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream
|
|||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamEndPacket_v1_0_1_B;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamEndPacket_v1_0_1_B;
|
||||||
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamStartPacket_v1_0_1_B;
|
import org.openautonomousconnection.protocol.packets.v1_0_1.beta.web.impl.stream.WebStreamStartPacket_v1_0_1_B;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.WebRequestMethod;
|
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.WebRequestMethod;
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebCacheMode;
|
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebInitiatorType;
|
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketFlags;
|
|
||||||
import org.openautonomousconnection.protocol.versions.v1_0_1.beta.WebPacketHeader;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -70,7 +67,7 @@ public final class WebCompatMapper {
|
|||||||
long requestId,
|
long requestId,
|
||||||
long tabId,
|
long tabId,
|
||||||
long pageId,
|
long pageId,
|
||||||
WebRequestPacket requestPacket
|
WebRequestPacket requestPacket, ProtocolBridge bridge
|
||||||
) {
|
) {
|
||||||
Objects.requireNonNull(requestPacket, "requestPacket");
|
Objects.requireNonNull(requestPacket, "requestPacket");
|
||||||
|
|
||||||
@@ -96,7 +93,7 @@ public final class WebCompatMapper {
|
|||||||
body,
|
body,
|
||||||
null,
|
null,
|
||||||
WebInitiatorType.OTHER,
|
WebInitiatorType.OTHER,
|
||||||
WebCacheMode.DEFAULT
|
WebCacheMode.DEFAULT, bridge
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user