diff --git a/WASMImpl/Java/.gitignore b/WASMImpl/Java/.gitignore
new file mode 100644
index 0000000..0874e68
--- /dev/null
+++ b/WASMImpl/Java/.gitignore
@@ -0,0 +1,46 @@
+# Maven
+/target/
+/run/
+/dependency-reduced-pom.xml
+
+# IntelliJ IDEA
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+.idea/*
+*.iws
+*.iml
+*.ipr
+out/
+**/src/main/**/out/
+**/src/test/**/out/
+
+# Eclipse
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+**/src/main/**/bin/
+**/src/test/**/bin/
+
+# NetBeans
+/nbproject/private/
+/nbbuild/
+/nbdist/
+
+# Visual Studio Code
+/.vscode/
+
+# macOS
+.DS_Store
+
+# Java
+hs_err_pid*.log
+
+# Luxon
+/src/main/luxon_server.wasm
diff --git a/WASMImpl/Java/pom.xml b/WASMImpl/Java/pom.xml
index f1089ab..44167c8 100644
--- a/WASMImpl/Java/pom.xml
+++ b/WASMImpl/Java/pom.xml
@@ -27,6 +27,12 @@
wasi
${chicory.version}
+
+ org.jetbrains
+ annotations
+ 26.1.0
+ provided
+
diff --git a/WASMImpl/Java/src/main/java/com/gitlab/luxon_project/LuxonServer.java b/WASMImpl/Java/src/main/java/com/gitlab/luxon_project/LuxonServer.java
index 6a5bf78..f785299 100644
--- a/WASMImpl/Java/src/main/java/com/gitlab/luxon_project/LuxonServer.java
+++ b/WASMImpl/Java/src/main/java/com/gitlab/luxon_project/LuxonServer.java
@@ -8,7 +8,10 @@
import com.dylibso.chicory.runtime.Memory;
import com.dylibso.chicory.wasi.WasiOptions;
import com.dylibso.chicory.wasi.WasiPreview1;
+import com.dylibso.chicory.wasm.WasmModule;
import com.dylibso.chicory.wasm.types.ValueType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -23,6 +26,7 @@
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
+import java.nio.channels.UnsupportedAddressTypeException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.security.SecureRandom;
@@ -33,21 +37,20 @@
import java.util.Map;
public class LuxonServer {
-
private static final int O_NONBLOCK = 0x00000800;
private static final int F_GETFL = 3;
private static final int F_SETFL = 4;
-
+
private static final int AF_UNSPEC = 0;
private static final int AF_INET = 2;
private static final int AF_INET6 = 10;
-
+
private static final int SOCK_STREAM = 1;
private static final int SOCK_DGRAM = 2;
-
+
private static final int IPPROTO_TCP = 6;
private static final int IPPROTO_UDP = 17;
-
+
private static final int AI_PASSIVE = 0x0001;
private static final int AI_CANONNAME = 0x0002;
private static final int AI_NUMERICHOST = 0x0004;
@@ -55,7 +58,7 @@ public class LuxonServer {
private static final int AI_ALL = 0x0010;
private static final int AI_ADDRCONFIG = 0x0020; // accepted, ignored
private static final int AI_NUMERICSERV = 0x0400;
-
+
private static final int EAI_BADFLAGS = -1;
private static final int EAI_NONAME = -2;
private static final int EAI_AGAIN = -3;
@@ -64,907 +67,936 @@ public class LuxonServer {
private static final int EAI_SOCKTYPE = -7;
private static final int EAI_SERVICE = -8;
private static final int EAI_MEMORY = -10;
-
+
private static final int SOCKADDR_IN_LEN = 16;
private static final int SOCKADDR_IN6_LEN = 28;
private static final int ADDRINFO_LEN = 32;
-
+
// Emulated POSIX descriptor map starting at 100 to clear standard WASI descriptors (0-3)
private static final Map sockets = new HashMap<>();
- private static int nextFd = 100;
-
+ private static int nextFileDescriptor = 100;
+
private static class SocketHandle {
- final int fd;
- final int family;
+ final int fileDescriptor;
+ final int addressFamily;
boolean isServer = false;
- boolean isUdp = false;
+ boolean isUdp;
boolean nonBlocking = false;
ServerSocketChannel serverChannel;
SocketChannel socketChannel;
DatagramChannel datagramChannel;
-
- SocketHandle(int fd, int family, boolean isUdp) {
- this.fd = fd;
- this.family = family;
+
+ SocketHandle(int fileDescriptor, int addressFamily, boolean isUdp) {
+ this.fileDescriptor = fileDescriptor;
+ this.addressFamily = addressFamily;
this.isUdp = isUdp;
}
}
-
- public static void main(String[] args) {
+
+ public static void main(@NotNull String @NotNull [] args) {
try {
- WasiOptions wasiOptions = WasiOptions.builder()
- .withStdout(System.out)
- .withStderr(System.err)
- .withDirectory(".", Path.of("."))
- .build();
-
- WasiPreview1 wasi = WasiPreview1.builder()
- .withOptions(wasiOptions)
- .build();
-
- List functions = new ArrayList<>(Arrays.asList(wasi.toHostFunctions()));
-
- ImportFunction origPathOpen = null;
- ImportFunction origFdRead = null;
- ImportFunction origFdClose = null;
-
- for (ImportFunction f : functions) {
- if ("wasi_snapshot_preview1".equals(f.module())) {
- if ("path_open".equals(f.name())) origPathOpen = f;
- else if ("fd_read".equals(f.name())) origFdRead = f;
- else if ("fd_close".equals(f.name())) origFdClose = f;
+ @NotNull WasiOptions wasiOptions = WasiOptions.builder()
+ .withStdout(System.out)
+ .withStderr(System.err)
+ .withDirectory(".", Path.of("."))
+ .build();
+
+ //noinspection resource
+ @NotNull List<@NotNull ImportFunction> functions = new ArrayList<>(Arrays.asList(WasiPreview1.builder().withOptions(wasiOptions).build().toHostFunctions()));
+
+ @Nullable ImportFunction origPathOpen = null;
+ @Nullable ImportFunction origFdRead = null;
+ @Nullable ImportFunction origFdClose = null;
+
+ for (@NotNull ImportFunction function : functions) {
+ if ("wasi_snapshot_preview1".equals(function.module())) {
+ if ("path_open".equals(function.name())) origPathOpen = function;
+ else if ("fd_read".equals(function.name())) origFdRead = function;
+ else if ("fd_close".equals(function.name())) origFdClose = function;
}
}
-
- final ImportFunction finalPathOpen = origPathOpen;
- final ImportFunction finalFdRead = origFdRead;
- final ImportFunction finalFdClose = origFdClose;
-
+
+ final @Nullable ImportFunction finalPathOpen = origPathOpen;
+ final @Nullable ImportFunction finalFdRead = origFdRead;
+ final @Nullable ImportFunction finalFdClose = origFdClose;
+
// Reserve a high virtual FD number that won't collide with WASI or sockets
final int RANDOM_FD = 9999;
- final SecureRandom secureRandom = new SecureRandom();
-
+ final @NotNull SecureRandom secureRandom = new SecureRandom();
+
if (finalPathOpen != null) {
functions.remove(finalPathOpen);
- functions.add(new HostFunction(finalPathOpen.module(), finalPathOpen.name(), finalPathOpen.paramTypes(), finalPathOpen.returnTypes(), (instance, wasmArgs) -> {
- int pathPtr = (int) wasmArgs[2];
- int pathLen = (int) wasmArgs[3];
- int resultFdPtr = (int) wasmArgs[8];
-
- Memory mem = instance.memory();
- String path = new String(mem.readBytes(pathPtr, pathLen), StandardCharsets.UTF_8);
-
+ functions.add(new HostFunction(finalPathOpen.module(), finalPathOpen.name(), finalPathOpen.paramTypes(), finalPathOpen.returnTypes(), (instance, wasmArguments) -> {
+ int pathPtr = (int) wasmArguments[2];
+ int pathLen = (int) wasmArguments[3];
+ int resultFdPtr = (int) wasmArguments[8];
+
+ @NotNull Memory mem = instance.memory();
+ @NotNull String path = new String(mem.readBytes(pathPtr, pathLen), StandardCharsets.UTF_8);
+
if (path.endsWith("/dev/random") || path.endsWith("/dev/urandom") || path.equals("dev/random") || path.equals("dev/urandom")) {
writeIntLE(mem, resultFdPtr, RANDOM_FD);
- return new long[] { 0 }; // WASI_ESUCCESS
+ return new long[]{0}; // WASI_ESUCCESS
}
- return finalPathOpen.handle().apply(instance, wasmArgs);
+ return finalPathOpen.handle().apply(instance, wasmArguments);
}));
}
-
+
if (finalFdRead != null) {
functions.remove(finalFdRead);
- functions.add(new HostFunction(finalFdRead.module(), finalFdRead.name(), finalFdRead.paramTypes(), finalFdRead.returnTypes(), (instance, wasmArgs) -> {
- int fd = (int) wasmArgs[0];
+ functions.add(new HostFunction(finalFdRead.module(), finalFdRead.name(), finalFdRead.paramTypes(), finalFdRead.returnTypes(), (instance, wasmArguments) -> {
+ int fd = (int) wasmArguments[0];
if (fd == RANDOM_FD) {
- int iovsPtr = (int) wasmArgs[1];
- int iovsLen = (int) wasmArgs[2];
- int resultSizePtr = (int) wasmArgs[3];
- Memory mem = instance.memory();
-
+ int iovsPtr = (int) wasmArguments[1];
+ int iovsLen = (int) wasmArguments[2];
+ int resultSizePtr = (int) wasmArguments[3];
+ @NotNull Memory memory = instance.memory();
+
int totalRead = 0;
for (int i = 0; i < iovsLen; i++) {
- int bufPtr = readIntLE(mem, iovsPtr + (i * 8));
- int bufLen = readIntLE(mem, iovsPtr + (i * 8) + 4);
-
- byte[] randBytes = new byte[bufLen];
- secureRandom.nextBytes(randBytes);
- mem.write(bufPtr, randBytes);
- totalRead += bufLen;
+ int bufferPointer = readIntLE(memory, iovsPtr + (i * 8));
+ int bufferLength = readIntLE(memory, iovsPtr + (i * 8) + 4);
+
+ byte @NotNull [] randomBytes = new byte[bufferLength];
+ secureRandom.nextBytes(randomBytes);
+ memory.write(bufferPointer, randomBytes);
+ totalRead += bufferLength;
}
- writeIntLE(mem, resultSizePtr, totalRead);
- return new long[] { 0 }; // WASI_ESUCCESS
+ writeIntLE(memory, resultSizePtr, totalRead);
+ return new long[]{0}; // WASI_ESUCCESS
}
- return finalFdRead.handle().apply(instance, wasmArgs);
+ return finalFdRead.handle().apply(instance, wasmArguments);
}));
}
-
+
if (finalFdClose != null) {
functions.remove(finalFdClose);
functions.add(new HostFunction(finalFdClose.module(), finalFdClose.name(), finalFdClose.paramTypes(), finalFdClose.returnTypes(), (instance, wasmArgs) -> {
- int fd = (int) wasmArgs[0];
- if (fd == RANDOM_FD) {
- return new long[] { 0 }; // WASI_ESUCCESS
+ int fileDescriptor = (int) wasmArgs[0];
+ if (fileDescriptor == RANDOM_FD) {
+ return new long[]{0}; // WASI_ESUCCESS
}
return finalFdClose.handle().apply(instance, wasmArgs);
}));
}
-
+
functions.addAll(registerSocketEnvironmentImports());
-
- ImportValues imports = ImportValues.builder()
- .withFunctions(functions)
- .build();
-
- var module = LuxonServerModule.load();
- Instance instance = Instance.builder(module)
- .withMachineFactory(LuxonServerModule::create)
- .withImportValues(imports)
- .build();
-
- ExportFunction startFn = instance.export("_start");
- if (startFn != null) {
- startFn.apply();
+
+ @NotNull ImportValues imports = ImportValues.builder()
+ .withFunctions(functions)
+ .build();
+
+ @NotNull WasmModule module = LuxonServerModule.load();
+ @NotNull Instance instance = Instance.builder(module)
+ .withMachineFactory(LuxonServerModule::create)
+ .withImportValues(imports)
+ .build();
+
+ @Nullable ExportFunction startFunction = instance.export("_start");
+ if (startFunction != null) {
+ startFunction.apply();
}
-
- } catch (Exception e) {
- System.err.println("Fatal execution error inside WASM host wrapper: " + e.getMessage());
- e.printStackTrace();
+
+ } catch (@NotNull Exception exception) {
+ System.err.println("Fatal execution error inside WASM host wrapper: " + exception.getMessage());
+ exception.printStackTrace();
System.exit(1);
}
}
-
- private static List registerSocketEnvironmentImports() {
- List env = new ArrayList<>();
- final String NS = "env";
-
+
+ private static @NotNull List<@NotNull ImportFunction> registerSocketEnvironmentImports() {
+ final @NotNull List<@NotNull ImportFunction> environment = new ArrayList<>();
+ final @NotNull String namespace = "env";
+
// u32 w2c_env_socket_socket(domain, type, protocol) -> 3 params
- env.add(new HostFunction(NS, "socket_socket", params(3), returns(1), (instance, args) -> {
+ environment.add(new HostFunction(namespace, "socket_socket", params(3), returns(1), (instance, args) -> {
int domain = (int) args[0];
int type = (int) args[1];
- boolean isUdp = (type == SOCK_DGRAM);
- int fd = nextFd++;
- sockets.put(fd, new SocketHandle(fd, domain, isUdp));
- return new long[] { fd };
+ boolean isUdp = type == SOCK_DGRAM;
+ int fileDescriptor = nextFileDescriptor++;
+ sockets.put(fileDescriptor, new SocketHandle(fileDescriptor, domain, isUdp));
+ return new long[]{fileDescriptor};
}));
-
+
// u32 w2c_env_socket_bind(sockfd, addr_ptr, addrlen) -> 3 params
- env.add(new HostFunction(NS, "socket_bind", params(3), returns(1), (instance, args) -> {
- int sockfd = (int) args[0];
- int addrPtr = (int) args[1];
- int addrlen = (int) args[2];
- SocketHandle h = sockets.get(sockfd);
- if (h == null) return new long[] { -1L };
-
+ environment.add(new HostFunction(namespace, "socket_bind", params(3), returns(1), (instance, args) -> {
+ int socketFileDescriptor = (int) args[0];
+ int addressPointer = (int) args[1];
+ int addressLength = (int) args[2];
+ @Nullable SocketHandle handle = sockets.get(socketFileDescriptor);
+ if (handle == null) return new long[]{-1L};
+
try {
- Memory mem = instance.memory();
- int family = mem.readBytes(addrPtr, 1)[0] & 0xFF;
- int port = ((mem.readBytes(addrPtr + 2, 2)[0] & 0xFF) << 8) | (mem.readBytes(addrPtr + 2, 2)[1] & 0xFF);
-
- InetAddress addr = (family == AF_INET6 || addrlen == 28) ?
- InetAddress.getByAddress(mem.readBytes(addrPtr + 8, 16)) :
- InetAddress.getByAddress(mem.readBytes(addrPtr + 4, 4));
-
+ @NotNull Memory memory = instance.memory();
+ int addressFamily = memory.readBytes(addressPointer, 1)[0] & 0xFF;
+ int port = ((memory.readBytes(addressPointer + 2, 2)[0] & 0xFF) << 8) | (memory.readBytes(addressPointer + 2, 2)[1] & 0xFF);
+
+ @NotNull InetAddress address = (addressFamily == AF_INET6 || addressLength == 28) ?
+ InetAddress.getByAddress(memory.readBytes(addressPointer + 8, 16)) :
+ InetAddress.getByAddress(memory.readBytes(addressPointer + 4, 4));
+
try {
- if (h.isUdp) {
- h.datagramChannel = DatagramChannel.open();
- h.datagramChannel.configureBlocking(!h.nonBlocking);
- h.datagramChannel.bind(new InetSocketAddress(addr, port));
+ if (handle.isUdp) {
+ handle.datagramChannel = DatagramChannel.open();
+ handle.datagramChannel.configureBlocking(!handle.nonBlocking);
+ handle.datagramChannel.bind(new InetSocketAddress(address, port));
} else {
- h.isServer = true;
- h.serverChannel = ServerSocketChannel.open();
- h.serverChannel.configureBlocking(!h.nonBlocking);
- h.serverChannel.bind(new InetSocketAddress(addr, port));
+ handle.isServer = true;
+ handle.serverChannel = ServerSocketChannel.open();
+ handle.serverChannel.configureBlocking(!handle.nonBlocking);
+ handle.serverChannel.bind(new InetSocketAddress(address, port));
}
- } catch (java.nio.channels.UnsupportedAddressTypeException e) {
- InetAddress fallback = getFallbackAddress(addr);
+ } catch (UnsupportedAddressTypeException exception) {
+ @Nullable InetAddress fallback = getFallbackAddress(address);
if (fallback != null) {
- System.err.println("WARNING: Unsupported address type for bind. Falling back from " + addr + " to " + fallback);
- if (h.isUdp) {
- h.datagramChannel.bind(new InetSocketAddress(fallback, port));
+ System.err.println("WARNING: Unsupported address type for bind. Falling back from " + address + " to " + fallback);
+ if (handle.isUdp) {
+ handle.datagramChannel.bind(new InetSocketAddress(fallback, port));
} else {
- h.serverChannel.bind(new InetSocketAddress(fallback, port));
+ handle.serverChannel.bind(new InetSocketAddress(fallback, port));
}
} else {
- throw e;
+ throw exception;
}
}
- return new long[] { 0 };
- } catch (Exception e) {
- return new long[] { -1L };
+ return new long[]{0};
+ } catch (@NotNull Exception exception) {
+ return new long[]{-1L};
}
}));
-
+
// u32 w2c_env_socket_listen(sockfd, backlog) -> 2 params
- env.add(new HostFunction(NS, "socket_listen", params(2), returns(1), (instance, args) -> {
- SocketHandle h = sockets.get((int) args[0]);
- if (h != null && h.isUdp) return new long[] { 0 };
- return new long[] { (h != null && h.isServer) ? 0 : -1L };
+ environment.add(new HostFunction(namespace, "socket_listen", params(2), returns(1), (instance, args) -> {
+ @Nullable SocketHandle handle = sockets.get((int) args[0]);
+ if (handle != null && handle.isUdp) return new long[]{0};
+ return new long[]{(handle != null && handle.isServer) ? 0 : -1L};
}));
-
+
// u32 w2c_env_socket_accept(sockfd, addr_ptr, addrlen_ptr) -> 3 params
- env.add(new HostFunction(NS, "socket_accept", params(3), returns(1), (instance, args) -> {
- int sockfd = (int) args[0];
- int addrPtr = (int) args[1];
- int addrlenPtr = (int) args[2];
-
- SocketHandle h = sockets.get(sockfd);
- if (h == null || h.isUdp || !h.isServer || h.serverChannel == null) {
- return new long[] { -1L };
+ environment.add(new HostFunction(namespace, "socket_accept", params(3), returns(1), (instance, args) -> {
+ int socketFileDescriptor = (int) args[0];
+ int addressPointer = (int) args[1];
+ int addressLengthPointer = (int) args[2];
+
+ @Nullable SocketHandle handle = sockets.get(socketFileDescriptor);
+ if (handle == null || handle.isUdp || !handle.isServer || handle.serverChannel == null) {
+ return new long[]{-1L};
}
-
+
// POSIX ABI: if addr != NULL, addrlen must be a valid value-result pointer.
- if (addrPtr != 0 && addrlenPtr == 0) {
- return new long[] { -1L };
+ if (addressPointer != 0 && addressLengthPointer == 0) {
+ return new long[]{-1L};
}
-
+
try {
- SocketChannel client = h.serverChannel.accept();
+ @Nullable SocketChannel client = handle.serverChannel.accept();
if (client == null) {
- return new long[] { -1L };
+ return new long[]{-1L};
}
-
+
client.configureBlocking(true);
-
- int clientFd = nextFd++;
- SocketHandle clientHandle = new SocketHandle(clientFd, h.family, false);
+
+ int clientFileDescriptor = nextFileDescriptor++;
+ @NotNull SocketHandle clientHandle = new SocketHandle(clientFileDescriptor, handle.addressFamily, false);
clientHandle.socketChannel = client;
- sockets.put(clientFd, clientHandle);
-
- if (addrPtr != 0) {
- SocketAddress remote = client.getRemoteAddress();
+ sockets.put(clientFileDescriptor, clientHandle);
+
+ if (addressPointer != 0) {
+ @Nullable SocketAddress remote = client.getRemoteAddress();
if (!(remote instanceof InetSocketAddress) ||
- !writeSockaddrResult(instance.memory(), addrPtr, addrlenPtr, (InetSocketAddress) remote, h.family)) {
- closeHandle(clientFd);
- return new long[] { -1L };
+ writeSockaddrResult(instance.memory(), addressPointer, addressLengthPointer, (InetSocketAddress) remote, handle.addressFamily)) {
+ closeHandle(clientFileDescriptor);
+ return new long[]{-1L};
}
}
-
- return new long[] { clientFd };
- } catch (IOException e) {
- return new long[] { -1L };
+
+ return new long[]{clientFileDescriptor};
+ } catch (@NotNull IOException e) {
+ return new long[]{-1L};
}
}));
-
+
// u32 w2c_env_socket_connect(sockfd, addr_ptr, addrlen) -> 3 params
- env.add(new HostFunction(NS, "socket_connect", params(3), returns(1), (instance, args) -> {
- int sockfd = (int) args[0];
- int addrPtr = (int) args[1];
- int addrlen = (int) args[2];
- SocketHandle h = sockets.get(sockfd);
- if (h == null) return new long[] { -1L };
-
+ environment.add(new HostFunction(namespace, "socket_connect", params(3), returns(1), (instance, args) -> {
+ int socketFileDescriptor = (int) args[0];
+ int addressPointer = (int) args[1];
+ int addressLength = (int) args[2];
+ @Nullable SocketHandle handle = sockets.get(socketFileDescriptor);
+ if (handle == null) return new long[]{-1L};
+
try {
- Memory mem = instance.memory();
- int family = mem.readBytes(addrPtr, 1)[0] & 0xFF;
- int port = ((mem.readBytes(addrPtr + 2, 2)[0] & 0xFF) << 8) | (mem.readBytes(addrPtr + 2, 2)[1] & 0xFF);
- InetAddress addr = (family == AF_INET6 || addrlen == 28) ?
- InetAddress.getByAddress(mem.readBytes(addrPtr + 8, 16)) :
- InetAddress.getByAddress(mem.readBytes(addrPtr + 4, 4));
-
+ @NotNull Memory memory = instance.memory();
+ int addressFamily = memory.readBytes(addressPointer, 1)[0] & 0xFF;
+ int port = ((memory.readBytes(addressPointer + 2, 2)[0] & 0xFF) << 8) | (memory.readBytes(addressPointer + 2, 2)[1] & 0xFF);
+ @NotNull InetAddress address = (addressFamily == AF_INET6 || addressLength == 28) ?
+ InetAddress.getByAddress(memory.readBytes(addressPointer + 8, 16)) :
+ InetAddress.getByAddress(memory.readBytes(addressPointer + 4, 4));
+
try {
- if (h.isUdp) {
- h.datagramChannel = DatagramChannel.open();
- h.datagramChannel.configureBlocking(!h.nonBlocking);
- h.datagramChannel.connect(new InetSocketAddress(addr, port));
- return new long[] { 0 };
+ if (handle.isUdp) {
+ handle.datagramChannel = DatagramChannel.open();
+ handle.datagramChannel.configureBlocking(!handle.nonBlocking);
+ handle.datagramChannel.connect(new InetSocketAddress(address, port));
+ return new long[]{0};
} else {
- h.socketChannel = SocketChannel.open();
- h.socketChannel.configureBlocking(!h.nonBlocking);
- boolean success = h.socketChannel.connect(new InetSocketAddress(addr, port));
- return new long[] { success ? 0 : -1L };
+ handle.socketChannel = SocketChannel.open();
+ handle.socketChannel.configureBlocking(!handle.nonBlocking);
+ boolean success = handle.socketChannel.connect(new InetSocketAddress(address, port));
+ return new long[]{success ? 0 : -1L};
}
- } catch (java.nio.channels.UnsupportedAddressTypeException e) {
- InetAddress fallback = getFallbackAddress(addr);
+ } catch (@NotNull UnsupportedAddressTypeException exception) {
+ @Nullable InetAddress fallback = getFallbackAddress(address);
if (fallback != null) {
- System.err.println("WARNING: Unsupported address type for connect. Falling back from " + addr + " to " + fallback);
- if (h.isUdp) {
- h.datagramChannel.connect(new InetSocketAddress(fallback, port));
- return new long[] { 0 };
+ System.err.println("WARNING: Unsupported address type for connect. Falling back from " + address + " to " + fallback);
+ if (handle.isUdp) {
+ handle.datagramChannel.connect(new InetSocketAddress(fallback, port));
+ return new long[]{0};
} else {
- boolean success = h.socketChannel.connect(new InetSocketAddress(fallback, port));
- return new long[] { success ? 0 : -1L };
+ boolean success = handle.socketChannel.connect(new InetSocketAddress(fallback, port));
+ return new long[]{success ? 0 : -1L};
}
} else {
- throw e; // Rethrow if we can't formulate a valid fallback
+ throw exception; // Rethrow if we can't formulate a valid fallback
}
}
- } catch (Exception e) {
- return new long[] { -1L };
+ } catch (@NotNull Exception exception) {
+ return new long[]{-1L};
}
}));
-
- env.add(new HostFunction(NS, "socket_send", params(4), returns(1), (instance, args) ->
- doSend(instance, (int) args[0], (int) args[1], (int) args[2], (int) args[3], 0, 0)
+
+ environment.add(new HostFunction(namespace, "socket_send", params(4), returns(1), (instance, wasmArguments) ->
+ doSend(instance, (int) wasmArguments[0], (int) wasmArguments[1], (int) wasmArguments[2], (int) wasmArguments[3], 0, 0)
));
-
- env.add(new HostFunction(NS, "socket_recv", params(4), returns(1), (instance, args) ->
- doRecv(instance, (int) args[0], (int) args[1], (int) args[2], (int) args[3], 0, 0)
+
+ environment.add(new HostFunction(namespace, "socket_recv", params(4), returns(1), (instance, wasmArguments) ->
+ doRecv(instance, (int) wasmArguments[0], (int) wasmArguments[1], (int) wasmArguments[2], (int) wasmArguments[3], 0, 0)
));
-
- env.add(new HostFunction(NS, "socket_sendto", params(6), returns(1), (instance, args) ->
- doSend(instance, (int) args[0], (int) args[1], (int) args[2], (int) args[3], (int) args[4], (int) args[5])
+
+ environment.add(new HostFunction(namespace, "socket_sendto", params(6), returns(1), (instance, wasmArguments) ->
+ doSend(instance, (int) wasmArguments[0], (int) wasmArguments[1], (int) wasmArguments[2], (int) wasmArguments[3], (int) wasmArguments[4], (int) wasmArguments[5])
));
-
- env.add(new HostFunction(NS, "socket_recvfrom", params(6), returns(1), (instance, args) ->
- doRecv(instance, (int) args[0], (int) args[1], (int) args[2], (int) args[3], (int) args[4], (int) args[5])
+
+ environment.add(new HostFunction(namespace, "socket_recvfrom", params(6), returns(1), (instance, wasmArguments) ->
+ doRecv(instance, (int) wasmArguments[0], (int) wasmArguments[1], (int) wasmArguments[2], (int) wasmArguments[3], (int) wasmArguments[4], (int) wasmArguments[5])
));
-
- env.add(new HostFunction(NS, "socket_setsockopt", params(5), returns(1), (instance, args) -> new long[] { 0 }));
- env.add(new HostFunction(NS, "socket_shutdown", params(2), returns(1), (instance, args) -> closeHandle((int) args[0])));
- env.add(new HostFunction(NS, "socket_close", params(1), returns(1), (instance, args) -> closeHandle((int) args[0])));
-
+
+ environment.add(new HostFunction(namespace, "socket_setsockopt", params(5), returns(1), (instance, wasmArguments) -> new long[]{0}));
+ environment.add(new HostFunction(namespace, "socket_shutdown", params(2), returns(1), (instance, wasmArguments) -> closeHandle((int) wasmArguments[0])));
+ environment.add(new HostFunction(namespace, "socket_close", params(1), returns(1), (instance, wasmArguments) -> closeHandle((int) wasmArguments[0])));
+
// u32 w2c_env_socket_fcntl(fd, cmd, arg) -> 3 params
- env.add(new HostFunction(NS, "socket_fcntl", params(3), returns(1), (instance, args) -> {
- SocketHandle h = sockets.get((int) args[0]);
- if (h == null) return new long[] { -1L };
- int cmd = (int) args[1];
- int arg = (int) args[2];
-
+ environment.add(new HostFunction(namespace, "socket_fcntl", params(3), returns(1), (instance, wasmArguments) -> {
+ @Nullable SocketHandle handle = sockets.get((int) wasmArguments[0]);
+ if (handle == null) return new long[]{-1L};
+ int cmd = (int) wasmArguments[1];
+ int arg = (int) wasmArguments[2];
+
if (cmd == F_GETFL) {
- return new long[] { h.nonBlocking ? O_NONBLOCK : 0 };
+ return new long[]{handle.nonBlocking ? O_NONBLOCK : 0};
} else if (cmd == F_SETFL) {
- h.nonBlocking = (arg & O_NONBLOCK) != 0;
+ handle.nonBlocking = (arg & O_NONBLOCK) != 0;
try {
- if (h.serverChannel != null) h.serverChannel.configureBlocking(!h.nonBlocking);
- if (h.datagramChannel != null) h.datagramChannel.configureBlocking(!h.nonBlocking);
- if (h.socketChannel != null) h.socketChannel.configureBlocking(!h.nonBlocking);
- return new long[] { 0 };
- } catch (IOException e) {
- return new long[] { -1L };
+ if (handle.serverChannel != null) handle.serverChannel.configureBlocking(!handle.nonBlocking);
+ if (handle.datagramChannel != null) handle.datagramChannel.configureBlocking(!handle.nonBlocking);
+ if (handle.socketChannel != null) handle.socketChannel.configureBlocking(!handle.nonBlocking);
+ return new long[]{0};
+ } catch (@NotNull IOException exception) {
+ return new long[]{-1L};
}
}
- return new long[] { -1L };
+ return new long[]{-1L};
}));
-
- env.add(new HostFunction(NS, "socket_ioctl", params(3), returns(1), (instance, args) -> new long[] { 0 }));
-
- env.add(new HostFunction(NS, "socket_inet_pton", params(3), returns(1), (instance, args) -> {
- int af = (int) args[0];
- int srcPtr = (int) args[1];
- int dstPtr = (int) args[2];
-
+
+ environment.add(new HostFunction(namespace, "socket_ioctl", params(3), returns(1), (instance, wasmArguments) -> new long[]{0}));
+
+ environment.add(new HostFunction(namespace, "socket_inet_pton", params(3), returns(1), (instance, wasmArguments) -> {
+ int addressFamily = (int) wasmArguments[0];
+ int sourcePointer = (int) wasmArguments[1];
+ int destinationPointer = (int) wasmArguments[2];
+
try {
- Memory mem = instance.memory();
- String src = readNullTerminatedString(mem, srcPtr);
-
+ @NotNull Memory memory = instance.memory();
+ @NotNull String source = readNullTerminatedString(memory, sourcePointer);
+
byte[] parsed;
- if (af == AF_INET) {
- parsed = parseIpv4Literal(src);
- } else if (af == AF_INET6) {
- parsed = parseIpv6Literal(src);
+ if (addressFamily == AF_INET) {
+ parsed = parseIpv4Literal(source);
+ } else if (addressFamily == AF_INET6) {
+ parsed = parseIpv6Literal(source);
} else {
// POSIX: unsupported family => -1 / EAFNOSUPPORT.
- return new long[] { -1L };
+ return new long[]{-1L};
}
-
+
if (parsed == null) {
// Invalid presentation format.
- return new long[] { 0 };
+ return new long[]{0};
}
-
- mem.write(dstPtr, parsed);
- return new long[] { 1 };
- } catch (Exception e) {
- return new long[] { 0 };
+
+ memory.write(destinationPointer, parsed);
+ return new long[]{1};
+ } catch (@NotNull Exception e) {
+ return new long[]{0};
}
}));
-
- env.add(new HostFunction(NS, "socket_inet_ntop", params(4), returns(1), (instance, args) -> {
+
+ environment.add(new HostFunction(namespace, "socket_inet_ntop", params(4), returns(1), (instance, args) -> {
try {
- Memory mem = instance.memory();
- int af = (int) args[0];
- byte[] ipBytes = mem.readBytes((int) args[1], af == AF_INET6 ? 16 : 4);
- byte[] strBytes = InetAddress.getByAddress(ipBytes).getHostAddress().getBytes(StandardCharsets.UTF_8);
+ @NotNull Memory memory = instance.memory();
+ int addressFamily = (int) args[0];
+ byte @NotNull [] ipBytes = memory.readBytes((int) args[1], addressFamily == AF_INET6 ? 16 : 4);
+ byte @NotNull [] strBytes = InetAddress.getByAddress(ipBytes).getHostAddress().getBytes(StandardCharsets.UTF_8);
if (strBytes.length + 1 <= (int) args[3]) {
- mem.write((int) args[2], strBytes);
- mem.write((int) args[2] + strBytes.length, new byte[] { 0 });
- return new long[] { args[2] };
+ memory.write((int) args[2], strBytes);
+ memory.write((int) args[2] + strBytes.length, new byte[]{0});
+ return new long[]{args[2]};
}
- } catch (Exception e) {}
- return new long[] { 0 };
+ } catch (@NotNull Exception ignored) {
+ }
+ return new long[]{0};
}));
-
+
// Selector loop evaluating Read/Write states asynchronously
- env.add(new HostFunction(NS, "socket_select", params(5), returns(1), (instance, args) -> {
+ environment.add(new HostFunction(namespace, "socket_select", params(5), returns(1), (instance, args) -> {
int nfds = (int) args[0];
int readfdsPtr = (int) args[1];
int writefdsPtr = (int) args[2];
int exceptfdsPtr = (int) args[3];
- int timeoutPtr = (int) args[4];
- Memory mem = instance.memory();
-
- long timeoutMs = 0;
+ int timeoutPointer = (int) args[4];
+ @NotNull Memory memory = instance.memory();
+
+ long timeoutMilliseconds = 0;
boolean hasTimeout = false;
- if (timeoutPtr != 0) {
+ if (timeoutPointer != 0) {
hasTimeout = true;
- long sec = readLongLE(mem, timeoutPtr);
- long usec = readLongLE(mem, timeoutPtr + 8);
- timeoutMs = (sec * 1000) + (usec / 1000);
+ long seconds = readLongLE(memory, timeoutPointer);
+ long milliseconds = readLongLE(memory, timeoutPointer + 8);
+ timeoutMilliseconds = (seconds * 1000) + (milliseconds / 1000);
}
-
+
try (Selector selector = Selector.open()) {
- Map keyToFd = new HashMap<>();
-
+ @NotNull Map<@NotNull SelectionKey, @NotNull Integer> keyFileDescriptorMap = new HashMap<>();
+
int bytesToClear = (nfds + 7) / 8;
-
- byte[] rfds = readfdsPtr != 0 && bytesToClear > 0 ? mem.readBytes(readfdsPtr, bytesToClear) : null;
- byte[] wfds = writefdsPtr != 0 && bytesToClear > 0 ? mem.readBytes(writefdsPtr, bytesToClear) : null;
-
- if (readfdsPtr != 0 && bytesToClear > 0) mem.write(readfdsPtr, new byte[bytesToClear]);
- if (writefdsPtr != 0 && bytesToClear > 0) mem.write(writefdsPtr, new byte[bytesToClear]);
- if (exceptfdsPtr != 0 && bytesToClear > 0) mem.write(exceptfdsPtr, new byte[bytesToClear]);
-
+
+ byte[] rfds = readfdsPtr != 0 && bytesToClear > 0 ? memory.readBytes(readfdsPtr, bytesToClear) : null;
+ byte[] wfds = writefdsPtr != 0 && bytesToClear > 0 ? memory.readBytes(writefdsPtr, bytesToClear) : null;
+
+ if (readfdsPtr != 0 && bytesToClear > 0) memory.write(readfdsPtr, new byte[bytesToClear]);
+ if (writefdsPtr != 0 && bytesToClear > 0) memory.write(writefdsPtr, new byte[bytesToClear]);
+ if (exceptfdsPtr != 0 && bytesToClear > 0) memory.write(exceptfdsPtr, new byte[bytesToClear]);
+
for (int fd = 0; fd < nfds; fd++) {
boolean wantsRead = rfds != null && (rfds[fd / 8] & (1 << (fd % 8))) != 0;
boolean wantsWrite = wfds != null && (wfds[fd / 8] & (1 << (fd % 8))) != 0;
-
+
if (wantsRead || wantsWrite) {
- SocketHandle h = sockets.get(fd);
- if (h != null) {
- int ops = 0;
+ @Nullable SocketHandle handle = sockets.get(fd);
+ if (handle != null) {
+ int operations = 0;
if (wantsRead) {
- if (h.isServer && h.serverChannel != null) ops |= SelectionKey.OP_ACCEPT;
- else ops |= SelectionKey.OP_READ;
+ if (handle.isServer && handle.serverChannel != null)
+ operations |= SelectionKey.OP_ACCEPT;
+ else operations |= SelectionKey.OP_READ;
}
- if (wantsWrite && !h.isServer) {
- ops |= SelectionKey.OP_WRITE;
+ if (wantsWrite && !handle.isServer) {
+ operations |= SelectionKey.OP_WRITE;
}
-
- if (ops != 0) {
- SelectionKey key = null;
- if (h.isServer && h.serverChannel != null) {
- if (h.serverChannel.isBlocking()) h.serverChannel.configureBlocking(false);
- key = h.serverChannel.register(selector, ops);
- } else if (h.isUdp && h.datagramChannel != null) {
- if (h.datagramChannel.isBlocking()) h.datagramChannel.configureBlocking(false);
- key = h.datagramChannel.register(selector, ops);
- } else if (h.socketChannel != null) {
- if (h.socketChannel.isBlocking()) h.socketChannel.configureBlocking(false);
- key = h.socketChannel.register(selector, ops);
+
+ if (operations != 0) {
+ @Nullable SelectionKey key = null;
+ if (handle.isServer && handle.serverChannel != null) {
+ if (handle.serverChannel.isBlocking())
+ handle.serverChannel.configureBlocking(false);
+ key = handle.serverChannel.register(selector, operations);
+ } else if (handle.isUdp && handle.datagramChannel != null) {
+ if (handle.datagramChannel.isBlocking())
+ handle.datagramChannel.configureBlocking(false);
+ key = handle.datagramChannel.register(selector, operations);
+ } else if (handle.socketChannel != null) {
+ if (handle.socketChannel.isBlocking())
+ handle.socketChannel.configureBlocking(false);
+ key = handle.socketChannel.register(selector, operations);
}
- if (key != null) keyToFd.put(key, fd);
+ if (key != null) keyFileDescriptorMap.put(key, fd);
}
}
}
}
-
+
int readyCount = 0;
- if (!keyToFd.isEmpty()) {
+ if (!keyFileDescriptorMap.isEmpty()) {
if (hasTimeout) {
- if (timeoutMs == 0) selector.selectNow();
- else selector.select(timeoutMs);
+ if (timeoutMilliseconds == 0) selector.selectNow();
+ else selector.select(timeoutMilliseconds);
} else {
selector.select();
}
-
- for (SelectionKey key : selector.selectedKeys()) {
- int fd = keyToFd.get(key);
+
+ for (@NotNull SelectionKey key : selector.selectedKeys()) {
+ int fd = keyFileDescriptorMap.get(key);
if (readfdsPtr != 0 && (key.isReadable() || key.isAcceptable())) {
- byte[] b = mem.readBytes(readfdsPtr + (fd / 8), 1);
- b[0] |= (byte) (1 << (fd % 8));
- mem.write(readfdsPtr + (fd / 8), b);
+ byte @NotNull [] bytes = memory.readBytes(readfdsPtr + (fd / 8), 1);
+ bytes[0] |= (byte) (1 << (fd % 8));
+ memory.write(readfdsPtr + (fd / 8), bytes);
readyCount++;
}
if (writefdsPtr != 0 && key.isWritable()) {
- byte[] b = mem.readBytes(writefdsPtr + (fd / 8), 1);
- b[0] |= (byte) (1 << (fd % 8));
- mem.write(writefdsPtr + (fd / 8), b);
+ byte @NotNull [] bytes = memory.readBytes(writefdsPtr + (fd / 8), 1);
+ bytes[0] |= (byte) (1 << (fd % 8));
+ memory.write(writefdsPtr + (fd / 8), bytes);
readyCount++;
}
}
- } else if (hasTimeout && timeoutMs > 0) {
- Thread.sleep(timeoutMs);
+ } else if (hasTimeout && timeoutMilliseconds > 0) {
+ Thread.sleep(timeoutMilliseconds);
}
-
- for (SelectionKey key : keyToFd.keySet()) key.cancel();
+
+ for (@NotNull SelectionKey key : keyFileDescriptorMap.keySet()) key.cancel();
selector.selectNow();
-
- for (int fd : keyToFd.values()) {
- SocketHandle h = sockets.get(fd);
- if (h != null) {
- if (h.isServer && h.serverChannel != null) h.serverChannel.configureBlocking(!h.nonBlocking);
- else if (h.isUdp && h.datagramChannel != null) h.datagramChannel.configureBlocking(!h.nonBlocking);
- else if (h.socketChannel != null) h.socketChannel.configureBlocking(!h.nonBlocking);
+
+ for (int fileDescriptor : keyFileDescriptorMap.values()) {
+ @Nullable SocketHandle handle = sockets.get(fileDescriptor);
+ if (handle != null) {
+ if (handle.isServer && handle.serverChannel != null)
+ handle.serverChannel.configureBlocking(!handle.nonBlocking);
+ else if (handle.isUdp && handle.datagramChannel != null)
+ handle.datagramChannel.configureBlocking(!handle.nonBlocking);
+ else if (handle.socketChannel != null)
+ handle.socketChannel.configureBlocking(!handle.nonBlocking);
}
}
- return new long[] { readyCount };
- } catch (Exception e) {
- return new long[] { -1L };
+ return new long[]{readyCount};
+ } catch (@NotNull Exception e) {
+ return new long[]{-1L};
}
}));
-
- env.add(new HostFunction(NS, "socket_getaddrinfo", params(4), returns(1), (instance, args) -> {
- Memory mem = instance.memory();
-
- int nodePtr = (int) args[0];
- int servicePtr = (int) args[1];
- int hintsPtr = (int) args[2];
- int resPtr = (int) args[3];
-
- if (resPtr == 0) {
- return new long[] { EAI_FAIL };
+
+ environment.add(new HostFunction(namespace, "socket_getaddrinfo", params(4), returns(1), (instance, args) -> {
+ @NotNull Memory memory = instance.memory();
+
+ int nodePointer = (int) args[0];
+ int servicePointer = (int) args[1];
+ int hintsPointer = (int) args[2];
+ int resourcePointer = (int) args[3];
+
+ if (resourcePointer == 0) {
+ return new long[]{EAI_FAIL};
}
- writeIntLE(mem, resPtr, 0);
-
- String node = nodePtr != 0 ? readNullTerminatedString(mem, nodePtr) : null;
- String service = servicePtr != 0 ? readNullTerminatedString(mem, servicePtr) : null;
-
+ writeIntLE(memory, resourcePointer, 0);
+
+ @Nullable String node = nodePointer != 0 ? readNullTerminatedString(memory, nodePointer) : null;
+ @Nullable String service = servicePointer != 0 ? readNullTerminatedString(memory, servicePointer) : null;
+
if (node == null && service == null) {
- return new long[] { EAI_NONAME };
+ return new long[]{EAI_NONAME};
}
-
+
int flags = 0;
- int family = AF_UNSPEC;
+ int addressFamily = AF_UNSPEC;
int socktype = 0;
int protocol = 0;
-
- if (hintsPtr != 0) {
- flags = readIntLE(mem, hintsPtr + 0);
- family = readIntLE(mem, hintsPtr + 4);
- socktype = readIntLE(mem, hintsPtr + 8);
- protocol = readIntLE(mem, hintsPtr + 12);
+
+ if (hintsPointer != 0) {
+ flags = readIntLE(memory, hintsPointer);
+ addressFamily = readIntLE(memory, hintsPointer + 4);
+ socktype = readIntLE(memory, hintsPointer + 8);
+ protocol = readIntLE(memory, hintsPointer + 12);
}
-
+
int supportedFlags =
AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST |
- AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG | AI_NUMERICSERV;
-
+ AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG | AI_NUMERICSERV;
+
if ((flags & ~supportedFlags) != 0) {
- return new long[] { EAI_BADFLAGS };
+ return new long[]{EAI_BADFLAGS};
}
-
- if (family != AF_UNSPEC && family != AF_INET && family != AF_INET6) {
- return new long[] { EAI_FAMILY };
+
+ if (addressFamily != AF_UNSPEC && addressFamily != AF_INET && addressFamily != AF_INET6) {
+ return new long[]{EAI_FAMILY};
}
-
+
if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM) {
- return new long[] { EAI_SOCKTYPE };
+ return new long[]{EAI_SOCKTYPE};
}
-
+
if (protocol != 0 && protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) {
- return new long[] { EAI_SERVICE };
+ return new long[]{EAI_SERVICE};
}
-
+
if ((socktype == SOCK_STREAM && protocol == IPPROTO_UDP) ||
(socktype == SOCK_DGRAM && protocol == IPPROTO_TCP)) {
- return new long[] { EAI_SERVICE };
+ return new long[]{EAI_SERVICE};
}
-
+
int port = 0;
if (service != null) {
- Integer parsedPort = parseNumericService(service);
+ @Nullable Integer parsedPort = parseNumericService(service);
if (parsedPort == null) {
- return new long[] { EAI_SERVICE };
+ return new long[]{EAI_SERVICE};
}
port = parsedPort;
}
-
- List addresses;
- boolean numericNode = false;
-
+
+ @NotNull List<@NotNull InetAddress> addresses;
+ boolean numericNode;
+
try {
if (node == null) {
- addresses = defaultAddressesForNullNode(family, (flags & AI_PASSIVE) != 0);
+ addresses = defaultAddressesForNullNode(addressFamily, (flags & AI_PASSIVE) != 0);
} else {
byte[] v4 = parseIpv4Literal(node);
byte[] v6 = (v4 == null) ? parseIpv6Literal(node) : null;
numericNode = (v4 != null || v6 != null);
-
+
if (numericNode) {
- addresses = resolveNumericNode(node, family, flags, v4, v6);
+ addresses = resolveNumericNode(addressFamily, flags, v4, v6);
} else {
if ((flags & AI_NUMERICHOST) != 0) {
- return new long[] { EAI_NONAME };
+ return new long[]{EAI_NONAME};
}
- addresses = resolveDnsNode(node, family, flags);
+ addresses = resolveDnsNode(node, addressFamily, flags);
}
}
- } catch (UnknownHostException e) {
- return new long[] { EAI_NONAME };
- } catch (Exception e) {
- return new long[] { EAI_FAIL };
+ } catch (@NotNull UnknownHostException e) {
+ return new long[]{EAI_NONAME};
+ } catch (@NotNull Exception e) {
+ return new long[]{EAI_FAIL};
}
-
+
if (addresses.isEmpty()) {
- return new long[] { EAI_NONAME };
+ return new long[]{EAI_NONAME};
}
-
- List pairs = buildSockProtoPairs(socktype, protocol);
+
+ @NotNull List<@NotNull SockProtoPair> pairs = buildSockProtoPairs(socktype, protocol);
if (pairs.isEmpty()) {
- return new long[] { EAI_SERVICE };
+ return new long[]{EAI_SERVICE};
}
-
- String canonName = ((flags & AI_CANONNAME) != 0 && node != null) ? node : null;
-
- List results = new ArrayList<>();
+
+ @Nullable String canonicalName = ((flags & AI_CANONNAME) != 0 && node != null) ? node : null;
+
+ @NotNull List<@NotNull AddrInfoResult> results = new ArrayList<>();
boolean first = true;
-
- for (InetAddress addr : addresses) {
+
+ for (@NotNull InetAddress addr : addresses) {
byte[] raw = addr.getAddress();
int outFamily = raw.length == 16 ? AF_INET6 : AF_INET;
int scopeId = (addr instanceof Inet6Address) ? ((Inet6Address) addr).getScopeId() : 0;
byte[] sockaddr = encodeSockaddr(outFamily, raw, port, scopeId);
-
- for (SockProtoPair pair : pairs) {
+
+ for (@NotNull SockProtoPair pair : pairs) {
results.add(new AddrInfoResult(
outFamily,
- pair.socktype,
+ pair.socketType,
pair.protocol,
sockaddr,
- first ? canonName : null
+ first ? canonicalName : null
));
first = false;
}
}
-
- ExportFunction malloc = findExport(instance, "malloc", "_malloc");
- ExportFunction free = findExport(instance, "free", "_free");
+
+ @Nullable ExportFunction malloc = findExport(instance, "malloc", "_malloc");
+ @Nullable ExportFunction free = findExport(instance, "free", "_free");
if (malloc == null) {
- return new long[] { EAI_MEMORY };
+ return new long[]{EAI_MEMORY};
}
-
- List allocated = new ArrayList<>();
-
+
+ @NotNull List<@NotNull Integer> allocated = new ArrayList<>();
+
try {
- int head = 0;
- int prev = 0;
-
- for (AddrInfoResult r : results) {
- int saPtr = guestMalloc(malloc, r.sockaddr.length);
+ int headPointer = 0;
+ int previousPointer = 0;
+
+ for (@NotNull AddrInfoResult r : results) {
+ int saPtr = guestMalloc(malloc, r.socketAddress.length);
if (saPtr == 0) throw new OutOfMemoryError();
allocated.add(saPtr);
- mem.write(saPtr, r.sockaddr);
-
+ memory.write(saPtr, r.socketAddress);
+
int canonPtr = 0;
- if (r.canonName != null) {
- byte[] nameBytes = r.canonName.getBytes(StandardCharsets.UTF_8);
+ if (r.canonicalName != null) {
+ byte[] nameBytes = r.canonicalName.getBytes(StandardCharsets.UTF_8);
canonPtr = guestMalloc(malloc, nameBytes.length + 1);
if (canonPtr == 0) throw new OutOfMemoryError();
allocated.add(canonPtr);
- mem.write(canonPtr, nameBytes);
- mem.write(canonPtr + nameBytes.length, new byte[] { 0 });
+ memory.write(canonPtr, nameBytes);
+ memory.write(canonPtr + nameBytes.length, new byte[]{0});
}
-
- int aiPtr = guestMalloc(malloc, ADDRINFO_LEN);
- if (aiPtr == 0) throw new OutOfMemoryError();
- allocated.add(aiPtr);
-
- writeIntLE(mem, aiPtr + 0, 0);
- writeIntLE(mem, aiPtr + 4, r.family);
- writeIntLE(mem, aiPtr + 8, r.socktype);
- writeIntLE(mem, aiPtr + 12, r.protocol);
- writeIntLE(mem, aiPtr + 16, r.sockaddr.length);
- writeIntLE(mem, aiPtr + 20, saPtr);
- writeIntLE(mem, aiPtr + 24, canonPtr);
- writeIntLE(mem, aiPtr + 28, 0);
-
- if (head == 0) {
- head = aiPtr;
+
+ int addressInfoPointer = guestMalloc(malloc, ADDRINFO_LEN);
+ if (addressInfoPointer == 0) throw new OutOfMemoryError();
+ allocated.add(addressInfoPointer);
+
+ writeIntLE(memory, addressInfoPointer, 0);
+ writeIntLE(memory, addressInfoPointer + 4, r.addressFamily);
+ writeIntLE(memory, addressInfoPointer + 8, r.socketType);
+ writeIntLE(memory, addressInfoPointer + 12, r.protocol);
+ writeIntLE(memory, addressInfoPointer + 16, r.socketAddress.length);
+ writeIntLE(memory, addressInfoPointer + 20, saPtr);
+ writeIntLE(memory, addressInfoPointer + 24, canonPtr);
+ writeIntLE(memory, addressInfoPointer + 28, 0);
+
+ if (headPointer == 0) {
+ headPointer = addressInfoPointer;
} else {
- writeIntLE(mem, prev + 28, aiPtr);
+ writeIntLE(memory, previousPointer + 28, addressInfoPointer);
}
- prev = aiPtr;
+ previousPointer = addressInfoPointer;
}
-
- writeIntLE(mem, resPtr, head);
- return new long[] { 0 };
- } catch (Throwable t) {
+
+ writeIntLE(memory, resourcePointer, headPointer);
+ return new long[]{0};
+ } catch (@NotNull Throwable throwable) {
if (free != null) {
for (int i = allocated.size() - 1; i >= 0; i--) {
int ptr = allocated.get(i);
if (ptr != 0) free.apply(ptr);
}
}
- writeIntLE(mem, resPtr, 0);
- return new long[] { EAI_MEMORY };
+ writeIntLE(memory, resourcePointer, 0);
+ return new long[]{EAI_MEMORY};
}
}));
-
- env.add(new HostFunction(NS, "socket_freeaddrinfo", params(1), returns(0), (instance, args) -> {
- ExportFunction free = instance.export("free");
+
+ environment.add(new HostFunction(namespace, "socket_freeaddrinfo", params(1), returns(0), (instance, args) -> {
+ @Nullable ExportFunction free = instance.export("free");
if (free == null) free = instance.export("_free");
if (free == null) return new long[0];
-
- Memory mem = instance.memory();
- int curr = (int) args[0];
- while (curr != 0) {
- int addr = readIntLE(mem, curr + 20);
- int canon = readIntLE(mem, curr + 24);
- int next = readIntLE(mem, curr + 28);
-
- if (addr != 0) free.apply(addr);
+
+ @NotNull Memory mem = instance.memory();
+ int currentArgument = (int) args[0];
+ while (currentArgument != 0) {
+ int address = readIntLE(mem, currentArgument + 20);
+ int canon = readIntLE(mem, currentArgument + 24);
+ int next = readIntLE(mem, currentArgument + 28);
+
+ if (address != 0) free.apply(address);
if (canon != 0) free.apply(canon);
- free.apply(curr);
- curr = next;
+ free.apply(currentArgument);
+ currentArgument = next;
}
return new long[0];
}));
-
+
// u32 w2c_env_socket_getsockname(sockfd, addr_ptr, addrlen_ptr) -> 3 params
- env.add(new HostFunction(NS, "socket_getsockname", params(3), returns(1), (instance, args) -> {
- int sockfd = (int) args[0];
- int addrPtr = (int) args[1];
- int addrlenPtr = (int) args[2];
-
- SocketHandle h = sockets.get(sockfd);
- if (h == null) return new long[] { -1L };
-
+ environment.add(new HostFunction(namespace, "socket_getsockname", params(3), returns(1), (instance, args) -> {
+ int socketFileDescriptor = (int) args[0];
+ int addressPointer = (int) args[1];
+ int addressLengthPointer = (int) args[2];
+
+ @Nullable SocketHandle handle = sockets.get(socketFileDescriptor);
+ if (handle == null) return new long[]{-1L};
+
// POSIX ABI: if addr != NULL, addrlen must be a valid value-result pointer.
- if (addrPtr != 0 && addrlenPtr == 0) {
- return new long[] { -1L };
+ if (addressPointer != 0 && addressLengthPointer == 0) {
+ return new long[]{-1L};
}
-
+
try {
- SocketAddress local = null;
- if (h.isServer && h.serverChannel != null) {
- local = h.serverChannel.getLocalAddress();
- } else if (h.isUdp && h.datagramChannel != null) {
- local = h.datagramChannel.getLocalAddress();
- } else if (h.socketChannel != null) {
- local = h.socketChannel.getLocalAddress();
+ @Nullable SocketAddress socketAddress = null;
+ if (handle.isServer && handle.serverChannel != null) {
+ socketAddress = handle.serverChannel.getLocalAddress();
+ } else if (handle.isUdp && handle.datagramChannel != null) {
+ socketAddress = handle.datagramChannel.getLocalAddress();
+ } else if (handle.socketChannel != null) {
+ socketAddress = handle.socketChannel.getLocalAddress();
}
-
- if (local == null) {
- return new long[] { -1L };
+
+ if (socketAddress == null) {
+ return new long[]{-1L};
}
-
- if (addrPtr != 0) {
- if (!(local instanceof InetSocketAddress) ||
- !writeSockaddrResult(instance.memory(), addrPtr, addrlenPtr, (InetSocketAddress) local, h.family)) {
- return new long[] { -1L };
+
+ if (addressPointer != 0) {
+ if (!(socketAddress instanceof InetSocketAddress) ||
+ writeSockaddrResult(instance.memory(), addressPointer, addressLengthPointer, (InetSocketAddress) socketAddress, handle.addressFamily)) {
+ return new long[]{-1L};
}
}
-
- return new long[] { 0 };
- } catch (IOException e) {
- return new long[] { -1L };
+
+ return new long[]{0};
+ } catch (@NotNull IOException exception) {
+ return new long[]{-1L};
}
}));
-
- return env;
+
+ return environment;
}
-
-private static InetAddress getFallbackAddress(InetAddress addr) {
+
+ private static @Nullable InetAddress getFallbackAddress(@NotNull InetAddress address) {
try {
- byte[] raw = addr.getAddress();
- if (raw.length == 16) {
- // Check if it's an IPv4-mapped IPv6 (::ffff:x.x.x.x)
- if (isIpv4MappedIpv6(raw)) {
- return InetAddress.getByAddress(extractMappedIpv4(raw));
+ byte[] rawAddress = address.getAddress();
+ if (rawAddress.length == 16) {
+ // Check for an IPv4-mapped IPv6 address (::ffff:x.x.x.x)
+ if (isIpv4MappedIpv6(rawAddress)) {
+ return InetAddress.getByAddress(extractMappedIpv4(rawAddress));
}
-
- // Check for IPv6 ANY (::) -> Translate to IPv4 ANY (0.0.0.0)
- boolean isAny = true;
- for (byte b : raw) {
- if (b != 0) {
- isAny = false;
+
+ // Check for IPv6 wildcard address (::) and translate to IPv4 wildcard address (0.0.0.0)
+ boolean isWildcardAddress = true;
+ for (byte item : rawAddress) {
+ if (item != 0) {
+ isWildcardAddress = false;
break;
}
}
- if (isAny) {
+ if (isWildcardAddress) {
return InetAddress.getByAddress(new byte[]{0, 0, 0, 0});
}
-
- // Check for IPv6 Loopback (::1) -> Translate to IPv4 Loopback (127.0.0.1)
+
+ // Check for IPv6 loopback address (::1) and translate to to IPv4 loopback address (127.0.0.1)
boolean isLoopback = true;
for (int i = 0; i < 15; i++) {
- if (raw[i] != 0) {
+ if (rawAddress[i] != 0) {
isLoopback = false;
break;
}
}
- if (isLoopback && raw[15] == 1) {
+ if (isLoopback && rawAddress[15] == 1) {
return InetAddress.getByAddress(new byte[]{127, 0, 0, 1});
}
-
- } else if (raw.length == 4) {
+
+ } else if (rawAddress.length == 4) {
// Try promoting IPv4 up to IPv6 as a last resort
- return InetAddress.getByAddress(ipv4ToMappedIpv6(raw));
+ return InetAddress.getByAddress(ipv4ToMappedIpv6(rawAddress));
}
- } catch (UnknownHostException e) {
- // Ignore, will return null
+ } catch (@NotNull UnknownHostException ignored) {
}
return null;
}
-
- private static long[] doSend(Instance instance, int sockfd, int bufPtr, int len, int flags, int destAddrPtr, int addrlen) {
- SocketHandle h = sockets.get(sockfd);
- if (h == null) return new long[] { -1L };
+
+ private static long[] doSend(
+ Instance instance,
+ int socketFileDescriptor,
+ int destinationBufferPointer,
+ int desinationBufferLength,
+ @SuppressWarnings("unused") int flags,
+ int destinationAddressPointer,
+ int destinationAddressLength
+ ) {
+ @Nullable SocketHandle handle = sockets.get(socketFileDescriptor);
+ if (handle == null) return new long[]{-1L};
try {
- Memory mem = instance.memory();
- byte[] data = mem.readBytes(bufPtr, len);
- ByteBuffer buf = ByteBuffer.wrap(data);
-
- if (h.isUdp && h.datagramChannel != null) {
- if (destAddrPtr != 0) {
- int family = mem.readBytes(destAddrPtr, 1)[0] & 0xFF;
- int port = ((mem.readBytes(destAddrPtr + 2, 2)[0] & 0xFF) << 8) | (mem.readBytes(destAddrPtr + 2, 2)[1] & 0xFF);
- InetAddress addr = (family == AF_INET6 || addrlen == 28) ?
- InetAddress.getByAddress(mem.readBytes(destAddrPtr + 8, 16)) :
- InetAddress.getByAddress(mem.readBytes(destAddrPtr + 4, 4));
- int sent = h.datagramChannel.send(buf, new InetSocketAddress(addr, port));
- return new long[] { sent };
+ @NotNull Memory memory = instance.memory();
+ byte[] data = memory.readBytes(destinationBufferPointer, desinationBufferLength);
+ @NotNull ByteBuffer buf = ByteBuffer.wrap(data);
+
+ if (handle.isUdp && handle.datagramChannel != null) {
+ if (destinationAddressPointer != 0) {
+ int addressFamily = memory.readBytes(destinationAddressPointer, 1)[0] & 0xFF;
+ int port = ((memory.readBytes(destinationAddressPointer + 2, 2)[0] & 0xFF) << 8) | (memory.readBytes(destinationAddressPointer + 2, 2)[1] & 0xFF);
+ @NotNull InetAddress addr = (addressFamily == AF_INET6 || destinationAddressLength == 28) ?
+ InetAddress.getByAddress(memory.readBytes(destinationAddressPointer + 8, 16)) :
+ InetAddress.getByAddress(memory.readBytes(destinationAddressPointer + 4, 4));
+ int sent = handle.datagramChannel.send(buf, new InetSocketAddress(addr, port));
+ return new long[]{sent};
} else {
- return new long[] { h.datagramChannel.write(buf) };
+ return new long[]{handle.datagramChannel.write(buf)};
}
- } else if (h.socketChannel != null) {
- return new long[] { h.socketChannel.write(buf) };
+ } else if (handle.socketChannel != null) {
+ return new long[]{handle.socketChannel.write(buf)};
}
- return new long[] { -1L };
- } catch (IOException e) {
- return new long[] { -1L };
+ return new long[]{-1L};
+ } catch (@NotNull IOException exception) {
+ return new long[]{-1L};
}
}
-
+
// Dynamic address structure promotion mapped securely to guest memory buffers
- private static long[] doRecv(Instance instance, int sockfd, int bufPtr, int len, int flags, int srcAddrPtr, int addrlenPtr) {
- SocketHandle h = sockets.get(sockfd);
- if (h == null) return new long[] { -1L };
-
+ private static long[] doRecv(
+ @NotNull Instance instance,
+ int socketFileDescriptor,
+ int destinationBufferPointer,
+ int desinationBufferLength,
+ @SuppressWarnings("unused") int flags,
+ int sourceAddressPointer,
+ int sourceAddressLength
+ ) {
+ @Nullable SocketHandle handle = sockets.get(socketFileDescriptor);
+ if (handle == null) return new long[]{-1L};
+
// POSIX ABI: if src_addr != NULL, addrlen must be a valid value-result pointer.
- if (srcAddrPtr != 0 && addrlenPtr == 0) {
- return new long[] { -1L };
+ if (sourceAddressPointer != 0 && sourceAddressLength == 0) {
+ return new long[]{-1L};
}
-
+
try {
- Memory mem = instance.memory();
- ByteBuffer buf = ByteBuffer.allocate(len);
-
- if (h.isUdp && h.datagramChannel != null) {
- SocketAddress sender = h.datagramChannel.receive(buf);
+ @NotNull Memory memory = instance.memory();
+ @NotNull ByteBuffer buffer = ByteBuffer.allocate(desinationBufferLength);
+
+ if (handle.isUdp && handle.datagramChannel != null) {
+ SocketAddress sender = handle.datagramChannel.receive(buffer);
if (sender == null) {
- return new long[] { -1L };
+ return new long[]{-1L};
}
-
- buf.flip();
- mem.write(bufPtr, Arrays.copyOf(buf.array(), buf.limit()));
-
- if (srcAddrPtr != 0) {
+
+ buffer.flip();
+ memory.write(destinationBufferPointer, Arrays.copyOf(buffer.array(), buffer.limit()));
+
+ if (sourceAddressPointer != 0) {
if (!(sender instanceof InetSocketAddress) ||
- !writeSockaddrResult(mem, srcAddrPtr, addrlenPtr, (InetSocketAddress) sender, h.family)) {
- return new long[] { -1L };
+ writeSockaddrResult(memory, sourceAddressPointer, sourceAddressLength, (InetSocketAddress) sender, handle.addressFamily)) {
+ return new long[]{-1L};
}
}
-
- return new long[] { buf.limit() };
- } else if (h.socketChannel != null) {
- int read = h.socketChannel.read(buf);
+
+ return new long[]{buffer.limit()};
+ } else if (handle.socketChannel != null) {
+ int read = handle.socketChannel.read(buffer);
if (read > 0) {
- mem.write(bufPtr, Arrays.copyOf(buf.array(), read));
- return new long[] { read };
+ memory.write(destinationBufferPointer, Arrays.copyOf(buffer.array(), read));
+ return new long[]{read};
}
- return new long[] { read == -1 ? 0 : -1L };
+ return new long[]{read == -1 ? 0 : -1L};
}
-
- return new long[] { -1L };
- } catch (IOException e) {
- return new long[] { -1L };
+
+ return new long[]{-1L};
+ } catch (@NotNull IOException exception) {
+ return new long[]{-1L};
}
}
-
- private static long[] closeHandle(int fd) {
- SocketHandle h = sockets.remove(fd);
- if (h != null) {
- try { if (h.serverChannel != null) h.serverChannel.close(); } catch (IOException e) {}
- try { if (h.datagramChannel != null) h.datagramChannel.close(); } catch (IOException e) {}
- try { if (h.socketChannel != null) h.socketChannel.close(); } catch (IOException e) {}
+
+ private static long[] closeHandle(int handleID) {
+ @Nullable SocketHandle handle = sockets.remove(handleID);
+ if (handle != null) {
+ try {
+ if (handle.serverChannel != null) handle.serverChannel.close();
+ } catch (@NotNull IOException ignored) {
+ }
+ try {
+ if (handle.datagramChannel != null) handle.datagramChannel.close();
+ } catch (@NotNull IOException ignored) {
+ }
+ try {
+ if (handle.socketChannel != null) handle.socketChannel.close();
+ } catch (@NotNull IOException ignored) {
+ }
}
- return new long[] { 0 };
+ return new long[]{0};
}
-
- private static List params(int count) {
- List res = new ArrayList<>(count);
+
+ private static @NotNull List<@NotNull ValueType> params(int count) {
+ @NotNull List<@NotNull ValueType> res = new ArrayList<>(count);
for (int i = 0; i < count; i++) res.add(ValueType.I32);
return res;
}
-
- private static List returns(int count) {
+
+ private static @NotNull List<@NotNull ValueType> returns(int count) {
return count == 0 ? List.of() : List.of(ValueType.I32);
}
-
- private static void writeIntLE(Memory mem, int offset, int val) {
- mem.write(offset, new byte[] {
+
+ private static void writeIntLE(@NotNull Memory mem, int offset, int val) {
+ mem.write(offset, new byte[]{
(byte) val, (byte) (val >> 8), (byte) (val >> 16), (byte) (val >> 24)
});
}
-
- private static int readIntLE(Memory mem, int offset) {
+
+ private static int readIntLE(@NotNull Memory mem, int offset) {
byte[] b = mem.readBytes(offset, 4);
return (b[0] & 0xFF) | ((b[1] & 0xFF) << 8) | ((b[2] & 0xFF) << 16) | ((b[3] & 0xFF) << 24);
}
-
- private static long readLongLE(Memory mem, int offset) {
+
+ private static long readLongLE(@NotNull Memory mem, int offset) {
byte[] b = mem.readBytes(offset, 8);
long res = 0;
for (int i = 0; i < 8; i++) {
@@ -972,8 +1004,8 @@ private static long readLongLE(Memory mem, int offset) {
}
return res;
}
-
- private static String readNullTerminatedString(Memory mem, int offset) {
+
+ private static @NotNull String readNullTerminatedString(@NotNull Memory mem, int offset) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int curr = offset;
while (true) {
@@ -983,351 +1015,350 @@ private static String readNullTerminatedString(Memory mem, int offset) {
}
return baos.toString(StandardCharsets.UTF_8);
}
-
- private static final class SockProtoPair {
- final int socktype;
- final int protocol;
-
- SockProtoPair(int socktype, int protocol) {
- this.socktype = socktype;
- this.protocol = protocol;
- }
+
+ private record SockProtoPair(int socketType, int protocol) {
}
-
- private static final class AddrInfoResult {
- final int family;
- final int socktype;
- final int protocol;
- final byte[] sockaddr;
- final String canonName;
-
- AddrInfoResult(int family, int socktype, int protocol, byte[] sockaddr, String canonName) {
- this.family = family;
- this.socktype = socktype;
- this.protocol = protocol;
- this.sockaddr = sockaddr;
- this.canonName = canonName;
- }
+
+ private record AddrInfoResult(
+ int addressFamily,
+ int socketType,
+ int protocol,
+ byte @NotNull [] socketAddress,
+ @NotNull String canonicalName
+ ) {
}
-
- private static ExportFunction findExport(Instance instance, String primary, String fallback) {
- ExportFunction fn = instance.export(primary);
- return fn != null ? fn : instance.export(fallback);
+
+ private static @Nullable ExportFunction findExport(@NotNull Instance instance, @NotNull String primary, @NotNull String fallback) {
+ @Nullable ExportFunction function = instance.export(primary);
+ return function != null ? function : instance.export(fallback);
}
-
- private static int guestMalloc(ExportFunction malloc, int size) {
+
+ private static int guestMalloc(@NotNull ExportFunction malloc, int size) {
return (int) malloc.apply(size)[0];
}
-
- private static void putU16LE(byte[] out, int off, int v) {
- out[off] = (byte) (v & 0xFF);
- out[off + 1] = (byte) ((v >>> 8) & 0xFF);
+
+ private static void putU16LE(byte[] buffer, @SuppressWarnings("SameParameterValue") int offset, int value) {
+ buffer[offset] = (byte) (value & 0xFF);
+ buffer[offset + 1] = (byte) ((value >>> 8) & 0xFF);
}
-
- private static void putU16BE(byte[] out, int off, int v) {
- out[off] = (byte) ((v >>> 8) & 0xFF);
- out[off + 1] = (byte) (v & 0xFF);
+
+ private static void putU16BE(byte[] buffer, @SuppressWarnings("SameParameterValue") int offset, int value) {
+ buffer[offset] = (byte) ((value >>> 8) & 0xFF);
+ buffer[offset + 1] = (byte) (value & 0xFF);
}
-
- private static void putIntLE(byte[] out, int off, int v) {
- out[off] = (byte) (v & 0xFF);
- out[off + 1] = (byte) ((v >>> 8) & 0xFF);
- out[off + 2] = (byte) ((v >>> 16) & 0xFF);
- out[off + 3] = (byte) ((v >>> 24) & 0xFF);
+
+ private static void putIntLE(byte[] buffer, int offset, int value) {
+ buffer[offset] = (byte) (value & 0xFF);
+ buffer[offset + 1] = (byte) ((value >>> 8) & 0xFF);
+ buffer[offset + 2] = (byte) ((value >>> 16) & 0xFF);
+ buffer[offset + 3] = (byte) ((value >>> 24) & 0xFF);
}
-
- private static byte[] ipv4ToMappedIpv6(byte[] v4) {
- byte[] out = new byte[16];
- out[10] = (byte) 0xFF;
- out[11] = (byte) 0xFF;
- System.arraycopy(v4, 0, out, 12, 4);
- return out;
+
+ private static byte @NotNull [] ipv4ToMappedIpv6(byte[] address) {
+ byte[] returnValue = new byte[16];
+ returnValue[10] = (byte) 0xFF;
+ returnValue[11] = (byte) 0xFF;
+ System.arraycopy(address, 0, returnValue, 12, 4);
+ return returnValue;
}
-
- private static boolean isIpv4MappedIpv6(byte[] v6) {
- if (v6 == null || v6.length != 16) return false;
- for (int i = 0; i < 10; i++) {
- if (v6[i] != 0) return false;
+
+ private static boolean isIpv4MappedIpv6(byte[] address) {
+ if (address == null || address.length != 16) return false;
+ for (int index = 0; index < 10; index++) {
+ if (address[index] != 0) return false;
}
- return v6[10] == (byte) 0xFF && v6[11] == (byte) 0xFF;
+ return address[10] == (byte) 0xFF && address[11] == (byte) 0xFF;
}
-
- private static byte[] extractMappedIpv4(byte[] v6) {
- return Arrays.copyOfRange(v6, 12, 16);
+
+ private static byte @NotNull [] extractMappedIpv4(byte @NotNull [] address) {
+ return Arrays.copyOfRange(address, 12, 16);
}
-
- private static byte[] encodeSockaddr(int family, byte[] addr, int port, int scopeId) {
- if (family == AF_INET) {
- if (addr.length != 4) throw new IllegalArgumentException("AF_INET requires 4 bytes");
- byte[] out = new byte[SOCKADDR_IN_LEN];
+
+ private static byte @NotNull [] encodeSockaddr(int addressFamily, byte @NotNull [] address, int port, int scopeId) {
+ if (addressFamily == AF_INET) {
+ if (address.length != 4) throw new IllegalArgumentException("AF_INET requires 4 bytes");
+ byte @NotNull [] out = new byte[SOCKADDR_IN_LEN];
putU16LE(out, 0, AF_INET);
putU16BE(out, 2, port);
- System.arraycopy(addr, 0, out, 4, 4);
+ System.arraycopy(address, 0, out, 4, 4);
return out;
}
-
- if (family == AF_INET6) {
- if (addr.length != 16) throw new IllegalArgumentException("AF_INET6 requires 16 bytes");
- byte[] out = new byte[SOCKADDR_IN6_LEN];
+
+ if (addressFamily == AF_INET6) {
+ if (address.length != 16) throw new IllegalArgumentException("AF_INET6 requires 16 bytes");
+ byte @NotNull [] out = new byte[SOCKADDR_IN6_LEN];
putU16LE(out, 0, AF_INET6);
putU16BE(out, 2, port);
putIntLE(out, 4, 0); // flowinfo
- System.arraycopy(addr, 0, out, 8, 16);
+ System.arraycopy(address, 0, out, 8, 16);
putIntLE(out, 24, scopeId);
return out;
}
-
- throw new IllegalArgumentException("unsupported family: " + family);
+
+ throw new IllegalArgumentException("Unsupported address family '" + addressFamily + "'");
}
-
- private static boolean writeSockaddrResult(Memory mem, int addrPtr, int addrlenPtr, InetSocketAddress remote, int socketFamily) {
- if (addrPtr == 0) {
- return true;
- }
- if (addrlenPtr == 0) {
+
+ private static boolean writeSockaddrResult(
+ @NotNull Memory memory,
+ int addressPointer,
+ int addressLength,
+ @NotNull InetSocketAddress remoteAddress,
+ int socketFamily
+ ) {
+ if (addressPointer == 0) {
return false;
}
-
- InetAddress inet = remote.getAddress();
+ if (addressLength == 0) {
+ return true;
+ }
+
+ @NotNull InetAddress inet = remoteAddress.getAddress();
if (inet == null) {
- return false;
+ return true;
}
-
- byte[] raw = inet.getAddress();
- int family;
+
+ byte[] rawAddress = inet.getAddress();
+ int addressFamily;
int scopeId = 0;
-
+
if (socketFamily == AF_INET6) {
- family = AF_INET6;
- if (raw.length == 4) {
- raw = ipv4ToMappedIpv6(raw);
+ addressFamily = AF_INET6;
+ if (rawAddress.length == 4) {
+ rawAddress = ipv4ToMappedIpv6(rawAddress);
}
if (inet instanceof Inet6Address) {
scopeId = ((Inet6Address) inet).getScopeId();
}
} else {
- family = AF_INET;
- if (raw.length == 16) {
- if (!isIpv4MappedIpv6(raw)) {
- return false;
+ addressFamily = AF_INET;
+ if (rawAddress.length == 16) {
+ if (!isIpv4MappedIpv6(rawAddress)) {
+ return true;
}
- raw = extractMappedIpv4(raw);
+ rawAddress = extractMappedIpv4(rawAddress);
}
}
-
- byte[] sockaddr = encodeSockaddr(family, raw, remote.getPort(), scopeId);
- int callerLen = Math.max(0, readIntLE(mem, addrlenPtr));
- int copyLen = Math.min(callerLen, sockaddr.length);
-
- if (copyLen > 0) {
- mem.write(addrPtr, Arrays.copyOf(sockaddr, copyLen));
+
+ byte @NotNull [] socketAddress = encodeSockaddr(addressFamily, rawAddress, remoteAddress.getPort(), scopeId);
+ int callerLength = Math.max(0, readIntLE(memory, addressLength));
+ int copyLength = Math.min(callerLength, socketAddress.length);
+
+ if (copyLength > 0) {
+ memory.write(addressPointer, Arrays.copyOf(socketAddress, copyLength));
}
- writeIntLE(mem, addrlenPtr, sockaddr.length);
- return true;
+ writeIntLE(memory, addressLength, socketAddress.length);
+ return false;
}
-
- private static Integer parseNumericService(String s) {
- if (s == null || s.isEmpty()) return null;
- for (int i = 0; i < s.length(); i++) {
- if (!Character.isDigit(s.charAt(i))) return null;
+
+ private static @Nullable Integer parseNumericService(@Nullable String string) {
+ if (string == null || string.isEmpty()) return null;
+ for (int i = 0; i < string.length(); i++) {
+ if (!Character.isDigit(string.charAt(i))) return null;
}
try {
- int port = Integer.parseInt(s);
+ int port = Integer.parseInt(string);
return (port >= 0 && port <= 65535) ? port : null;
} catch (NumberFormatException e) {
return null;
}
}
-
- private static int hexValue(char c) {
- if (c >= '0' && c <= '9') return c - '0';
- if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
- if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
+
+ private static int hexValue(char character) {
+ if (character >= '0' && character <= '9') return character - '0';
+ if (character >= 'a' && character <= 'f') return 10 + (character - 'a');
+ if (character >= 'A' && character <= 'F') return 10 + (character - 'A');
return -1;
}
-
- private static byte[] parseIpv4Literal(String s) {
- if (s == null || s.isEmpty()) return null;
- String[] parts = s.split("\\.", -1);
+
+ private static byte[] parseIpv4Literal(@Nullable String string) {
+ if (string == null || string.isEmpty()) return null;
+ @NotNull String @NotNull [] parts = string.split("\\.", -1);
if (parts.length != 4) return null;
-
- byte[] out = new byte[4];
- for (int i = 0; i < 4; i++) {
- String p = parts[i];
- if (p.isEmpty() || p.length() > 3) return null;
- int v = 0;
- for (int j = 0; j < p.length(); j++) {
- char c = p.charAt(j);
- if (!Character.isDigit(c)) return null;
- v = (v * 10) + (c - '0');
+
+ byte @NotNull [] returnValue = new byte[4];
+ for (int index = 0; index < 4; index++) {
+ @NotNull String part = parts[index];
+ if (part.isEmpty() || part.length() > 3) return null;
+ int value = 0;
+ for (int partIndex = 0; partIndex < part.length(); partIndex++) {
+ char character = part.charAt(partIndex);
+ if (!Character.isDigit(character)) return null;
+ value = (value * 10) + (character - '0');
}
- if (v < 0 || v > 255) return null;
- out[i] = (byte) v;
+ if (value < 0 || value > 255) return null;
+ returnValue[index] = (byte) value;
}
- return out;
+ return returnValue;
}
-
- private static List parseIpv6Section(String part, boolean allowIpv4Tail) {
- List words = new ArrayList<>();
+
+ private static @Nullable List<@NotNull Integer> parseIpv6Section(@NotNull String part, boolean allowIpv4Tail) {
+ @NotNull List<@NotNull Integer> words = new ArrayList<>();
if (part.isEmpty()) return words;
-
+
String[] tokens = part.split(":", -1);
- for (int i = 0; i < tokens.length; i++) {
- String token = tokens[i];
+ for (int index = 0; index < tokens.length; index++) {
+ @NotNull String token = tokens[index];
if (token.isEmpty()) return null;
-
+
if (token.indexOf('.') >= 0) {
- if (!allowIpv4Tail || i != tokens.length - 1) return null;
- byte[] v4 = parseIpv4Literal(token);
- if (v4 == null) return null;
- words.add(((v4[0] & 0xFF) << 8) | (v4[1] & 0xFF));
- words.add(((v4[2] & 0xFF) << 8) | (v4[3] & 0xFF));
+ if (!allowIpv4Tail || index != tokens.length - 1) return null;
+ byte @NotNull [] address = parseIpv4Literal(token);
+ if (address == null) return null;
+ words.add(((address[0] & 0xFF) << 8) | (address[1] & 0xFF));
+ words.add(((address[2] & 0xFF) << 8) | (address[3] & 0xFF));
} else {
if (token.length() > 4) return null;
int value = 0;
- for (int j = 0; j < token.length(); j++) {
- int hv = hexValue(token.charAt(j));
- if (hv < 0) return null;
- value = (value << 4) | hv;
+ for (int tokenIndex = 0; tokenIndex < token.length(); tokenIndex++) {
+ int hexValue = hexValue(token.charAt(tokenIndex));
+ if (hexValue < 0) return null;
+ value = (value << 4) | hexValue;
}
words.add(value);
}
}
-
+
return words;
}
-
- private static byte[] parseIpv6Literal(String s) {
- if (s == null || s.isEmpty()) return null;
- if (s.indexOf('%') >= 0) return null; // inet_pton does not accept zone ids
-
- String[] halves = s.split("::", -1);
+
+ private static byte @Nullable [] parseIpv6Literal(@Nullable String string) {
+ if (string == null || string.isEmpty()) return null;
+ if (string.indexOf('%') >= 0) return null; // inet_pton does not accept zone ids
+
+ @NotNull String @NotNull [] halves = string.split("::", -1);
if (halves.length > 2) return null;
-
- List words = new ArrayList<>(8);
-
+
+ @NotNull List<@NotNull Integer> words = new ArrayList<>(8);
+
if (halves.length == 1) {
- List all = parseIpv6Section(s, true);
+ @Nullable List<@NotNull Integer> all = parseIpv6Section(string, true);
if (all == null || all.size() != 8) return null;
words.addAll(all);
} else {
- List left = parseIpv6Section(halves[0], false);
- List right = parseIpv6Section(halves[1], true);
+ @Nullable List<@NotNull Integer> left = parseIpv6Section(halves[0], false);
+ @Nullable List<@NotNull Integer> right = parseIpv6Section(halves[1], true);
if (left == null || right == null) return null;
-
+
int zeros = 8 - (left.size() + right.size());
if (zeros < 1) return null;
-
+
words.addAll(left);
for (int i = 0; i < zeros; i++) words.add(0);
words.addAll(right);
}
-
+
if (words.size() != 8) return null;
-
- byte[] out = new byte[16];
- for (int i = 0; i < 8; i++) {
- int w = words.get(i);
- out[i * 2] = (byte) ((w >>> 8) & 0xFF);
- out[i * 2 + 1] = (byte) (w & 0xFF);
+
+ byte[] returnValue = new byte[16];
+ for (int index = 0; index < 8; index++) {
+ int word = words.get(index);
+ returnValue[index * 2] = (byte) ((word >>> 8) & 0xFF);
+ returnValue[index * 2 + 1] = (byte) (word & 0xFF);
}
- return out;
+ return returnValue;
}
-
- private static List defaultAddressesForNullNode(int family, boolean passive) throws UnknownHostException {
- List out = new ArrayList<>();
-
- if (family == AF_UNSPEC || family == AF_INET6) {
- byte[] v6 = new byte[16];
- if (!passive) v6[15] = 1; // ::1
- out.add(InetAddress.getByAddress(v6));
+
+ private static @NotNull List<@NotNull InetAddress> defaultAddressesForNullNode(
+ int addressFamily,
+ boolean passive
+ ) throws UnknownHostException {
+ @NotNull List<@NotNull InetAddress> returnValue = new ArrayList<>();
+
+ if (addressFamily == AF_UNSPEC || addressFamily == AF_INET6) {
+ byte[] address = new byte[16];
+ if (!passive) address[15] = 1; // ::1
+ returnValue.add(InetAddress.getByAddress(address));
}
-
- if (family == AF_UNSPEC || family == AF_INET) {
- byte[] v4 = passive ? new byte[] {0, 0, 0, 0} : new byte[] {127, 0, 0, 1};
- out.add(InetAddress.getByAddress(v4));
+
+ if (addressFamily == AF_UNSPEC || addressFamily == AF_INET) {
+ byte[] address = passive ? new byte[]{0, 0, 0, 0} : new byte[]{127, 0, 0, 1};
+ returnValue.add(InetAddress.getByAddress(address));
}
-
- return out;
+
+ return returnValue;
}
-
- private static List resolveNumericNode(String node, int family, int flags, byte[] v4, byte[] v6)
- throws UnknownHostException {
- List out = new ArrayList<>();
-
- if (v4 != null) {
- if (family == AF_UNSPEC || family == AF_INET) {
- out.add(InetAddress.getByAddress(v4));
- } else if (family == AF_INET6 && (flags & AI_V4MAPPED) != 0) {
- out.add(InetAddress.getByAddress(ipv4ToMappedIpv6(v4)));
+
+ private static @NotNull List<@NotNull InetAddress> resolveNumericNode(
+ int addressFamily,
+ int flags,
+ byte @Nullable [] v4Address,
+ byte @Nullable [] v6Address
+ ) throws UnknownHostException {
+ List returnValue = new ArrayList<>();
+
+ if (v4Address != null) {
+ if (addressFamily == AF_UNSPEC || addressFamily == AF_INET) {
+ returnValue.add(InetAddress.getByAddress(v4Address));
+ } else if (addressFamily == AF_INET6 && (flags & AI_V4MAPPED) != 0) {
+ returnValue.add(InetAddress.getByAddress(ipv4ToMappedIpv6(v4Address)));
}
- return out;
+ return returnValue;
}
-
- if (v6 != null) {
- if (family == AF_UNSPEC || family == AF_INET6) {
- out.add(InetAddress.getByAddress(v6));
+
+ if (v6Address != null) {
+ if (addressFamily == AF_UNSPEC || addressFamily == AF_INET6) {
+ returnValue.add(InetAddress.getByAddress(v6Address));
}
}
-
- return out;
+
+ return returnValue;
}
-
- private static List resolveDnsNode(String node, int family, int flags) throws UnknownHostException {
- InetAddress[] resolved = InetAddress.getAllByName(node);
-
- List v4 = new ArrayList<>();
- List v6 = new ArrayList<>();
- for (InetAddress addr : resolved) {
- if (addr.getAddress().length == 16) v6.add(addr);
- else v4.add(addr);
+
+ private static @NotNull List<@NotNull InetAddress> resolveDnsNode(@NotNull String node, int addressFamily, int flags) throws UnknownHostException {
+ InetAddress[] resolvedAddresses = InetAddress.getAllByName(node);
+
+ List v4Address = new ArrayList<>();
+ List v6Address = new ArrayList<>();
+ for (InetAddress address : resolvedAddresses) {
+ if (address.getAddress().length == 16) v6Address.add(address);
+ else v4Address.add(address);
}
-
- List out = new ArrayList<>();
-
- if (family == AF_UNSPEC) {
- out.addAll(Arrays.asList(resolved));
- return out;
+
+ List returnValue = new ArrayList<>();
+
+ if (addressFamily == AF_UNSPEC) {
+ returnValue.addAll(Arrays.asList(resolvedAddresses));
+ return returnValue;
}
-
- if (family == AF_INET) {
- out.addAll(v4);
- return out;
+
+ if (addressFamily == AF_INET) {
+ returnValue.addAll(v4Address);
+ return returnValue;
}
-
+
// AF_INET6
- out.addAll(v6);
- if ((flags & AI_V4MAPPED) != 0 && (((flags & AI_ALL) != 0) || v6.isEmpty())) {
- for (InetAddress a : v4) {
- out.add(InetAddress.getByAddress(ipv4ToMappedIpv6(a.getAddress())));
+ returnValue.addAll(v6Address);
+ if ((flags & AI_V4MAPPED) != 0 && (((flags & AI_ALL) != 0) || v6Address.isEmpty())) {
+ for (@NotNull InetAddress a : v4Address) {
+ returnValue.add(InetAddress.getByAddress(ipv4ToMappedIpv6(a.getAddress())));
}
}
- return out;
+ return returnValue;
}
-
- private static List buildSockProtoPairs(int socktype, int protocol) {
- List out = new ArrayList<>();
-
+
+ private static @NotNull List<@NotNull SockProtoPair> buildSockProtoPairs(int socktype, int protocol) {
+ @NotNull List<@NotNull SockProtoPair> returnValue = new ArrayList<>();
+
if (socktype == 0) {
if (protocol == 0 || protocol == IPPROTO_TCP) {
- out.add(new SockProtoPair(SOCK_STREAM, IPPROTO_TCP));
+ returnValue.add(new SockProtoPair(SOCK_STREAM, IPPROTO_TCP));
}
if (protocol == 0 || protocol == IPPROTO_UDP) {
- out.add(new SockProtoPair(SOCK_DGRAM, IPPROTO_UDP));
+ returnValue.add(new SockProtoPair(SOCK_DGRAM, IPPROTO_UDP));
}
- return out;
+ return returnValue;
}
-
+
if (socktype == SOCK_STREAM) {
- out.add(new SockProtoPair(SOCK_STREAM, IPPROTO_TCP));
- return out;
+ returnValue.add(new SockProtoPair(SOCK_STREAM, IPPROTO_TCP));
+ return returnValue;
}
-
+
if (socktype == SOCK_DGRAM) {
- out.add(new SockProtoPair(SOCK_DGRAM, IPPROTO_UDP));
- return out;
+ returnValue.add(new SockProtoPair(SOCK_DGRAM, IPPROTO_UDP));
+ return returnValue;
}
-
- return out;
+
+ return returnValue;
}
}
diff --git a/WASMImpl/Java/src/main/luxon_server.wasm b/WASMImpl/Java/src/main/luxon_server.wasm
deleted file mode 100644
index e69de29..0000000