Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 44 additions & 26 deletions src/main/java/io/roastedroot/proxywasm/ABI.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.roastedroot.proxywasm;

import static io.roastedroot.proxywasm.Helpers.bytes;
import static io.roastedroot.proxywasm.Helpers.replaceBytes;
import static io.roastedroot.proxywasm.Helpers.split;
import static io.roastedroot.proxywasm.Helpers.string;

import com.dylibso.chicory.experimental.hostmodule.annotations.HostModule;
Expand All @@ -11,7 +13,7 @@
import com.dylibso.chicory.runtime.WasmRuntimeException;
import com.dylibso.chicory.wasm.InvalidException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

@HostModule("env")
Expand Down Expand Up @@ -221,15 +223,6 @@ private byte[] readMemory(int address, int len) throws WasmException {
}
}

private String readString(int address, int len) throws WasmException {
var data = readMemory(address, len);
return new String(data, StandardCharsets.UTF_8);
}

private void copyIntoInstance(String value, int retPtr, int retSize) throws WasmException {
copyIntoInstance(value.getBytes(), retPtr, retSize);
}

private void copyIntoInstance(byte[] value, int retPtr, int retSize) throws WasmException {
try {
if (value.length != 0) {
Expand Down Expand Up @@ -402,7 +395,7 @@ boolean proxyOnConfigure(int arg0, int arg1) {
int proxyLog(int logLevel, int messageData, int messageSize) {
try {
var msg = memory.readBytes(messageData, messageSize);
handler.log(LogLevel.fromInt(logLevel), new String(msg));
handler.log(LogLevel.fromInt(logLevel), string(msg));
return WasmResult.OK.getValue();
} catch (WasmException e) {
return e.result().getValue();
Expand Down Expand Up @@ -840,7 +833,7 @@ int proxyGetHeaderMapValue(
}

// Get key from memory
String key = readString(keyDataPtr, keySize);
String key = string(readMemory(keyDataPtr, keySize));

// Get value from map
String value = headerMap.get(key);
Expand All @@ -849,7 +842,7 @@ int proxyGetHeaderMapValue(
}

// Copy value into WebAssembly memory
copyIntoInstance(value, valueDataPtr, valueSize);
copyIntoInstance(bytes(value), valueDataPtr, valueSize);
return WasmResult.OK.getValue();

} catch (WasmRuntimeException e) {
Expand Down Expand Up @@ -898,10 +891,10 @@ int proxyReplaceHeaderMapValue(
}

// Get key from memory
String key = readString(keyDataPtr, keySize);
String key = string(readMemory(keyDataPtr, keySize));

// Get value from memory
String value = readString(valueDataPtr, valueSize);
String value = string(readMemory(valueDataPtr, valueSize));

// Replace value in map
var copy = new ArrayProxyMap(headerMap);
Expand Down Expand Up @@ -936,7 +929,7 @@ int proxyRemoveHeaderMapValue(int mapType, int keyDataPtr, int keySize) {
}

// Get key from memory
String key = readString(keyDataPtr, keySize);
String key = string(readMemory(keyDataPtr, keySize));
if (key.isEmpty()) {
return WasmResult.BAD_ARGUMENT.getValue();
}
Expand Down Expand Up @@ -1075,11 +1068,11 @@ private ProxyMap decodeMap(int addr, int mem_size) throws WasmException {
}

// Extract key
String key = readString((int) (addr + dataOffset), (int) keySize);
String key = string(readMemory((int) (addr + dataOffset), (int) keySize));
dataOffset += keySize + 1; // Skip null terminator

// Extract value
String value = readString((int) (addr + dataOffset), (int) valueSize);
String value = string(readMemory((int) (addr + dataOffset), (int) valueSize));
dataOffset += valueSize + 1;

// Add to result map
Expand Down Expand Up @@ -1620,7 +1613,18 @@ int proxyGetSharedData(
return WasmResult.NOT_FOUND.getValue();
}

copyIntoInstance(value.data, returnValueData, returnValueSize);
try {
if (value.data.length != 0) {
int addr = malloc(value.data.length);
putMemory(addr, value.data);
putUint32(returnValueData, addr);
} else {
putUint32(returnValueData, 0);
}
putUint32(returnValueSize, value.data.length);
} catch (WasmException e) {
throw new WasmException(WasmResult.INVALID_MEMORY_ACCESS);
}
putUint32(returnCas, value.cas);
return WasmResult.OK.getValue();

Expand All @@ -1642,10 +1646,13 @@ int proxyRegisterSharedQueue(int queueNameDataPtr, int queueNameSize, int return
// Get queue name from memory
String queueName = string(readMemory(queueNameDataPtr, queueNameSize));

var vmId = handler.getProperty("vm_id");
var vmId = handler.getProperty(List.of("vm_id"));
if (vmId == null) {
return WasmResult.INTERNAL_FAILURE.getValue();
}

// Register shared queue using handler
int queueId = handler.registerSharedQueue(new QueueName(vmId, queueName));
int queueId = handler.registerSharedQueue(new QueueName(string(vmId), queueName));
putUint32(returnQueueId, queueId);
return WasmResult.OK.getValue();

Expand Down Expand Up @@ -1710,7 +1717,18 @@ int proxyDequeueSharedQueue(int queueId, int returnValueData, int returnValueSiz
return WasmResult.EMPTY.getValue();
}

copyIntoInstance(value, returnValueData, returnValueSize);
try {
if (value.length != 0) {
int addr = malloc(value.length);
putMemory(addr, value);
putUint32(returnValueData, addr);
} else {
putUint32(returnValueData, 0);
}
putUint32(returnValueSize, value.length);
} catch (WasmException e) {
throw new WasmException(WasmResult.INVALID_MEMORY_ACCESS);
}
return WasmResult.OK.getValue();

} catch (WasmException e) {
Expand Down Expand Up @@ -1811,10 +1829,10 @@ int proxyGetProperty(int keyPtr, int keySize, int returnValueData, int returnVal
return WasmResult.BAD_ARGUMENT.getValue();
}

String key = new String(keyBytes);
var path = split(string(keyBytes), '\u0000');

// Get property value using handler
String value = handler.getProperty(key);
byte[] value = handler.getProperty(path);
if (value == null) {
return WasmResult.NOT_FOUND.getValue();
}
Expand All @@ -1834,10 +1852,10 @@ int proxyGetProperty(int keyPtr, int keySize, int returnValueData, int returnVal
int proxySetProperty(int pathDataPtr, int pathSize, int valueDataPtr, int valueSize) {
try {
// Get key from memory
String path = string(readMemory(pathDataPtr, pathSize));
var path = split(string(readMemory(pathDataPtr, pathSize)), '\u0000');

// Get value from memory
String value = string(readMemory(valueDataPtr, valueSize));
var value = readMemory(valueDataPtr, valueSize);

// Set property value using handler
WasmResult result = handler.setProperty(path, value);
Expand Down
14 changes: 8 additions & 6 deletions src/main/java/io/roastedroot/proxywasm/ChainedHandler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.roastedroot.proxywasm;

import java.util.List;

/**
* A Handler implementation that chains to another handler if it can't handle the request.
*/
Expand Down Expand Up @@ -103,10 +105,15 @@ public WasmResult setGrpcReceiveTrailerMetaData(ProxyMap metadata) {
}

@Override
public String getProperty(String key) throws WasmException {
public byte[] getProperty(List<String> key) throws WasmException {
return next().getProperty(key);
}

@Override
public WasmResult setProperty(List<String> path, byte[] value) {
return next().setProperty(path, value);
}

@Override
public byte[] getHttpRequestBody() {
return next().getHttpRequestBody();
Expand Down Expand Up @@ -324,11 +331,6 @@ public LogLevel getLogLevel() throws WasmException {
return next().getLogLevel();
}

@Override
public WasmResult setProperty(String path, String value) {
return next().setProperty(path, value);
}

@Override
public int grpcCall(
String upstreamName,
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/io/roastedroot/proxywasm/Handler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.roastedroot.proxywasm;

import java.util.List;

public interface Handler {

default void log(LogLevel level, String message) throws WasmException {}
Expand Down Expand Up @@ -45,11 +47,11 @@ default ProxyMap getCustomHeaders(int mapType) {
return null;
}

default String getProperty(String key) throws WasmException {
default byte[] getProperty(List<String> key) throws WasmException {
return null;
}

default WasmResult setProperty(String path, String value) {
default WasmResult setProperty(List<String> path, byte[] value) {
return WasmResult.UNIMPLEMENTED;
}

Expand Down
16 changes: 16 additions & 0 deletions src/main/java/io/roastedroot/proxywasm/Helpers.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.dylibso.chicory.runtime.HostFunction;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public final class Helpers {
Expand Down Expand Up @@ -30,6 +32,20 @@ public static String string(byte[] value) {
return new String(value, StandardCharsets.UTF_8);
}

public static List<String> split(String str, char separator) {
ArrayList<String> parts = new ArrayList<>();
int start = 0;
int len = str.length();
for (int i = 0; i < len; i++) {
if (str.charAt(i) == separator) {
parts.add(str.substring(start, i));
start = i + 1;
}
}
parts.add(str.substring(start)); // Add the last part
return List.copyOf(parts);
}

public static int len(byte[] value) {
if (value == null) {
return 0;
Expand Down
43 changes: 0 additions & 43 deletions src/main/java/io/roastedroot/proxywasm/ProxyWasm.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ public final class ProxyWasm implements Closeable {
private final Handler pluginHandler;
private final byte[] pluginConfig;
private final byte[] vmConfig;
private final HashMap<String, String> properties;
private final WasiPreview1 wasi;

private final AtomicInteger nextContextID = new AtomicInteger(1);
Expand All @@ -42,7 +41,6 @@ public final class ProxyWasm implements Closeable {
private ProxyWasm(Builder other) throws StartException {
this.vmConfig = other.vmConfig;
this.pluginConfig = other.pluginConfig;
this.properties = Objects.requireNonNullElse(other.properties, new HashMap<>());
this.pluginHandler = Objects.requireNonNullElse(other.pluginHandler, new Handler() {});
this.wasi = other.wasi;
this.abi = other.abi;
Expand Down Expand Up @@ -91,19 +89,6 @@ public byte[] getPluginConfig() {
return pluginConfig;
}

@Override
public String getProperty(String key) throws WasmException {
if (properties.containsKey(key)) {
return properties.get(key);
}

var handler = activeContext.handler();
if (handler != null) {
return handler.getProperty(key);
}
return null;
}

@Override
public WasmResult setEffectiveContextID(int contextID) {
Context context = contexts.get(contextID);
Expand Down Expand Up @@ -188,24 +173,6 @@ public void tick() {
this.abi.proxyOnTick(pluginContext.id());
}

public void setProperty(String[] path, String data) {
if (len(path) == 0) {
throw new IllegalArgumentException("path must not be empty");
}
if (len(data) == 0) {
throw new IllegalArgumentException("data must not be empty");
}

this.properties.put(String.join("\u0000", path), data);
}

public String getProperty(String[] path) {
if (len(path) == 0) {
throw new IllegalArgumentException("path must not be empty");
}
return this.properties.get(String.join("\u0000", path));
}

@Override
public void close() {
this.pluginContext.close();
Expand Down Expand Up @@ -262,7 +229,6 @@ public static class Builder implements Cloneable {

private byte[] vmConfig = new byte[0];
private byte[] pluginConfig = new byte[0];
private HashMap<String, String> properties;
private Handler pluginHandler;
private ImportMemory memory;
private WasiOptions wasiOptions;
Expand Down Expand Up @@ -301,15 +267,6 @@ public ProxyWasm.Builder withPluginConfig(String pluginConfig) {
return this;
}

public ProxyWasm.Builder withProperties(Map<String, String> properties) {
if (properties != null) {
this.properties = new HashMap<>(properties);
} else {
this.properties = null;
}
return this;
}

public ProxyWasm.Builder withPluginHandler(Handler vmHandler) {
this.pluginHandler = vmHandler;
return this;
Expand Down
13 changes: 13 additions & 0 deletions src/test/java/io/roastedroot/proxywasm/examples/MockHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -461,4 +461,17 @@ public WasmResult setAction(StreamType streamType, Action action) {
public Action getAction() {
return action;
}

final HashMap<List<String>, byte[]> properties = new HashMap<>();

@Override
public byte[] getProperty(List<String> path) throws WasmException {
return properties.get(path);
}

@Override
public WasmResult setProperty(List<String> path, byte[] value) {
properties.put(path, value);
return WasmResult.OK;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.roastedroot.proxywasm.examples;

import static io.roastedroot.proxywasm.Helpers.bytes;
import static org.junit.jupiter.api.Assertions.assertEquals;

import com.dylibso.chicory.wasm.Parser;
Expand All @@ -22,10 +23,9 @@ public class OnRequestHeadersTest {
public void test() throws StartException {
// This module uses the 0_1_0 ABI
var handler = new MockHandler();
ProxyWasm.Builder builder =
ProxyWasm.builder()
.withProperties(Map.of("plugin_root_id", ""))
.withPluginHandler(handler);
handler.setProperty(List.of("plugin_root_id"), bytes(""));

ProxyWasm.Builder builder = ProxyWasm.builder().withPluginHandler(handler);

try (var proxyWasm = builder.build(module)) {

Expand Down
Loading