From d7bcd210512efdce3d41f01037c8182cfddec37f Mon Sep 17 00:00:00 2001 From: Piotr Sikora Date: Tue, 17 Mar 2020 20:55:10 +0000 Subject: [PATCH 1/4] Re-add ABI vNEXT (to be reviewed). Signed-off-by: Piotr Sikora --- abi-versions/README.md | 40 ++ abi-versions/vNEXT/README.md | 919 +++++++++++++++++++++++++++++++++++ 2 files changed, 959 insertions(+) create mode 100644 abi-versions/README.md create mode 100644 abi-versions/vNEXT/README.md diff --git a/abi-versions/README.md b/abi-versions/README.md new file mode 100644 index 0000000..2008c69 --- /dev/null +++ b/abi-versions/README.md @@ -0,0 +1,40 @@ +# Proxy-Wasm ABI specification + +## ABI versioning + +The ABI is in the form of: `..` + +Breaking changes require increasing the major version. + +Adding new functions requires increasing the minor version. + +Adding new enum values requires increasing the patch version. + +Wasm modules should export `proxy_abi_version___` function, indicating which +version of the ABI they were compiled against. + +Host environments should be able to support multiple versions of the ABI. + +## Naming conventions + +All functions are using `snake_case`, and they start with the `proxy_` prefix. Implementation +specific extensions should use different prefixes (e.g. `envoy_`, `nginx_`, `ats_`, etc.) in order +to avoid polluting the common namespace. However, this is highly discouraged, and should be used +only for implementing optional proxy-specific functionality, otherwise we’re going to lose +portability. + +Function names are in the form of: `proxy____` (e.g. +`proxy_on_http_request_headers`, `proxy_get_map_value`, etc). + +## Memory ownership + +No memory-managed data is passed to Wasm module in any of the event callbacks, and Wasm module must +request memory-managed data from the host environment if it’s interested in it, e.g. +`proxy_on_http_request_body` only passes the information about the number of available request body +bytes, but the module must request them using `proxy_get_buffer`. When that happens, the host +environment will request the Wasm module to allocate memory using `proxy_on_memory_allocate` and +copy requested data into it. In doing so, it passes memory ownership of that data to the Wasm +module, which is expected to free this memory when it no longer needs it. + +SDKs implementing this ABI are expected to automatically handle freeing of the memory-managed data +for the developers. diff --git a/abi-versions/vNEXT/README.md b/abi-versions/vNEXT/README.md new file mode 100644 index 0000000..38af8e6 --- /dev/null +++ b/abi-versions/vNEXT/README.md @@ -0,0 +1,919 @@ +# Proxy-Wasm vNEXT ABI specification + +# Functions implemented in the Wasm module + +All functions implemented in the Wasm module, other than the integration and memory management +functions, include context identifier (`context_id`) as the first parameter, which should be used to +distinguish between different contexts. + + +## Integration + +### `_start` + +* params: + - none +* returns: + - none + +Start function which is called when the module is loaded and initialized. This can be used by SDKs +to setup and/or initialize state, but no proxy_ functions can be used at that point yet. + + +### `proxy_abi_version_X_Y_Z` + +* params: + - none +* returns: + - none + +Exports ABI version (vX.Y.Z) this module was compiled against. + +Considered alternatives: Ideally, this would be exported as a global variable, but existing +toolchains have trouble with that (some don’t support global variables at all, some incorrectly +export language-specific and not Wasm-generic variables). + + +## Memory management + +### `proxy_on_memory_allocate` + +* params: + - `i32 (size_t) memory_size` +* returns: + - `i32 (void*) allocated_ptr` + +Allocates memory using in-VM memory allocator and returns it to the host. + + +## Module lifecycle + +### `proxy_on_context_create` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (uint32_t) parent_context_id` +* returns: + - none + +Called when the host environment creates a new root context (if `parent_context_id` is `0`) or a new +per-stream context. + + +### `proxy_on_done` + +* params: + - `i32 (uint32_t) context_id` +* returns: + - `i32 (bool) is_done` + +Called when the host environment is done processing the context (`context_id`). Return value +indicates when the Wasm VM is done with the processing as well. + + +### `proxy_on_log` + +* params: + - `i32 (uint32_t) context_id` +* returns: + - none + +Called in the logging phase. + + +### `proxy_on_delete` + +* params: + - `i32 (uint32_t) context_id` +* returns: + - none + +Called when the host environment removes the context (`context_id`). This is used to signal that VM +should stop tracking that `context_id` and remove all associated state. + + +## Configuration + +### `proxy_on_vm_start` + +* params: + - `i32 (uint32_t) root_context_id` + - `i32 (size_t) vm_configuration_size` +* returns: + - `i32 (bool) success` + +Called when the host environment starts the WebAssembly Virtual Machine. Its configuration +(`vm_configuration_size`) might be retrieved using `proxy_get_buffer`. + + +### `proxy_on_configure` + +* params: + - `i32 (uint32_t) root_context_id` + - `i32 (size_t) plugin_configuration_size` +* returns: + - `i32 (bool) success` + +Called when the host environment starts the plugin. Its configuration (`plugin_configuration_size`) +might be retrieved using `proxy_get_buffer`. + + +## Timers + +### `proxy_on_tick` + +* params: + - `i32 (uint32_t) root_context_id` +* returns: + - none + +Timer called every tick period. Tick period can be configured using +`proxy_set_tick_period_milliseconds`. + + +## TCP/UDP/QUIC stream (L4) extensions + +Note: `downstream` means the connection between client and proxy, and `upstream` means the +connection between proxy and backend (aka “next hop”). + +### `proxy_on_new_connection` + +* params: + - `i32 (uint32_t) context_id` +* returns: + - `i32 (proxy_action_t) next_action` + +Called on a new TCP connection. + + +### `proxy_on_downstream_data` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (size_t) data_size` + - `i32 (bool) end_of_stream` +* returns: + - `i32 (proxy_action_t) next_action` + +Called for each data chunk received from downstream. + + +### `proxy_on_downstream_close` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (proxy_peer_type_t) peer_type` +* returns: + - none + +Called when downstream connection is closed. + + +### `proxy_on_upstream_data` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (size_t) data_size` + - `i32 (bool) end_of_stream` +* returns: + - `i32 (proxy_action_t) next_action` + +Called for each data chunk received from upstream. + + +### `proxy_on_upstream_close` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (proxy_peer_type_t) peer_type` +* returns: + - none + +Called when upstream connection is closed. + + +## HTTP (L7) extensions + +### `proxy_on_http_request_headers` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (size_t) num_headers` + - `i32 (bool) end_of_stream` +* returns: + - `i32 (proxy_action_t) next_action` + +Called when HTTP request headers are received from the client. Headers can be retrieved using +`proxy_get_map` and/or `proxy_get_map_value`. + + +### `proxy_on_http_request_body` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (size_t) body_size` + - `i32 (bool) end_of_stream` +* returns: + - `i32 (proxy_action_t) next_action` + +Called for each chunk of HTTP request body received from the client. Request body can be retrieved +using `proxy_get_buffer`. + + +### `proxy_on_http_request_trailers` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (size_t) num_trailers` + - `i32 (bool) end_of_stream` +* returns: + - `i32 (proxy_action_t) next_action` + +Called when HTTP request trailers are received from the client. Trailers can be retrieved using +`proxy_get_map` and/or `proxy_get_map_value`. + + +### `proxy_on_http_request_metadata` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (size_t) num_elements` + - `i32 (bool) end_of_stream` +* returns: + - `i32 (proxy_action_t) next_action` + +Called for each HTTP/2 METADATA frame received from the client. Metadata can be retrieved using +`proxy_get_map` and/or `proxy_get_map_value`. + + +### `proxy_on_http_response_headers` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (size_t) num_headers` + - `i32 (bool) end_of_stream` +* returns: + - `i32 (proxy_action_t) next_action` + +Called when HTTP response headers are received from the upstream. Headers can be retrieved using +`proxy_get_map` and/or `proxy_get_map_value`. + + +### `proxy_on_http_response_body` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (size_t) body_size` + - `i32 (bool) end_of_stream` +* returns: + - `i32 (proxy_action_t) next_action` + +Called for each chunk of HTTP response body received from the client. Response body can be retrieved +using `proxy_get_buffer`. + + +### `proxy_on_http_response_trailers` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (size_t) num_trailers` + - `i32 (bool) end_of_stream` +* returns: + - `i32 (proxy_action_t) next_action` + +Called when HTTP response trailers are received from the upstream. Trailers can be retrieved using +`proxy_get_map` and/or `proxy_get_map_value`. + + +### `proxy_on_http_response_metadata` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (size_t) num_elements` + - `i32 (bool) end_of_stream` +* returns: + - `i32 (proxy_action_t) next_action` + +Called for each HTTP/2 METADATA frame received from the upstream. Metadata can be retrieved using +`proxy_get_map` and/or `proxy_get_map_value`. + + +## HTTP calls + +### `proxy_on_http_call_response` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (uint32_t) callout_id` + - `i32 (size_t) num_headers` + - `i32 (size_t) body_size` + - `i32 (size_t) num_trailers` +* returns: + - none + +Called when the response to the HTTP call (`callout_id`) is received. + + +## gRPC callouts + +### `proxy_on_grpc_call_response_header_metadata` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (uint32_t) callout_id` + - `i32 (size_t) num_elemets` +* returns: + - none + +Called when header metadata in the response to the gRPC call (`callout_id`) is received. + + +### `proxy_on_grpc_call_response_message` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (uint32_t) callout_id` + - `i32 (size_t) message_size` +* returns: + - none + +Called when the response to the gRPC call (`callout_id`) is received. + + +### `proxy_on_grpc_call_response_trailer_metadata` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (uint32_t) callout_id` + - `i32 (size_t) num_elements` +* returns: + - none + +Called when trailer metadata in the response to the gRPC call (`callout_id`) is received. + + +### `proxy_on_grpc_call_close` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (uint32_t) callout_id` + - `i32 (uint32_t) status_code` +* returns: + - none + +Called when the request to the gRPC call (`callout_id`) fails or if the gRPC connection is closed. + + +## Shared queue + +### `proxy_on_queue_ready` + +* params: + - `i32 (uint32_t) context_id` + - `i32 (uint32_t) queue_id` +* returns: + - none + +Called when there is data available in the queue (`queue_id`). + + +# Functions implemented in the host environment + +All functions implemented in the host environment return `proxy_result_t`, which indicates the +status of the call (successful, invalid memory access, etc.), and the return values are written into +memory pointers passed in as arguments (indicated by the `return_` prefix in the specification). + + +## Logging + +### `proxy_log` + +* params: + - `i32 (proxy_log_level_t) log_level` + - `i32 (const char*) message_data` + - `i32 (size_t) message_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Log message (`message_data`, `message_size`) at the given `log_level`. + + +### `proxy_get_current_time` + +* params: + - `i32 (uint64_t*) return_current_time_nanoseconds` +* returns: + - `i32 (proxy_result_t) call_result` + +Get current time (`return_current_time`). + + +## Module lifecycle + +### `proxy_set_effective_context` + +* params: + - `i32 (uint32_t) context_id` +* returns: + - `i32 (proxy_result_t) call_result` + +Change the effective context to `context_id`. This function is usually used to change the context +after receiving `proxy_on_http_call_response`, `proxy_on_grpc_call_response` or +`proxy_on_queue_ready`. + + +### `proxy_done` + +* params: + - none +* returns: + - `i32 (proxy_result_t) call_result` + +Indicate to the host environment that Wasm VM side is done processing current context. This can be +used after returning `false` in `proxy_on_done`. + + +## Timers + +### `proxy_set_tick_period` + +* params: + - `i32 (uint32_t) tick_period` +* returns: + - `i32 (proxy_result_t) call_result` + +Set timer period (`tick_period`). Once set, the host environment will call `proxy_on_tick` every +`tick_period` milliseconds. + + +## Buffers, maps, and properties + +### `proxy_get_buffer` + +* params: + - `i32 (proxy_buffer_type_t) buffer_type` + - `i32 (offset_t) offset` + - `i32 (size_t) max_size` + - `i32 (const char**) return_buffer_data` + - `i32 (size_t*) return_buffer_size` + - `i32 (uint32_t*) return_flags` +* returns: + - `i32 (proxy_result_t) call_result` + +Get up to max_size bytes from the `buffer_type`, starting from `offset`. Bytes are written into +buffer slice (`return_buffer_data`, `return_buffer_size`), and buffer flags are written into +`return_flags`. + + +### `proxy_set_buffer` + +* params: + - `i32 (proxy_buffer_type_t) buffer_type` + - `i32 (offset_t) offset` + - `i32 (size_t) size` + - `i32 (const char*) buffer_data` + - `i32 (size_t) buffer_size` + - `i32 (uint32_t) flags` +* returns: + - `i32 (proxy_result_t) call_result` + +Set content of the buffer `buffer_type` to the bytes (`buffer_data`, `buffer_size`), replacing +`size` bytes, starting at `offset` in the existing buffer. + + +### `proxy_get_map` + +* params: + - `i32 (proxy_map_type_t) map_type` + - `i32 (const char**) return_map_data` + - `i32 (size_t*) return_map_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Get all key-value pairs from a given map (`map_type`). + + +### `proxy_set_map` + +* params: + - `i32 (proxy_map_type_t) map_type` + - `i32 (const char*) map_data` + - `i32 (size_t) map_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Set all key-value pairs in a given map (`map_type`). + + +### `proxy_get_map_value` + +* params: + - `i32 (proxy_map_type_t) map_type` + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` + - `i32 (const char**) return_value_data` + - `i32 (size_t*) return_value_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Get content of key (`key_data`, `key_size`) from a given map (`map_type`). + + +### `proxy_set_map_value` + +* params: + - `i32 (proxy_map_type_t) map_type` + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` + - `i32 (const char*) value_data` + - `i32 (size_t) value_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Set or replace the content of key (`key_data`, `key_size`) to the value (`value_data`, `value_size`) +in a given map (`map_type`). + +### `proxy_add_map_value` + +* params: + - `i32 (proxy_map_type_t) map_type` + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` + - `i32 (const char*) value_data` + - `i32 (size_t) value_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Add key (`key_data`, `key_size`) with the value (`value_data`, `value_size`) to a given map +(`map_type`). + + +### `proxy_remove_map_value` + +* params: + - `i32 (proxy_map_type_t) map_type` + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Remove key (`key_data`, `key_size`) from a given map (`map_type`). + + +### `proxy_get_property` + +* params: + - `i32 (const char*) property_path_data` + - `i32 (size_t) property_path_size` + - `i32 (const char**) return_property_value_data` + - `i32 (size_t*) return_property_value_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Get property (`property_path_data`, `property_path_size`). + + +### `proxy_set_property` + +* params: + - `i32 (const char*) property_path_data` + - `i32 (size_t) property_path_size` + - `i32 (const char*) property_value_data` + - `i32 (size_t) property_value_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Set property (`property_path_data`, `property_path_size`) to given value (`property_value_data`, +`property_value_size`). + + +## TCP/UDP/QUIC stream (L4) extensions + +### `proxy_resume_downstream` + +* params: + - none +* returns: + - `i32 (proxy_result_t) call_result` + +Resume processing of paused downstream. + + +### `proxy_resume_upstream` + +* params: + - none +* returns: + - `i32 (proxy_result_t) call_result` + +Resume processing of paused upstream. + + +## HTTP (L7) extensions + +### `proxy_resume_http_request` + +* params: + - none +* returns: + - `i32 (proxy_result_t) call_result` + +Resume processing of paused HTTP request. + + +### `proxy_resume_http_response` + +* params: + - none +* returns: + - `i32 (proxy_result_t) call_result` + +Resume processing of paused HTTP response. + + +### `proxy_send_http_response` + +* params: + - `i32 (uint32_t) response_code` + - `i32 (const char*) response_code_details_data` + - `i32 (size_t) response_code_details_size` + - `i32 (const char*) response_body_data` + - `i32 (size_t) response_body_size` + - `i32 (const char*) additional_headers_map_data` + - `i32 (size_t) additional_headers_size` + - `i32 (uint32_t) grpc_status` +* returns: + - `i32 (proxy_result_t) call_result` + +Sends HTTP response without forwarding request to the upstream. + + +## HTTP calls + +### `proxy_dispatch_http_call` + +* params: + - `i32 (const char*) upstream_name_data` + - `i32 (size_t) upstream_name_size` + - `i32 (const char*) headers_map_data` + - `i32 (size_t) headers_map_size` + - `i32 (const char*) body_data` + - `i32 (size_t) body_size` + - `i32 (const char*) trailers_map_data` + - `i32 (size_t) trailers_map_size` + - `i32 (uint32_t) timeout_milliseconds` + - `i32 (uint32_t*) return_callout_id` +* returns: + - `i32 (proxy_result_t) call_result` + +Dispatch a HTTP call to upstream (`upstream_name_data`, `upstream_name_size`). Once the response is +returned to the host, `proxy_on_http_call_response` will be called with a unique call identifier +(`return_callout_id`). + + +## gRPC calls + +### `proxy_dispatch_grpc_call` + +* params: + - `i32 (const char*) grpc_service_data` + - `i32 (size_t) grpc_service_size` + - `i32 (const char*) service_name_data` + - `i32 (size_t) service_name_size` + - `i32 (const char*) method_data` + - `i32 (size_t) method_size` + - `i32 (const char*) grpc_message_data` + - `i32 (size_t) grpc_message_size` + - `i32 (uint32_t) timeout_milliseconds` + - `i32 (uint32_t*) return_callout_id` +* returns: + - `i32 (proxy_result_t) call_result` + +Dispatch a gRPC call to a service (`service_name_data`, `service_name_size`). Once the response is +returned to the host, `proxy_on_grpc_call_response` and/or `proxy_on_grpc_call_close` will be called +with a unique call identifier (`return_callout_id`). The call identifier can also be used to cancel +outstanding requests using `proxy_cancel_grpc_call` or close outstanding request using or +`proxy_close_grpc_call`. + + +### `proxy_open_grpc_stream` + +* params: + - `i32 (const char*) grpc_service_data` + - `i32 (size_t) grpc_service_size` + - `i32 (const char*) service_name_data` + - `i32 (size_t) service_name_size` + - `i32 (const char*) method_data` + - `i32 (size_t) method_size` + - `i32 (uint32_t*) return_callout_id` +* returns: + - `i32 (proxy_result_t) call_result` + +Open a connection to the gRPC service (`service_name_data`, `service_name_size`). + + +### `proxy_send_grpc_call_message` + +* params: + - `i32 (uint32_t) callout_id` + - `i32 (const char*) grpc_message_data` + - `i32 (size_t) grpc_message_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Send gRPC message (`grpc_message_data`, `grpc_message_size`) on the existing gRPC stream +(`callout_id`). + + +### `proxy_cancel_grpc_call` + +* params: + - `i32 (uint32_t) callout_id` +* returns: + - `i32 (proxy_result_t) call_result` + +Cancel outstanding gRPC request or stream (`callout_id`). + + +### `proxy_close_grpc_call` + +* params: + - `i32 (uint32_t) callout_id` +* returns: + - `i32 (proxy_result_t) call_result` + +Cancel outstanding gRPC request or close existing gRPC stream (`callout_id`). + + +## Shared Key-Value store + +### `proxy_get_shared_data` + +* params: + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` + - `i32 (const char**) return_value_data` + - `i32 (size_t*) return_value_size` + - `i32 (uint32_t*) return_cas` +* returns: + - `i32 (proxy_result_t) call_result` + +Get shared data identified by a key (`key_data`, `key_size`). The compare-and-switch value +(`return_cas`) is returned and can be used when updating the value with `proxy_set_shared_data`. + + +### `proxy_set_shared_data` + +* params: + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` + - `i32 (const char*) value_data` + - `i32 (size_t) value_size` + - `i32 (uint32_t) cas` +* returns: + - `i32 (proxy_result_t) call_result` + +Set shared data identified by a key (`key_data`, `key_size`) to a value (`value_data`, +`value_size`). If compare-and-switch value (`cas`) is set, then it must match the current value in +order to update to succeed. + + +## Shared queue + +### `proxy_register_shared_queue` + +* params: + - `i32 (const char*) queue_name_data` + - `i32 (size_t) queue_name_size` + - `i32 (uint32_t*) return_queue_id` +* returns: + - `i32 (proxy_result_t) call_result` + +Register a shared queue using a given name (`queue_name_data`, `queue_name_size`). It can be +referred to in `proxy_enqueue_shared_queue` and `proxy_dequeue_shared_queue` using returned unique +queue identifier (`queue_id`). + + +### `proxy_resolve_shared_queue` + +* params: + - `i32 (const char*) queue_name_data` + - `i32 (size_t) queue_name_size` + - `i32 (uint32_t*) return_queue_id` +* returns: + - `i32 (proxy_result_t) call_result` + +Resolves existing shared queue using a given name (`queue_name_data`, `queue_name_size`). It can be +referred to in `proxy_enqueue_shared_queue` and `proxy_dequeue_shared_queue` using returned unique +queue identifier (`queue_id`). + + +### `proxy_dequeue_shared_queue` + +* params: + - `i32 (uint32_t) queue_id` + - `i32 (const char**) payload_data` + - `i32 (size_t*) payload_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Get data (`payload_data`, `payload_size`) to the end of the queue (`queue_id`). + + +### `proxy_enqueue_shared_queue` + +* params: + - `i32 (uint32_t) queue_id` + - `i32 (const char*) payload_data` + - `i32 (size_t) payload_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Add data (`payload_data`, `payload_size`) to the front of the queue (`queue_id`). + + +### `proxy_remove_shared_queue` + +* params: + - `i32 (uint32_t) queue_id` +* returns: + - `i32 (proxy_result_t) call_result` + +Remove queue (`queue_id`). + + +## Stats/metrics + +### `proxy_define_metric` + +* params: + - `i32 (proxy_metric_type_t) metric_type` + - `i32 (const char*) metric_name_data` + - `i32 (size_t) metric_name_size` + - `i32 (uint32_t*) return_metric_id` +* returns: + - `i32 (proxy_result_t) call_result` + +Define a metric using a given name (`metric_name_data`, `metic_name_size`). It can be referred to in +`proxy_get_metric`, `proxy_increment_metric` and `proxy_record_metric` using returned unique metric +identifier (`metric_id`). + + +### `proxy_get_metric` + +* params: + - `i32 (uint32_t) metric_id` + - `i32 (uint64_t*) return_value` +* returns: + - `i32 (proxy_result_t) call_result` + +Get the value of the metric (`metric_id`). + + +### `proxy_record_metric` + +* params: + - `i32 (uint32_t) metric_id` + - `i64 (uint64_t) value +* returns: + - `i32 (proxy_result_t) call_result` + +Set the value of the metric (`metric_id`) to the value (`value`). + + +### `proxy_increment_metric` + +* params: + - `i32 (uint32_t) metric_id` + - `i64 (int64_t) offset +* returns: + - `i32 (proxy_result_t) call_result` + +Increment/decrement value of the metric (`metric_id`) by offset (`offset`). + + +### `proxy_remove_metric` + +* params: + - `i32 (uint32_t) metric_id` +* returns: + - `i32 (proxy_result_t) call_result` + +Remove the metric (`metric_id`). + + +## Foreign function interface (FFI): + +### `proxy_call_foreign_function` + +* params: + - `i32 (const char*) function_name_data` + - `i32 (size_t) function_name_size` + - `i32 (const char *) parameters_data` + - `i32 (size_t) parameters_size` + - `i32 (const char**) return_results_data` + - `i32 (size_t*) return_results_size` +* returns: + - `i32 (proxy_result_t) call_result` + +Call registered foreign function (`function_name_data`, `function_name_size`). From fc772fa00164f09fd30952f733454c85fc018eb3 Mon Sep 17 00:00:00 2001 From: Piotr Sikora Date: Fri, 17 Jul 2020 14:06:25 +0000 Subject: [PATCH 2/4] Update ABI specification with more details. Signed-off-by: Piotr Sikora --- abi-versions/vNEXT/README.md | 1405 ++++++++++++++++++++++++---------- 1 file changed, 1012 insertions(+), 393 deletions(-) diff --git a/abi-versions/vNEXT/README.md b/abi-versions/vNEXT/README.md index 38af8e6..790c3ae 100644 --- a/abi-versions/vNEXT/README.md +++ b/abi-versions/vNEXT/README.md @@ -1,656 +1,1173 @@ # Proxy-Wasm vNEXT ABI specification -# Functions implemented in the Wasm module +# Callbacks and Functions -All functions implemented in the Wasm module, other than the integration and memory management -functions, include context identifier (`context_id`) as the first parameter, which should be used to -distinguish between different contexts. +### Callbacks optionally exposed by the Wasm module + +All callbacks (entry points named `proxy_on_`) are optional, and will be +called only if exposed by the Wasm module. + +All callbacks, other than the integration functions, include unique context +identifier as the first parameter, which can be used to distinguish between +different contexts. + +### Functions exposed by the host environment + +All functions exposed by the host environment return `proxy_result_t`, which +indicates the status of the call (success, invalid memory access, etc.), and +return values are written into memory pointed by `return_` parameters. ## Integration -### `_start` +### Functions exposed by the host environment + +#### `proxy_abi_version_X_Y_Z` * params: - none * returns: - none -Start function which is called when the module is loaded and initialized. This can be used by SDKs -to setup and/or initialize state, but no proxy_ functions can be used at that point yet. - +Exports ABI version (vX.Y.Z) that the Wasm module was compiled against. -### `proxy_abi_version_X_Y_Z` +#### `proxy_log` * params: - - none + - `i32 (proxy_log_level_t) log_level` + - `i32 (const char*) message_data` + - `i32 (size_t) message_size` * returns: - - none + - `i32 (proxy_result_t) call_result` + +Logs message (`message_data`, `message_size`) at the log level (`log_level`). -Exports ABI version (vX.Y.Z) this module was compiled against. +Returns `Ok` on success. -Considered alternatives: Ideally, this would be exported as a global variable, but existing -toolchains have trouble with that (some don’t support global variables at all, some incorrectly -export language-specific and not Wasm-generic variables). +Returns `BadArgument` for unknown `log_level`. +Returns `InvalidMemoryAccess` when `message_data` and/or `message_size` point to +invalid memory address. -## Memory management +### Callbacks optionally exposed by the Wasm module -### `proxy_on_memory_allocate` +#### `proxy_on_memory_allocate` * params: - `i32 (size_t) memory_size` * returns: - - `i32 (void*) allocated_ptr` + - `i32 (void*) memory_data` + +Allocates continuous memory buffer of size `memory_size` using the in-VM memory +allocator and returns address of the memory buffer to the host environment using +`memory_data`. Returning `0` indicates failure. -Allocates memory using in-VM memory allocator and returns it to the host. +## Context lifecycle -## Module lifecycle +### Callbacks optionally exposed by the Wasm module -### `proxy_on_context_create` +#### `proxy_on_context_create` * params: - `i32 (uint32_t) context_id` - `i32 (uint32_t) parent_context_id` + - `i32 (proxy_context_type_t) context_type` * returns: - - none + - `i32 (uint32_t) new_context_id` + +Called when the host environment creates a new context (`context_id`) of type +`context_type` (e.g. `VmContext`, `PluginContext`, `StreamContext`, +`HttpContext`). -Called when the host environment creates a new root context (if `parent_context_id` is `0`) or a new -per-stream context. +This callback can be used to associate `context_id` with `parent_context_id`, +or when using custom context identifiers, but otherwise the in-VM context can be +implicitly created in `proxy_on_vm_start`, `proxy_on_plugin_start`, +`proxy_on_new_connection` and `proxy_on_http_request_headers` callbacks. +Return value (`new_context_id`) can be used to assign new context identifier +that will be used by the host environment in subsequent calls. Returning `0` +retains the original context identifier. -### `proxy_on_done` +#### `proxy_on_context_finalize` * params: - `i32 (uint32_t) context_id` * returns: - `i32 (bool) is_done` -Called when the host environment is done processing the context (`context_id`). Return value -indicates when the Wasm VM is done with the processing as well. +Called when the host environment is done processing context (`context_id`). +Any finalization (e.g. logging) should be done within this callback. +Return value (`is_done`) indicates that the Wasm module also finished processing +context (`context_id`). If it didn't, then it should return `false` and call +`proxy_context_finalize` when it's done. -### `proxy_on_log` +### Functions exposed by the host environment + +#### `proxy_set_effective_context` * params: - `i32 (uint32_t) context_id` * returns: - - none + - `i32 (proxy_result_t) call_result` + +Change the effective context to `context_id`. This function is usually used to +change effective context during `proxy_on_queue_ready`, `proxy_on_timer_ready`, +`proxy_on_http_call_response` and `proxy_on_grpc_call_response` callbacks. -Called in the logging phase. +Returns `Ok` on success. +Returns `BadArgument` for unknown `context_id`. -### `proxy_on_delete` +#### `proxy_context_finalize` * params: - - `i32 (uint32_t) context_id` -* returns: - none +* returns: + - `i32 (proxy_result_t) call_result` + +Indicates to the host environment that the Wasm module finished processing +current context. It should be used after previously returning `false` in +`proxy_on_context_finalize`. -Called when the host environment removes the context (`context_id`). This is used to signal that VM -should stop tracking that `context_id` and remove all associated state. +Returns `Ok` on success. ## Configuration -### `proxy_on_vm_start` +### Callbacks optionally exposed by the Wasm module + +#### `proxy_on_vm_start` * params: - - `i32 (uint32_t) root_context_id` + - `i32 (uint32_t) vm_id` - `i32 (size_t) vm_configuration_size` * returns: - - `i32 (bool) success` + - `i32 (bool) is_success` + +Called when the host environment starts WebAssembly Virtual Machine (WasmVm). -Called when the host environment starts the WebAssembly Virtual Machine. Its configuration -(`vm_configuration_size`) might be retrieved using `proxy_get_buffer`. +Its configuration (of size `vm_configuration_size`) can be retrieved using +`proxy_get_buffer`. +Return value (`is_success`) indicates that configuration was processed correctly +and that WasmVm started successfully. -### `proxy_on_configure` +#### `proxy_on_plugin_start` * params: - - `i32 (uint32_t) root_context_id` + - `i32 (uint32_t) plugin_id` - `i32 (size_t) plugin_configuration_size` * returns: - - `i32 (bool) success` - -Called when the host environment starts the plugin. Its configuration (`plugin_configuration_size`) -might be retrieved using `proxy_get_buffer`. + - `i32 (bool) is_success` +Called when the host environment starts plugin. -## Timers +Its configuration (of size `plugin_configuration_size`) can be retrieved using +`proxy_get_buffer`. -### `proxy_on_tick` +Return value (`is_success`) indicates that configuration was processed correctly +and that plugin started successfully. -* params: - - `i32 (uint32_t) root_context_id` -* returns: - - none -Timer called every tick period. Tick period can be configured using -`proxy_set_tick_period_milliseconds`. +## TCP/UDP/QUIC stream (L4) extensions +Note: `downstream` means the connection between client and proxy, and `upstream` + means the connection between proxy and backend (aka “next hop”). -## TCP/UDP/QUIC stream (L4) extensions +Note: The same unique context identifier (`stream_id`) is shared by a pair of + `downstream` and `upstream` connections. -Note: `downstream` means the connection between client and proxy, and `upstream` means the -connection between proxy and backend (aka “next hop”). +### Callbacks optionally exposed by the Wasm module -### `proxy_on_new_connection` +#### `proxy_on_new_connection` * params: - - `i32 (uint32_t) context_id` + - `i32 (uint32_t) stream_id` * returns: - `i32 (proxy_action_t) next_action` -Called on a new TCP connection. +Called on a new connection (`stream_id`). +Return value (`next_action`) instructs the host environment what action to take: +- `Continue` means that this connection should be accepted. +- `Done` means that this connection should be accepted and that this extension + shouldn't be called again for the current stream. +- `Pause` means that further processing should be paused until + `proxy_resume_stream` is called. +- `Close` means that this connection should be rejected. -### `proxy_on_downstream_data` +#### `proxy_on_downstream_data` * params: - - `i32 (uint32_t) context_id` + - `i32 (uint32_t) stream_id` - `i32 (size_t) data_size` - `i32 (bool) end_of_stream` * returns: - `i32 (proxy_action_t) next_action` -Called for each data chunk received from downstream. +Called for each data chunk received from downstream (`stream_id`). + +Data (of size `data_size`) can be retrieved using `proxy_get_buffer`. +Return value (`next_action`) instructs the host environment what action to take: +- `Continue` means that data chunk should be forwarded upstream. +- `EndStream` means that data chunk should be forwarded upstream and that this + connection should be closed afterwards. +- `Done` means that data chunk should be forwarded upstream and that this + extension shouldn't be called again for the current stream. +- `Pause` means that further processing should be paused until + `proxy_resume_stream` is called. +- `WaitForMoreData` means that further processing should be paused and that host + should call this callback again when it has more data. +- `WaitForEndOrFull` means that further processing should be paused and that + host should call this callback again when downstream connection is closed or + when its internal buffers are full. +- `Close` means that this connection should be closed immediately. -### `proxy_on_downstream_close` +#### `proxy_on_downstream_close` * params: - `i32 (uint32_t) context_id` - - `i32 (proxy_peer_type_t) peer_type` + - `i32 (proxy_close_source_type_t) close_source` * returns: - none -Called when downstream connection is closed. +Called when the downstream connection (`stream_id`) is closed. - -### `proxy_on_upstream_data` +#### `proxy_on_upstream_data` * params: - - `i32 (uint32_t) context_id` + - `i32 (uint32_t) stream_id` - `i32 (size_t) data_size` - `i32 (bool) end_of_stream` * returns: - `i32 (proxy_action_t) next_action` -Called for each data chunk received from upstream. +Called for each data chunk received from upstream (`stream_id`). +Data (of size `data_size`) can be retrieved using `proxy_get_buffer`. -### `proxy_on_upstream_close` +Return value (`next_action`) instructs the host environment what action to take: +- `Continue` means that data should be forwarded downstream. +- `EndStream` means that data should be forwarded downstream and that this + connection should be closed afterwards. +- `Done` means that data should be forwarded downstream and that this extension + shouldn't be called again for the current stream. +- `Pause` means that further processing should be paused until + `proxy_resume_stream` is called. +- `WaitForMoreData` means that further processing should be paused and that host + should call this callback again when it has more data. +- `WaitForEndOrFull` means that further processing should be paused and that + host should call this callback again when when upstream connection is closed + or when its internal buffers are full. +- `Close` means that this connection should be closed immediately. + +#### `proxy_on_upstream_close` * params: - - `i32 (uint32_t) context_id` - - `i32 (proxy_peer_type_t) peer_type` + - `i32 (uint32_t) stream_id` + - `i32 (proxy_close_source_type_t) close_source` * returns: - none -Called when upstream connection is closed. +Called when the upstream connection (`stream_id`) is closed. + +### Functions exposed by the host environment + +#### `proxy_resume_stream` + +* params: + - `i32 (proxy_stream_type_t) stream_type` +* returns: + - `i32 (proxy_result_t) call_result` + +Resume processing of paused downstream or upstream (`stream_type`) connection +in current context. + +Returns `Ok` on success. + +Returns `BadArgument` for unknown `stream_type`. + +Returns `InvalidOperation` when stream wasn't paused. + +#### `proxy_close_stream` + +* params: + - `i32 (proxy_stream_type_t) stream_type` +* returns: + - `i32 (proxy_result_t) call_result` + +Close downstream or upstream (`stream_type`) connections in current context. + +Returns `Ok` on success. + +Returns `BadArgument` for unknown `stream_type`. + +Returns `InvalidOperation` when stream is already closed. ## HTTP (L7) extensions -### `proxy_on_http_request_headers` +Note: The same unique context identifier (`stream_id`) is shared by a pair of + HTTP request and response. + +### Callbacks optionally exposed by the Wasm module + +#### `proxy_on_http_request_headers` * params: - - `i32 (uint32_t) context_id` + - `i32 (uint32_t) stream_id` - `i32 (size_t) num_headers` - `i32 (bool) end_of_stream` * returns: - `i32 (proxy_action_t) next_action` -Called when HTTP request headers are received from the client. Headers can be retrieved using -`proxy_get_map` and/or `proxy_get_map_value`. +Called when HTTP request headers for stream `stream_id` are received from +downstream. +Headers (`num_headers` entries) can be retrieved using `proxy_get_map` and/or +`proxy_get_map_value`. -### `proxy_on_http_request_body` +Return value (`next_action`) instructs the host environment what action to take: +- `Continue` means that this HTTP request should be accepted and that HTTP + headers should be forwarded upstream. +- `EndStream` means that this HTTP request should be accepted, that HTTP headers + should be forwarded upstream and that the underlying stream should be closed + afterwards. +- `Done` means that this HTTP request should be accepted, that HTTP headers + should be forwarded upstream and that this extension shouldn't be called again + for this HTTP request. +- `Pause` instructs the host environment to pause processing until + `proxy_resume` is called. +- `Close` means that the stream should be closed immediately. + +#### `proxy_on_http_request_body` * params: - - `i32 (uint32_t) context_id` + - `i32 (uint32_t) stream_id` - `i32 (size_t) body_size` - `i32 (bool) end_of_stream` * returns: - `i32 (proxy_action_t) next_action` -Called for each chunk of HTTP request body received from the client. Request body can be retrieved -using `proxy_get_buffer`. +Called for each chunk of HTTP request body for stream `stream_id` received from +downstream. +Request body (of size `body_size`) can be retrieved using `proxy_get_buffer`. -### `proxy_on_http_request_trailers` +Return value (`next_action`) instructs the host environment what action to take: +- `Continue` means that this HTTP request body chunk should be forwarded + upstream. +- `EndStream` means that this HTTP request body chunk should be forwarded + upstream and that the underlying stream should be closed afterwards. +- `Done` means that this HTTP request body should be forwarded upstream and that + this extension shouldn't be called again for this HTTP request. +- `Pause` means that further processing should be paused until `proxy_resume` is + called. +- `WaitForMoreData` means that further processing should be paused and host + should call this callback again when it has more data. +- `WaitForEndOrFull` means that further processing should be paused and host + should call this callback again when complete HTTP request body is available + or when its internal buffers are full. +- `Close` means that the stream should be closed immediately. + +#### `proxy_on_http_request_trailers` * params: - - `i32 (uint32_t) context_id` + - `i32 (uint32_t) stream_id` - `i32 (size_t) num_trailers` - `i32 (bool) end_of_stream` * returns: - `i32 (proxy_action_t) next_action` -Called when HTTP request trailers are received from the client. Trailers can be retrieved using -`proxy_get_map` and/or `proxy_get_map_value`. +Called when HTTP request trailers for stream `stream_id` are received from +downstream. +Trailers (`num_trailers` entries) can be retrieved using `proxy_get_map` and/or +`proxy_get_map_value`. -### `proxy_on_http_request_metadata` +Return value (`next_action`) instructs the host environment what action to take: +- `Continue` means that HTTP trailers should be forwarded upstream. +- `EndStream` means that HTTP trailers should be forwarded upstream and that + the underlying stream should be closed afterwards. +- `Done` means that HTTP trailers should be forwarded upstream and that this + extension shouldn't be called again for this HTTP request. +- `Pause` instructs the host environment to pause processing until + `proxy_resume` is called. +- `Close` means that the underlying stream should be closed immediately. + +#### `proxy_on_http_request_metadata` * params: - - `i32 (uint32_t) context_id` + - `i32 (uint32_t) stream_id` - `i32 (size_t) num_elements` - - `i32 (bool) end_of_stream` * returns: - `i32 (proxy_action_t) next_action` -Called for each HTTP/2 METADATA frame received from the client. Metadata can be retrieved using -`proxy_get_map` and/or `proxy_get_map_value`. +Called for each HTTP/2 METADATA frame for stream `stream_id` received from +downstream. +Metadata (`num_elements` entries) can be retrieved using `proxy_get_map` and/or +`proxy_get_map_value`. -### `proxy_on_http_response_headers` +Return value (`next_action`) instructs the host environment what action to take: +- `Continue` means that HTTP/2 METADATA elements should be forwarded upstream. + and that + the underlying stream should be closed afterwards. +- `Done` means that HTTP/2 METADATA elements should be forwarded upstream and + that this extension shouldn't be called again for this HTTP request. +- `Pause` instructs the host environment to pause processing until + `proxy_resume` is called. +- `Close` means that the underlying stream should be closed immediately. + +#### `proxy_on_http_response_headers` * params: - - `i32 (uint32_t) context_id` + - `i32 (uint32_t) stream_id` - `i32 (size_t) num_headers` - `i32 (bool) end_of_stream` * returns: - `i32 (proxy_action_t) next_action` -Called when HTTP response headers are received from the upstream. Headers can be retrieved using -`proxy_get_map` and/or `proxy_get_map_value`. +Called when HTTP response headers for stream `stream_id` are received from +upstream. +Headers (`num_headers` entries) can be retrieved using `proxy_get_map` and/or +`proxy_get_map_value`. -### `proxy_on_http_response_body` +Return value (`next_action`) instructs the host environment what action to take: +- `Continue` means that HTTP headers should be forwarded downstream. +- `EndStream` means that HTTP headers should be forwarded downstream and that + the underlying stream should be closed afterwards. +- `Done` means that HTTP headers should be forwarded downstream and that this + extension shouldn't be called again for this HTTP response. +- `Pause` instructs the host environment to pause processing until + `proxy_resume` is called. +- `Close` means that the underlying stream should be closed immediately. + +#### `proxy_on_http_response_body` * params: - - `i32 (uint32_t) context_id` + - `i32 (uint32_t) stream_id` - `i32 (size_t) body_size` - `i32 (bool) end_of_stream` * returns: - `i32 (proxy_action_t) next_action` -Called for each chunk of HTTP response body received from the client. Response body can be retrieved -using `proxy_get_buffer`. +Called for each chunk of HTTP response body for stream `stream_id` received from +upstream. +Response body (of size `body_size`) can be retrieved using `proxy_get_buffer`. -### `proxy_on_http_response_trailers` +Return value (`next_action`) instructs the host environment what action to take: +- `Continue` means that this HTTP response body chunk should be forwarded + downstream. +- `EndStream` means that this HTTP response body chunk should be forwarded + downstream and that the underlying stream should be closed afterwards. +- `Done` means that this HTTP response body chunk should be forwarded downstream + and that this extension shouldn't be called again for this HTTP response. +- `Pause` means that further processing should be paused until `proxy_resume` is + called. +- `WaitForMoreData` means that further processing should be paused and host + should call this callback again when it has more data. +- `WaitForEndOrFull` means that further processing should be paused and host + should call this callback again when complete HTTP response body is available + or when its internal buffers are full. +- `Close` means that the underlying stream should be closed immediately. + +#### `proxy_on_http_response_trailers` * params: - - `i32 (uint32_t) context_id` + - `i32 (uint32_t) stream_id` - `i32 (size_t) num_trailers` - `i32 (bool) end_of_stream` * returns: - `i32 (proxy_action_t) next_action` -Called when HTTP response trailers are received from the upstream. Trailers can be retrieved using -`proxy_get_map` and/or `proxy_get_map_value`. +Called when HTTP response trailers for stream `stream_id` are received from +upstream. + +Trailers (`num_trailers` entries) can be retrieved using `proxy_get_map` and/or +`proxy_get_map_value`. +Return value (`next_action`) instructs the host environment what action to take: +- `Continue` means that HTTP trailers should be forwarded downstream. +- `EndStream` means that HTTP trailers should be forwarded downstream and that + the underlying stream should be closed afterwards. +- `Done` means that HTTP trailers should be forwarded downstream and that this + extension shouldn't be called again for this HTTP response. +- `Pause` instructs the host environment to pause processing until + `proxy_resume` is called. +- `Close` means that the underlying stream should be closed immediately. -### `proxy_on_http_response_metadata` +#### `proxy_on_http_response_metadata` * params: - - `i32 (uint32_t) context_id` + - `i32 (uint32_t) stream_id` - `i32 (size_t) num_elements` - - `i32 (bool) end_of_stream` * returns: - `i32 (proxy_action_t) next_action` -Called for each HTTP/2 METADATA frame received from the upstream. Metadata can be retrieved using -`proxy_get_map` and/or `proxy_get_map_value`. +Called for each HTTP/2 METADATA frame for stream `stream_id` received from +upstream. +Metadata (`num_elements` entries) can be retrieved using `proxy_get_map` and/or +`proxy_get_map_value`. -## HTTP calls +Return value (`next_action`) instructs the host environment what action to take: +- `Continue` means that HTTP/2 METADATA elements should be forwarded downstream. +- `EndStream` means that HTTP/2 METADATA elements should be forwarded downstream + and that the underlying stream should be closed afterwards. +- `Done` means that HTTP/2 METADATA elements should be forwarded downstream and + that this extension shouldn't be called again for this HTTP response. +- `Pause` instructs the host environment to pause processing until + `proxy_resume` is called. +- `Close` means that the underlying stream should be closed immediately. -### `proxy_on_http_call_response` +### Functions exposed by the host environment + +#### `proxy_send_http_response` * params: - - `i32 (uint32_t) context_id` - - `i32 (uint32_t) callout_id` - - `i32 (size_t) num_headers` - - `i32 (size_t) body_size` - - `i32 (size_t) num_trailers` + - `i32 (uint32_t) response_code` + - `i32 (const char*) response_code_details_data` + - `i32 (size_t) response_code_details_size` + - `i32 (const char*) response_body_data` + - `i32 (size_t) response_body_size` + - `i32 (const char*) additional_headers_map_data` + - `i32 (size_t) additional_headers_size` + - `i32 (uint32_t) grpc_status` * returns: - - none + - `i32 (proxy_result_t) call_result` -Called when the response to the HTTP call (`callout_id`) is received. +Sends HTTP response to the client, without forwarding request to the upstream. +Returns `Ok` on success. -## gRPC callouts +Returns `BadArgument` for invalid `response_code` and/or `grpc_status`. + +Returns `InvalidMemoryAccess` when `response_code_details_data`, +`response_code_details_size`, `response_body_data`, `response_body_size`, +`additional_headers_map_data` and/or `additional_headers_size` point to invalid +memory address. -### `proxy_on_grpc_call_response_header_metadata` +#### `proxy_resume_http_stream` * params: - - `i32 (uint32_t) context_id` - - `i32 (uint32_t) callout_id` - - `i32 (size_t) num_elemets` + - `i32 (proxy_stream_type_t) stream_type` * returns: - - none + - `i32 (proxy_result_t) call_result` + +Resume processing of paused HTTP request or response (`stream_type`) in current +context. -Called when header metadata in the response to the gRPC call (`callout_id`) is received. +Returns `Ok` on success. +Returns `BadArgument` for unknown `stream_type`. -### `proxy_on_grpc_call_response_message` +Returns `InvalidOperation` when stream wasn't paused. + +#### `proxy_close_http_stream` * params: - - `i32 (uint32_t) context_id` - - `i32 (uint32_t) callout_id` - - `i32 (size_t) message_size` + - `i32 (proxy_stream_type_t) stream_type` * returns: - - none + - `i32 (proxy_result_t) call_result` + +Close HTTP request or response (`stream_type`) in current context. + +Returns `Ok` on success. + +Returns `BadArgument` for unknown `stream_type`. + +Returns `InvalidOperation` when stream is already closed. -Called when the response to the gRPC call (`callout_id`) is received. +## Buffers and maps -### `proxy_on_grpc_call_response_trailer_metadata` +### Functions exposed by the host environment + +#### `proxy_get_buffer` * params: - - `i32 (uint32_t) context_id` - - `i32 (uint32_t) callout_id` - - `i32 (size_t) num_elements` + - `i32 (proxy_buffer_type_t) buffer_type` + - `i32 (size_t) offset` + - `i32 (size_t) max_size` + - `i32 (const char**) return_buffer_data` + - `i32 (size_t*) return_buffer_size` * returns: - - none + - `i32 (proxy_result_t) call_result` + +Returns content of the buffer `buffer_type`. At most `max_size` bytes will be +returned, starting from the `offset`. Returned bytes are written into provided +memory slice (`return_buffer_data`, `return_buffer_size`). -Called when trailer metadata in the response to the gRPC call (`callout_id`) is received. +Returns `Ok` on success. +Returns `BadArgument` for unknown `buffer_type`. -### `proxy_on_grpc_call_close` +Returns `Empty` when `buffer_type` doesn't contain any data. + +Returns `InvalidMemoryAccess` when `return_buffer_data` and/or +`return_buffer_size` point to invalid memory address. + +#### `proxy_set_buffer` * params: - - `i32 (uint32_t) context_id` - - `i32 (uint32_t) callout_id` - - `i32 (uint32_t) status_code` + - `i32 (proxy_buffer_type_t) buffer_type` + - `i32 (offset_t) offset` + - `i32 (size_t) size` + - `i32 (const char*) buffer_data` + - `i32 (size_t) buffer_size` * returns: - - none + - `i32 (proxy_result_t) call_result` -Called when the request to the gRPC call (`callout_id`) fails or if the gRPC connection is closed. +Sets content of the buffer `buffer_type` to the provided value (`buffer_data`, +`buffer_size`), replacing `size` bytes in the existing buffer, starting at the +`offset`. Host environment must adjust the size of the destination buffer +(e.g. shrink the buffer if target `size` is larger than `buffer_size`). +Returns `Ok` on success. -## Shared queue +Returns `BadArgument` for unknown `buffer_type`. + +Returns `InvalidMemoryAccess` when `buffer_data` and/or `buffer_size` point to +invalid memory address. -### `proxy_on_queue_ready` +#### `proxy_get_map` * params: - - `i32 (uint32_t) context_id` - - `i32 (uint32_t) queue_id` + - `i32 (proxy_map_type_t) map_type` + - `i32 (const char**) return_map_data` + - `i32 (size_t*) return_map_size` * returns: - - none - -Called when there is data available in the queue (`queue_id`). + - `i32 (proxy_result_t) call_result` +Returns all key-value pairs from the given map (`map_type`). -# Functions implemented in the host environment +Returns `Ok` on success. -All functions implemented in the host environment return `proxy_result_t`, which indicates the -status of the call (successful, invalid memory access, etc.), and the return values are written into -memory pointers passed in as arguments (indicated by the `return_` prefix in the specification). +Returns `BadArgument` for unknown `map_type`. +Returns `Empty` when `map_type` doesn't contain any data. -## Logging +Returns `InvalidMemoryAccess` when `return_map_data` and/or `return_map_size` +point to invalid memory address. -### `proxy_log` +#### `proxy_set_map` * params: - - `i32 (proxy_log_level_t) log_level` - - `i32 (const char*) message_data` - - `i32 (size_t) message_size` + - `i32 (proxy_map_type_t) map_type` + - `i32 (const char*) map_data` + - `i32 (size_t) map_size` * returns: - `i32 (proxy_result_t) call_result` -Log message (`message_data`, `message_size`) at the given `log_level`. +Sets all key-value pairs in the given map (`map_type`). +Returns `Ok` on success. -### `proxy_get_current_time` +Returns `BadArgument` for unknown `map_type`. + +Returns `InvalidMemoryAccess` when `map_data` and/or `map_size` point to invalid +memory address. + +#### `proxy_get_map_values` * params: - - `i32 (uint64_t*) return_current_time_nanoseconds` + - `i32 (proxy_map_type_t) map_type` + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` + - `i32 (const char**) return_values_data` + - `i32 (size_t*) return_values_size` * returns: - `i32 (proxy_result_t) call_result` -Get current time (`return_current_time`). +Returns content of the key (`key_data`, `key_size`) from the map (`map_type`). + +Returns `Ok` on success. + +Returns `BadArgument` for unknown `map_type`. +Returns `NotFound` when key (`key_data`, `key_size`) doesn't exist. -## Module lifecycle +Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `return_values_data` +and/or `return_values_size` point to invalid memory address. -### `proxy_set_effective_context` +#### `proxy_set_map_key_values` * params: - - `i32 (uint32_t) context_id` + - `i32 (proxy_map_type_t) map_type` + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` + - `i32 (const char*) values_data` + - `i32 (size_t) values_size` + - `i32 (bool) multiple_values` * returns: - `i32 (proxy_result_t) call_result` -Change the effective context to `context_id`. This function is usually used to change the context -after receiving `proxy_on_http_call_response`, `proxy_on_grpc_call_response` or -`proxy_on_queue_ready`. +Sets content of the key (`key_data`, `key_size`) in the map (`map_type`) to the +provided values (`values_data`, `values_size`). + +If `multiple_values` is `false`, then `values_data`, `values_size` contains +a single value, otherwise it contains multiple values serialized as a list. + +Returns `Ok` on success. + +Returns `BadArgument` for unknown `map_type`. +Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `values_data` and/or +`values_size` point to invalid memory address. -### `proxy_done` +#### `proxy_add_map_key_values` * params: - - none + - `i32 (proxy_map_type_t) map_type` + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` + - `i32 (const char*) values_data` + - `i32 (size_t) values_size` + - `i32 (bool) multiple_values` * returns: - `i32 (proxy_result_t) call_result` -Indicate to the host environment that Wasm VM side is done processing current context. This can be -used after returning `false` in `proxy_on_done`. +Adds new values (`values_data`, `values_size`) to the key (`key_data`, +`key_size`) in the map (`map_type`). +If `multiple_values` is `false`, then `values_data`, `values_size` contains +a single value, otherwise it contains multiple values serialized as a list. -## Timers +Returns `Ok` on success. + +Returns `BadArgument` for unknown `map_type`. + +Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `values_data` and/or +`values_size` point to invalid memory address. -### `proxy_set_tick_period` +#### `proxy_remove_map_key` * params: - - `i32 (uint32_t) tick_period` + - `i32 (proxy_map_type_t) map_type` + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` * returns: - `i32 (proxy_result_t) call_result` -Set timer period (`tick_period`). Once set, the host environment will call `proxy_on_tick` every -`tick_period` milliseconds. +Removes the key (`key_data`, `key_size`) from the map (`map_type`). +Returns `Ok` on success. -## Buffers, maps, and properties +Returns `BadArgument` for unknown `map_type`. -### `proxy_get_buffer` +Returns `InvalidMemoryAccess` when `key_data` and/or `key_size` point to invalid +memory address. + + +## Shared key-value store + +Note: Global key-value store can be always accessed using `kvstore_id` `0`. + +### Functions exposed by the host environment + +#### `proxy_open_shared_kvstore` * params: - - `i32 (proxy_buffer_type_t) buffer_type` - - `i32 (offset_t) offset` - - `i32 (size_t) max_size` - - `i32 (const char**) return_buffer_data` - - `i32 (size_t*) return_buffer_size` - - `i32 (uint32_t*) return_flags` + - `i32 (const char*) kvstore_name_data` + - `i32 (size_t) kvstore_name_size` + - `i32 (bool) create_if_not_exist` + - `i32 (uint32_t*) return_kvstore_id` * returns: - `i32 (proxy_result_t) call_result` -Get up to max_size bytes from the `buffer_type`, starting from `offset`. Bytes are written into -buffer slice (`return_buffer_data`, `return_buffer_size`), and buffer flags are written into -`return_flags`. +Opens named key-value store (`kvstore_name_data`, `kvstore_name_size`). + +If `create_if_not_exist` is `true` and there is no shared key-value store with +that name, then it will be created. + +Key's value can be set using `proxy_set_shared_kvstore_key_values` and retrieved +using `proxy_get_shared_kvstore_key_values` from the key-value store using +returned unique key-value store identifier (`return_kvstore_id`). + +Returns `Ok` on success. + +Returns `NotFound` when `create_if_not_exist` is `false` and no shared key-value +store with the given name exists. +Returns `InvalidMemoryAccess` when `kvstore_name_data`, `kvstore_name_size` +and/or `return_kvstore_id` point to invalid memory address. -### `proxy_set_buffer` +#### `proxy_get_shared_kvstore_key_values` * params: - - `i32 (proxy_buffer_type_t) buffer_type` - - `i32 (offset_t) offset` - - `i32 (size_t) size` - - `i32 (const char*) buffer_data` - - `i32 (size_t) buffer_size` - - `i32 (uint32_t) flags` + - `i32 (uint32_t) kvstore_id` + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` + - `i32 (const char**) return_values_data` + - `i32 (size_t*) return_values_size` + - `i32 (uint32_t*) return_cas` * returns: - `i32 (proxy_result_t) call_result` -Set content of the buffer `buffer_type` to the bytes (`buffer_data`, `buffer_size`), replacing -`size` bytes, starting at `offset` in the existing buffer. +Returns value of the key (`key_data`, `key_size`) from a shared key-value store +(`kvstore_id`). Returned values are written into (`return_values_data`, +`return_values_size`). The compare-and-switch value (`return_cas`) can be used +when updating key's values with `proxy_set_shared_kvstore_key_values` and +`proxy_add_shared_kvstore_key_values` and `proxy_remove_shared_kvstore_key`. + +Returns `Ok` on success. + +Returns `BadArgument` when the key-value store (`kvstore_id`) doesn't exist. + +Returns `NotFound` when the key (`key_data`, `key_size`) doesn't exist. +Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `return_values_data`, +`return_values_size` and/or `return_cas` point to invalid memory address. -### `proxy_get_map` +#### `proxy_set_shared_kvstore_key_values` * params: - - `i32 (proxy_map_type_t) map_type` - - `i32 (const char**) return_map_data` - - `i32 (size_t*) return_map_size` + - `i32 (uint32_t) kvstore_id` + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` + - `i32 (const char*) values_data` + - `i32 (size_t) values_size` + - `i32 (bool) multiple_values` + - `i32 (uint32_t) cas` * returns: - `i32 (proxy_result_t) call_result` -Get all key-value pairs from a given map (`map_type`). +Sets the values of the key (`key_data`, `key_size`) in a shared key-value store +(`kvstore_id`) to the values (`values_data`, `values_size`). + +If `multiple_values` is `false`, then `values_data`, `values_size` contains +a single value, otherwise it contains multiple values serialized as a list. + +If compare-and-switch value (`cas`) is provided and non-zero, then it must match +the current value in order for update to succeed. + +Returns `Ok` on success. + +Returns `BadArgument` when the key-value store (`kvstore_id`) doesn't exist. +Returns `CompareAndSwapMismatch` when the compare-and-switch value isn't +current. -### `proxy_set_map` +Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `values_data` and/or +`values_size` point to invalid memory address. + +#### `proxy_add_shared_kvstore_key_values` * params: - - `i32 (proxy_map_type_t) map_type` - - `i32 (const char*) map_data` - - `i32 (size_t) map_size` + - `i32 (uint32_t) kvstore_id` + - `i32 (const char*) key_data` + - `i32 (size_t) key_size` + - `i32 (const char*) values_data` + - `i32 (size_t) values_size` + - `i32 (bool) multiple_values` + - `i32 (uint32_t) cas` * returns: - `i32 (proxy_result_t) call_result` -Set all key-value pairs in a given map (`map_type`). +Adds new values (`values_data`, `values_size`) to the key (`key_data`, +`key_size`) in a shared key-value store (`kvstore_id`). +If `multiple_values` is `false`, then `values_data`, `values_size` contains +a single value, otherwise it contains multiple values serialized as a list. -### `proxy_get_map_value` +If compare-and-switch value (`cas`) is provided and non-zero, then it must match +the current value in order for update to succeed. + +Returns `Ok` on success. + +Returns `BadArgument` when the key-value store (`kvstore_id`) doesn't exist. + +Returns `CompareAndSwapMismatch` when the compare-and-switch value isn't +current. + +Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `values_data` and/or +`values_size` point to invalid memory address. + +#### `proxy_remove_shared_kvstore_key` * params: - - `i32 (proxy_map_type_t) map_type` + - `i32 (uint32_t) kvstore_id` - `i32 (const char*) key_data` - `i32 (size_t) key_size` - - `i32 (const char**) return_value_data` - - `i32 (size_t*) return_value_size` + - `i32 (uint32_t) cas` * returns: - `i32 (proxy_result_t) call_result` -Get content of key (`key_data`, `key_size`) from a given map (`map_type`). +Removes the key (`key_data`, `key_size`) from a shared key-value store +(`kvstore_id`). + +If compare-and-switch value (`cas`) is provided and non-zero, then it must match +the current value in order for update to succeed. + +Returns `Ok` on success. + +Returns `BadArgument` when the key-value store (`kvstore_id`) doesn't exist. +Returns `CompareAndSwapMismatch` when the compare-and-switch value isn't +current. -### `proxy_set_map_value` +Returns `InvalidMemoryAccess` when `key_data` and/or `key_size` point to invalid +memory address. + +#### `proxy_delete_shared_kvstore` * params: - - `i32 (proxy_map_type_t) map_type` - - `i32 (const char*) key_data` - - `i32 (size_t) key_size` - - `i32 (const char*) value_data` - - `i32 (size_t) value_size` + - `i32 (uint32_t) kvstore_id` * returns: - `i32 (proxy_result_t) call_result` -Set or replace the content of key (`key_data`, `key_size`) to the value (`value_data`, `value_size`) -in a given map (`map_type`). +Deletes previously created shared key-value store (`kvstore_id`). + +Returns `Ok` on success. + +Returns `BadArgument` when the key-value store (`kvstore_id`) doesn't exist. + + +## Shared queue + +Note: Global queue can be always accessed using `queue_id` `0`. -### `proxy_add_map_value` +### Functions exposed by the host environment + +#### `proxy_open_shared_queue` * params: - - `i32 (proxy_map_type_t) map_type` - - `i32 (const char*) key_data` - - `i32 (size_t) key_size` - - `i32 (const char*) value_data` - - `i32 (size_t) value_size` + - `i32 (const char*) queue_name_data` + - `i32 (size_t) queue_name_size` + - `i32 (bool) create_if_not_exist` + - `i32 (uint32_t*) return_queue_id` * returns: - `i32 (proxy_result_t) call_result` -Add key (`key_data`, `key_size`) with the value (`value_data`, `value_size`) to a given map -(`map_type`). +Opens shared queue with the given name (`queue_name_data`, `queue_name_size`). +If `create_if_not_exist` is `true` and there is no shared queue with that name, +then it will be created. +Items can be queued using `proxy_enqueue_shared_queue_item` and dequeued using +`proxy_dequeue_shared_queue_item` from the queue using returned unique queue +identifier (`return_queue_id`). -### `proxy_remove_map_value` +Returns `Ok` on success. + +Returns `NotFound` when `create_if_not_exist` is `false` and no shared queue +with the given name exists. + +Returns `InvalidMemoryAccess` when `queue_name_data`, `queue_name_size` and/or +`return_queue_id` point to invalid memory address. + +#### `proxy_dequeue_shared_queue_item` * params: - - `i32 (proxy_map_type_t) map_type` - - `i32 (const char*) key_data` - - `i32 (size_t) key_size` + - `i32 (uint32_t) queue_id` + - `i32 (const char**) return_payload_data` + - `i32 (size_t*) return_payload_size` * returns: - `i32 (proxy_result_t) call_result` -Remove key (`key_data`, `key_size`) from a given map (`map_type`). +Removes item from the tail of the queue (`queue_id`). Returned value is written +into memory slice (`payload_data`, `payload_size`). +Returns `Ok` on success. -### `proxy_get_property` +Returns `BadArgument` when the queue (`queue_id`) doesn't exist. + +Returns `InvalidMemoryAccess` when `return_payload_data` and/or +`return_payload_size` point to invalid memory address. + +#### `proxy_enqueue_shared_queue_item` * params: - - `i32 (const char*) property_path_data` - - `i32 (size_t) property_path_size` - - `i32 (const char**) return_property_value_data` - - `i32 (size_t*) return_property_value_size` + - `i32 (uint32_t) queue_id` + - `i32 (const char*) payload_data` + - `i32 (size_t) payload_size` * returns: - `i32 (proxy_result_t) call_result` -Get property (`property_path_data`, `property_path_size`). +Adds item (`payload_data`, `payload_size`) at the front of the queue +(`queue_id`). + +Returns `Ok` on success. + +Returns `BadArgument` when the queue (`queue_id`) doesn't exist. +Returns `InvalidMemoryAccess` when `payload_data` and/or `payload_size` point to +invalid memory address. -### `proxy_set_property` +#### `proxy_delete_shared_queue` * params: - - `i32 (const char*) property_path_data` - - `i32 (size_t) property_path_size` - - `i32 (const char*) property_value_data` - - `i32 (size_t) property_value_size` + - `i32 (uint32_t) queue_id` * returns: - `i32 (proxy_result_t) call_result` -Set property (`property_path_data`, `property_path_size`) to given value (`property_value_data`, -`property_value_size`). +Deletes previously created shared queue (`queue_id`). +Returns `Ok` on success. -## TCP/UDP/QUIC stream (L4) extensions +Returns `BadArgument` when the queue (`queue_id`) doesn't exist. -### `proxy_resume_downstream` +### Callbacks optionally exposed by the Wasm module + +#### `proxy_on_queue_ready` * params: + - `i32 (uint32_t) queue_id` +* returns: - none + +Called when new item is available in the queue (`queue_id`). + + +## Timers + +### Functions exposed by the host environment + +#### `proxy_create_timer` + +* params: + - `i32 (uint32_t) period` + - `i32 (bool) one_time` + - `i32 (uint32_t*) return_timer_id` * returns: - `i32 (proxy_result_t) call_result` -Resume processing of paused downstream. +Creates a new timer. When a timer is created as a one-time alarm (`one_time`), +then callback will be called only once after `period` milliseconds. Otherwise, +the callback is going to be called every `period` milliseconds until the timer +is deleted using `proxy_delete_timer` with the returned unique timer identifier +(`return_timer_id`). + +Returns `Ok` on success. +Returns `InvalidMemoryAccess` when `return_timer_id` points to invalid memory +address. -### `proxy_resume_upstream` +#### `proxy_delete_timer` * params: - - none + - `i32 (uint32_t) timer_id` * returns: - `i32 (proxy_result_t) call_result` -Resume processing of paused upstream. +Deletes previously created timer (`timer_id`). +Returns `Ok` on success. -## HTTP (L7) extensions +Returns `BadArgument` when the timer (`timer_id`) doesn't exist. -### `proxy_resume_http_request` +### Callbacks optionally exposed by the Wasm module + +#### `proxy_on_timer_ready` * params: + - `i32 (uint32_t) timer_id` +* returns: - none + +Called after configured period by the timer (`timer_id`) created using +`proxy_create_timer`. + + +## Stats/metrics + +### Functions exposed by the host environment + +#### `proxy_create_metric` + +* params: + - `i32 (proxy_metric_type_t) metric_type` + - `i32 (const char*) metric_name_data` + - `i32 (size_t) metric_name_size` + - `i32 (uint32_t*) return_metric_id` * returns: - `i32 (proxy_result_t) call_result` -Resume processing of paused HTTP request. +Creates metric (`metric_name_data`, `metic_name_size`) of type `metric_type`. + +It can be referred to in `proxy_get_metric_value`, `proxy_set_metric_value`, +and `proxy_increment_metric_value` using returned unique metric identifier +(`metric_id`). + +Returns `Ok` on success. +Returns `BadArgument` for unknown `metric_type`. -### `proxy_resume_http_response` +Returns `InvalidMemoryAccess` when `metric_name_data`, `metric_name_size` +and/or `return_metric_id` point to invalid memory address. + +#### `proxy_get_metric_value` * params: - - none + - `i32 (uint32_t) metric_id` + - `i32 (uint64_t*) return_value` * returns: - `i32 (proxy_result_t) call_result` -Resume processing of paused HTTP response. +Get the value of the metric (`metric_id`). + +Returns `Ok` on success. +Returns `BadArgument` when the metric (`metric_id`) doesn't exist. -### `proxy_send_http_response` +#### `proxy_set_metric_value` * params: - - `i32 (uint32_t) response_code` - - `i32 (const char*) response_code_details_data` - - `i32 (size_t) response_code_details_size` - - `i32 (const char*) response_body_data` - - `i32 (size_t) response_body_size` - - `i32 (const char*) additional_headers_map_data` - - `i32 (size_t) additional_headers_size` - - `i32 (uint32_t) grpc_status` + - `i32 (uint32_t) metric_id` + - `i64 (uint64_t) value` +* returns: + - `i32 (proxy_result_t) call_result` + +Set the value of the metric (`metric_id`) to the value (`value`). + +Returns `Ok` on success. + +Returns `BadArgument` when the metric (`metric_id`) doesn't exist. + +Returns `InvalidOperation` when the `metric_type` doesn't support setting +values. + +#### `proxy_increment_metric_value` + +* params: + - `i32 (uint32_t) metric_id` + - `i64 (int64_t) offset` +* returns: + - `i32 (proxy_result_t) call_result` + +Increment/decrement value of the metric (`metric_id`) by offset (`offset`). + +Returns `Ok` on success. + +Returns `BadArgument` when the metric (`metric_id`) doesn't exist. + +Returns `InvalidOperation` when `metric_type` doesn't support incrementing +and/or decrementing values. + +#### `proxy_delete_metric` + +* params: + - `i32 (uint32_t) metric_id` * returns: - `i32 (proxy_result_t) call_result` -Sends HTTP response without forwarding request to the upstream. +Deletes previously created metric (`metric_id`). + +Returns `Ok` on success. +Returns `BadArgument` when the metric (`metric_id`) doesn't exist. -## HTTP calls -### `proxy_dispatch_http_call` +## HTTP callouts + +### Functions exposed by the host environment + +#### `proxy_dispatch_http_call` * params: - `i32 (const char*) upstream_name_data` @@ -666,14 +1183,47 @@ Sends HTTP response without forwarding request to the upstream. * returns: - `i32 (proxy_result_t) call_result` -Dispatch a HTTP call to upstream (`upstream_name_data`, `upstream_name_size`). Once the response is -returned to the host, `proxy_on_http_call_response` will be called with a unique call identifier -(`return_callout_id`). +Dispatches a HTTP call to upstream (`upstream_name_data`, `upstream_name_size`). + +Once the response is returned to the host, `proxy_on_http_call_response` will be +called with an unique call identifier (`return_callout_id`). + +Returns `Ok` on success. +Returns `NotFound` for unknown upstream. -## gRPC calls +Returns `NotAllowed` when requests to given upstream are not allowed. -### `proxy_dispatch_grpc_call` +Returns `InvalidMemoryAccess` when `upstream_name_data`, `upstream_name_size`, +`headers_map_data`, `headers_map_size`, `body_data`, `body_size`, +`trailers_map_data`, `trailers_map_size` and/or `return_callout_id` point to +invalid memory address. + +### Callbacks optionally exposed by the Wasm module + +#### `proxy_on_http_call_response` + +* params: + - `i32 (uint32_t) callout_id` + - `i32 (size_t) num_headers` + - `i32 (size_t) body_size` + - `i32 (size_t) num_trailers` +* returns: + - none + +Called when the complete response to the HTTP call (`callout_id`) is received. + +Headers (`num_headers` entries) and trailers (`num_trailers` entries) can be +retrieved using `proxy_get_map` and/or `proxy_get_map_value`. + +Response body (of size `body_size`) can be retrieved using `proxy_get_buffer`. + + +## gRPC callouts + +### Functions exposed by the host environment + +#### `proxy_dispatch_grpc_call` * params: - `i32 (const char*) grpc_service_data` @@ -682,6 +1232,8 @@ returned to the host, `proxy_on_http_call_response` will be called with a unique - `i32 (size_t) service_name_size` - `i32 (const char*) method_data` - `i32 (size_t) method_size` + - `i32 (const char*) initial_metadata_map_data` + - `i32 (size_t) initial_metadata_map_size` - `i32 (const char*) grpc_message_data` - `i32 (size_t) grpc_message_size` - `i32 (uint32_t) timeout_milliseconds` @@ -689,14 +1241,27 @@ returned to the host, `proxy_on_http_call_response` will be called with a unique * returns: - `i32 (proxy_result_t) call_result` -Dispatch a gRPC call to a service (`service_name_data`, `service_name_size`). Once the response is -returned to the host, `proxy_on_grpc_call_response` and/or `proxy_on_grpc_call_close` will be called -with a unique call identifier (`return_callout_id`). The call identifier can also be used to cancel -outstanding requests using `proxy_cancel_grpc_call` or close outstanding request using or -`proxy_close_grpc_call`. +Dispatch a gRPC call to a service (`service_name_data`, `service_name_size`). + +Once the response is returned to the host, `proxy_on_grpc_call_response` and/or +`proxy_on_grpc_call_close` will be called with an unique call identifier +(`return_callout_id`). The unique call identifier can also be used to cancel +outstanding requests using `proxy_cancel_grpc_call` or close outstanding request +using or `proxy_close_grpc_call`. + +Returns `Ok` on success. + +Returns `NotFound` for unknown service (`service_name_data`, +`service_name_size`). +Returns `NotAllowed` when requests to given service are not allowed. -### `proxy_open_grpc_stream` +Returns `InvalidMemoryAccess` when `grpc_service_data`, `grpc_service_size`, +`service_name_data`, `service_name_size`, `method_data`, `method_size`, +`initial_metadata_map_data`, `initial_metadata_map_size`, `grpc_message_data`, +`grpc_message_size` and/or `return_callout_id` point to invalid memory address. + +#### `proxy_open_grpc_stream` * params: - `i32 (const char*) grpc_service_data` @@ -705,14 +1270,27 @@ outstanding requests using `proxy_cancel_grpc_call` or close outstanding request - `i32 (size_t) service_name_size` - `i32 (const char*) method_data` - `i32 (size_t) method_size` + - `i32 (const char*) initial_metadata_map_data` + - `i32 (size_t) initial_metadata_map_size` - `i32 (uint32_t*) return_callout_id` * returns: - `i32 (proxy_result_t) call_result` -Open a connection to the gRPC service (`service_name_data`, `service_name_size`). +Opens connection to the gRPC service (`service_name_data`, `service_name_size`). + +Returns `Ok` on success. + +Returns `NotFound` for unknown service (`service_name_data`, +`service_name_size`). +Returns `NotAllowed` when requests to given service are not allowed. -### `proxy_send_grpc_call_message` +Returns `InvalidMemoryAccess` when `grpc_service_data`, `grpc_service_size`, +`service_name_data`, `service_name_size`, `method_data`, `method_size`, +`initial_metadata_map_data`, `initial_metadata_map_size` and/or +`return_callout_id` point to invalid memory address. + +#### `proxy_send_grpc_stream_message` * params: - `i32 (uint32_t) callout_id` @@ -721,11 +1299,17 @@ Open a connection to the gRPC service (`service_name_data`, `service_name_size`) * returns: - `i32 (proxy_result_t) call_result` -Send gRPC message (`grpc_message_data`, `grpc_message_size`) on the existing gRPC stream -(`callout_id`). +Send gRPC message (`grpc_message_data`, `grpc_message_size`) on the existing +gRPC stream (`callout_id`). + +Returns `Ok` on success. +Returns `BadArgument` when the gRPC call (`callout_id`) doesn't exist. -### `proxy_cancel_grpc_call` +Returns `InvalidMemoryAccess` when `grpc_message_data` and/or +`grpc_message_size` point to invalid memory address. + +#### `proxy_cancel_grpc_call` * params: - `i32 (uint32_t) callout_id` @@ -734,8 +1318,11 @@ Send gRPC message (`grpc_message_data`, `grpc_message_size`) on the existing gRP Cancel outstanding gRPC request or stream (`callout_id`). +Returns `Ok` on success. + +Returns `BadArgument` when the gRPC call (`callout_id`) doesn't exist. -### `proxy_close_grpc_call` +#### `proxy_close_grpc_call` * params: - `i32 (uint32_t) callout_id` @@ -744,176 +1331,208 @@ Cancel outstanding gRPC request or stream (`callout_id`). Cancel outstanding gRPC request or close existing gRPC stream (`callout_id`). +Returns `Ok` on success. -## Shared Key-Value store +Returns `BadArgument` when the gRPC call (`callout_id`) doesn't exist. -### `proxy_get_shared_data` +### Callbacks optionally exposed by the Wasm module + +#### `proxy_on_grpc_call_response_header_metadata` * params: - - `i32 (const char*) key_data` - - `i32 (size_t) key_size` - - `i32 (const char**) return_value_data` - - `i32 (size_t*) return_value_size` - - `i32 (uint32_t*) return_cas` + - `i32 (uint32_t) callout_id` + - `i32 (size_t) num_elements` * returns: - - `i32 (proxy_result_t) call_result` + - none -Get shared data identified by a key (`key_data`, `key_size`). The compare-and-switch value -(`return_cas`) is returned and can be used when updating the value with `proxy_set_shared_data`. +Called when header metadata in the response to the gRPC call (`callout_id`) is +received. +Header metadata (`num_headers` entries) can be retrieved using `proxy_get_map` +and/or `proxy_get_map_value`. -### `proxy_set_shared_data` +#### `proxy_on_grpc_call_response_message` * params: - - `i32 (const char*) key_data` - - `i32 (size_t) key_size` - - `i32 (const char*) value_data` - - `i32 (size_t) value_size` - - `i32 (uint32_t) cas` + - `i32 (uint32_t) callout_id` + - `i32 (size_t) message_size` * returns: - - `i32 (proxy_result_t) call_result` - -Set shared data identified by a key (`key_data`, `key_size`) to a value (`value_data`, -`value_size`). If compare-and-switch value (`cas`) is set, then it must match the current value in -order to update to succeed. + - none +Called when the response message (of size `message_size`) to the gRPC call +(`callout_id`) is received. -## Shared queue +Content of the gRPC message (of size `data_size`) can be retrieved using +`proxy_get_buffer`. -### `proxy_register_shared_queue` +#### `proxy_on_grpc_call_response_trailer_metadata` * params: - - `i32 (const char*) queue_name_data` - - `i32 (size_t) queue_name_size` - - `i32 (uint32_t*) return_queue_id` + - `i32 (uint32_t) callout_id` + - `i32 (size_t) num_elements` * returns: - - `i32 (proxy_result_t) call_result` + - none -Register a shared queue using a given name (`queue_name_data`, `queue_name_size`). It can be -referred to in `proxy_enqueue_shared_queue` and `proxy_dequeue_shared_queue` using returned unique -queue identifier (`queue_id`). +Called when trailer metadata in the response to the gRPC call (`callout_id`) is +received. +Trailer metadata (`num_headers` entries) can be retrieved using `proxy_get_map` +and/or `proxy_get_map_value`. -### `proxy_resolve_shared_queue` +#### `proxy_on_grpc_call_close` * params: - - `i32 (const char*) queue_name_data` - - `i32 (size_t) queue_name_size` - - `i32 (uint32_t*) return_queue_id` + - `i32 (uint32_t) callout_id` + - `i32 (uint32_t) status_code` * returns: - - `i32 (proxy_result_t) call_result` + - none -Resolves existing shared queue using a given name (`queue_name_data`, `queue_name_size`). It can be -referred to in `proxy_enqueue_shared_queue` and `proxy_dequeue_shared_queue` using returned unique -queue identifier (`queue_id`). +Called when the request to the gRPC call (`callout_id`) fails or if the gRPC +connection is closed. -### `proxy_dequeue_shared_queue` +## Custom extension points + +### Callbacks optionally exposed by the Wasm module + +#### `proxy_on_custom_callback` * params: - - `i32 (uint32_t) queue_id` - - `i32 (const char**) payload_data` - - `i32 (size_t*) payload_size` + - `i32 (uint32_t) custom_callback_id` + - `i32 (size_t) parameters_size` * returns: - - `i32 (proxy_result_t) call_result` + - `i32 (uint32_t) custom_return_code` + +Called for a well-known custom callback (`custom_callback_id`). + +Callback parameters (of size `parameters_size`) can be retrieved using +`proxy_get_buffer`. -Get data (`payload_data`, `payload_size`) to the end of the queue (`queue_id`). +Return value (`custom_return_code`) is defined as part of specification for each +custom callback. Returning `0` indicates unknown `custom_callback_id`. +### Functions exposed by the host environment -### `proxy_enqueue_shared_queue` +#### `proxy_call_custom_function` * params: - - `i32 (uint32_t) queue_id` - - `i32 (const char*) payload_data` - - `i32 (size_t) payload_size` + - `i32 (uint32_t) custom_function_id` + - `i32 (const char *) parameters_data` + - `i32 (size_t) parameters_size` + - `i32 (const char**) return_results_data` + - `i32 (size_t*) return_results_size` * returns: - `i32 (proxy_result_t) call_result` -Add data (`payload_data`, `payload_size`) to the front of the queue (`queue_id`). +Calls a well-known custom function (`custom_function_id`) with provided +parameters (`parameters_data`, `parameters_size`). +Returns `Ok` on success. -### `proxy_remove_shared_queue` +Returns `NotFound` for unknown `function_id`. -* params: - - `i32 (uint32_t) queue_id` -* returns: - - `i32 (proxy_result_t) call_result` +Returns `InvalidMemoryAccess` when `parameters_data`, `parameters_size`, +`return_results_data` and/or `return_results_size` point to invalid memory +address. -Remove queue (`queue_id`). +# Serialization -## Stats/metrics +The encoding of integers is little endian. -### `proxy_define_metric` +### List of values. -* params: - - `i32 (proxy_metric_type_t) metric_type` - - `i32 (const char*) metric_name_data` - - `i32 (size_t) metric_name_size` - - `i32 (uint32_t*) return_metric_id` -* returns: - - `i32 (proxy_result_t) call_result` +List of values is serialized as: 32-bit number of elements in the list, +followed by a series of 32-bit lengths of each value, followed by a series of +payload of each value. -Define a metric using a given name (`metric_name_data`, `metic_name_size`). It can be referred to in -`proxy_get_metric`, `proxy_increment_metric` and `proxy_record_metric` using returned unique metric -identifier (`metric_id`). +e.g. `{"a", "b"}` is serialized as: `{ 0x2, 0x1, 0x1, "a", "b" }`. +### Map with multiple values. -### `proxy_get_metric` +Map with multiple values is serialized as: 32-bit number of keys in the map, +followed by a series of pairs of 32-bit lengths of each key and its serialized +list of values, followed by a series of key names and its serialized list of +values. -* params: - - `i32 (uint32_t) metric_id` - - `i32 (uint64_t*) return_value` -* returns: - - `i32 (proxy_result_t) call_result` +e.g. `{"key": {"a", "b"}}` is serialized as: +`{ 0x1, 0x3, 0x5, "k", "e", "y", 0x2, 0x1, 0x1, "a", "b" }`. -Get the value of the metric (`metric_id`). +# Built-in types -### `proxy_record_metric` +### `proxy_result_t` -* params: - - `i32 (uint32_t) metric_id` - - `i64 (uint64_t) value -* returns: - - `i32 (proxy_result_t) call_result` +* `0` - `Ok` +* `1` - `Empty` +* `2` - `NotFound` +* `3` - `NotAllowed` +* `4` - `BadArgument` +* `5` - `InvalidMemoryAccess` +* `6` - `InvalidOperation` +* `7` - `CompareAndSwapMismatch` -Set the value of the metric (`metric_id`) to the value (`value`). +### `proxy_action_t` +* `1` - `Continue` +* `2` - `EndStream` +* `3` - `Done` +* `4` - `Pause` +* `5` - `WaitForMoreData` +* `6` - `WaitForEndOrFull` +* `7` - `Close` -### `proxy_increment_metric` +### `proxy_log_level_t` -* params: - - `i32 (uint32_t) metric_id` - - `i64 (int64_t) offset -* returns: - - `i32 (proxy_result_t) call_result` +* `1` - `Trace` +* `2` - `Debug` +* `3` - `Info` +* `4` - `Warning` +* `5` - `Error` -Increment/decrement value of the metric (`metric_id`) by offset (`offset`). +### `proxy_context_type_t` +* `1` - `VmContext` +* `2` - `PluginContext` +* `3` - `StreamContext` +* `4` - `HttpContext` -### `proxy_remove_metric` +### `proxy_stream_type_t` -* params: - - `i32 (uint32_t) metric_id` -* returns: - - `i32 (proxy_result_t) call_result` +* `1` - `Downstream` +* `2` - `Upstream` +* `3` - `HttpRequest` +* `4` - `HttpResponse` -Remove the metric (`metric_id`). +### `proxy_close_source_type_t` +* `1` - `Local` +* `2` - `Remote` -## Foreign function interface (FFI): +### `proxy_buffer_type_t` -### `proxy_call_foreign_function` +* `1` - `VmConfiguration` +* `2` - `PluginConfiguration` +* `3` - `DownstreamData` +* `4` - `UpstreamData` +* `5` - `HttpRequestBody` +* `6` - `HttpResponseBody` +* `7` - `HttpCalloutResponseBody` -* params: - - `i32 (const char*) function_name_data` - - `i32 (size_t) function_name_size` - - `i32 (const char *) parameters_data` - - `i32 (size_t) parameters_size` - - `i32 (const char**) return_results_data` - - `i32 (size_t*) return_results_size` -* returns: - - `i32 (proxy_result_t) call_result` +### `proxy_map_type_t` + +* `1` - `HttpRequestHeaders` +* `2` - `HttpRequestTrailers` +* `3` - `HttpRequestMetadata` +* `4` - `HttpResponseHeaders` +* `5` - `HttpResponseTrailers` +* `6` - `HttpResponseMetadata` +* `7` - `HttpCallResponseHeaders` +* `8` - `HttpCallResponseTrailers` +* `9` - `HttpCallResponseMetadata` + +### `proxy_metric_type_t` -Call registered foreign function (`function_name_data`, `function_name_size`). +* `1` - `Counter` +* `2` - `Gauge` +* `3` - `Histogram` From f1b52539e44dafd6b55f1c6b7e1470bf6316d773 Mon Sep 17 00:00:00 2001 From: Piotr Sikora Date: Sat, 18 Jul 2020 05:18:47 +0000 Subject: [PATCH 3/4] Update ABI specification to use vectors. Signed-off-by: Piotr Sikora --- abi-versions/vNEXT/README.md | 247 +++++++++++++---------------------- 1 file changed, 89 insertions(+), 158 deletions(-) diff --git a/abi-versions/vNEXT/README.md b/abi-versions/vNEXT/README.md index 790c3ae..85df56d 100644 --- a/abi-versions/vNEXT/README.md +++ b/abi-versions/vNEXT/README.md @@ -327,8 +327,7 @@ Note: The same unique context identifier (`stream_id`) is shared by a pair of Called when HTTP request headers for stream `stream_id` are received from downstream. -Headers (`num_headers` entries) can be retrieved using `proxy_get_map` and/or -`proxy_get_map_value`. +Headers (`num_headers` entries) can be retrieved using `proxy_get_map_values`. Return value (`next_action`) instructs the host environment what action to take: - `Continue` means that this HTTP request should be accepted and that HTTP @@ -385,8 +384,7 @@ Return value (`next_action`) instructs the host environment what action to take: Called when HTTP request trailers for stream `stream_id` are received from downstream. -Trailers (`num_trailers` entries) can be retrieved using `proxy_get_map` and/or -`proxy_get_map_value`. +Trailers (`num_trailers` entries) can be retrieved using `proxy_get_map_values`. Return value (`next_action`) instructs the host environment what action to take: - `Continue` means that HTTP trailers should be forwarded upstream. @@ -409,8 +407,7 @@ Return value (`next_action`) instructs the host environment what action to take: Called for each HTTP/2 METADATA frame for stream `stream_id` received from downstream. -Metadata (`num_elements` entries) can be retrieved using `proxy_get_map` and/or -`proxy_get_map_value`. +Metadata (`num_elements` entries) can be retrieved using `proxy_get_map_values`. Return value (`next_action`) instructs the host environment what action to take: - `Continue` means that HTTP/2 METADATA elements should be forwarded upstream. @@ -434,8 +431,7 @@ Return value (`next_action`) instructs the host environment what action to take: Called when HTTP response headers for stream `stream_id` are received from upstream. -Headers (`num_headers` entries) can be retrieved using `proxy_get_map` and/or -`proxy_get_map_value`. +Headers (`num_headers` entries) can be retrieved using `proxy_get_map_values`. Return value (`next_action`) instructs the host environment what action to take: - `Continue` means that HTTP headers should be forwarded downstream. @@ -489,8 +485,7 @@ Return value (`next_action`) instructs the host environment what action to take: Called when HTTP response trailers for stream `stream_id` are received from upstream. -Trailers (`num_trailers` entries) can be retrieved using `proxy_get_map` and/or -`proxy_get_map_value`. +Trailers (`num_trailers` entries) can be retrieved using `proxy_get_map_values`. Return value (`next_action`) instructs the host environment what action to take: - `Continue` means that HTTP trailers should be forwarded downstream. @@ -513,8 +508,7 @@ Return value (`next_action`) instructs the host environment what action to take: Called for each HTTP/2 METADATA frame for stream `stream_id` received from upstream. -Metadata (`num_elements` entries) can be retrieved using `proxy_get_map` and/or -`proxy_get_map_value`. +Metadata (`num_elements` entries) can be retrieved using `proxy_get_map_values`. Return value (`next_action`) instructs the host environment what action to take: - `Continue` means that HTTP/2 METADATA elements should be forwarded downstream. @@ -534,9 +528,9 @@ Return value (`next_action`) instructs the host environment what action to take: - `i32 (uint32_t) response_code` - `i32 (const char*) response_code_details_data` - `i32 (size_t) response_code_details_size` - - `i32 (const char*) response_body_data` + - `i32 (iovec_array_t) response_body_data` - `i32 (size_t) response_body_size` - - `i32 (const char*) additional_headers_map_data` + - `i32 (iovec_array_t[]) additional_headers_map_data` - `i32 (size_t) additional_headers_size` - `i32 (uint32_t) grpc_status` * returns: @@ -595,14 +589,15 @@ Returns `InvalidOperation` when stream is already closed. - `i32 (proxy_buffer_type_t) buffer_type` - `i32 (size_t) offset` - `i32 (size_t) max_size` - - `i32 (const char**) return_buffer_data` + - `i32 (iovec_array_t*) return_buffer_data` - `i32 (size_t*) return_buffer_size` * returns: - `i32 (proxy_result_t) call_result` Returns content of the buffer `buffer_type`. At most `max_size` bytes will be -returned, starting from the `offset`. Returned bytes are written into provided -memory slice (`return_buffer_data`, `return_buffer_size`). +returned, starting from the `offset`. Returned bytes are written into memory +slices pointed by a list of vectors (`return_buffer_data`, +`return_buffer_size`). Returns `Ok` on success. @@ -619,15 +614,16 @@ Returns `InvalidMemoryAccess` when `return_buffer_data` and/or - `i32 (proxy_buffer_type_t) buffer_type` - `i32 (offset_t) offset` - `i32 (size_t) size` - - `i32 (const char*) buffer_data` + - `i32 (iovec_array_t) buffer_data` - `i32 (size_t) buffer_size` * returns: - `i32 (proxy_result_t) call_result` -Sets content of the buffer `buffer_type` to the provided value (`buffer_data`, -`buffer_size`), replacing `size` bytes in the existing buffer, starting at the -`offset`. Host environment must adjust the size of the destination buffer -(e.g. shrink the buffer if target `size` is larger than `buffer_size`). +Sets content of the buffer `buffer_type` to the values from memory slices +pointed by the provided list of vectors (`buffer_data`, `buffer_size`), +replacing `size` bytes in the existing buffer, starting at the `offset`. Host +environment must adjust the size of the destination buffer (e.g. shrink the +buffer if target `size` is larger than `buffer_size`). Returns `Ok` on success. @@ -636,108 +632,57 @@ Returns `BadArgument` for unknown `buffer_type`. Returns `InvalidMemoryAccess` when `buffer_data` and/or `buffer_size` point to invalid memory address. -#### `proxy_get_map` +#### `proxy_get_map_values` * params: - `i32 (proxy_map_type_t) map_type` - - `i32 (const char**) return_map_data` + - `i32 (iovec_array_t) keys_data` + - `i32 (size_t) keys_size` + - `i32 (iovec_array_t[]*) return_map_data` - `i32 (size_t*) return_map_size` * returns: - `i32 (proxy_result_t) call_result` -Returns all key-value pairs from the given map (`map_type`). - -Returns `Ok` on success. - -Returns `BadArgument` for unknown `map_type`. - -Returns `Empty` when `map_type` doesn't contain any data. - -Returns `InvalidMemoryAccess` when `return_map_data` and/or `return_map_size` -point to invalid memory address. - -#### `proxy_set_map` - -* params: - - `i32 (proxy_map_type_t) map_type` - - `i32 (const char*) map_data` - - `i32 (size_t) map_size` -* returns: - - `i32 (proxy_result_t) call_result` - -Sets all key-value pairs in the given map (`map_type`). - -Returns `Ok` on success. - -Returns `BadArgument` for unknown `map_type`. - -Returns `InvalidMemoryAccess` when `map_data` and/or `map_size` point to invalid -memory address. - -#### `proxy_get_map_values` +Returns map containing key-values for keys from the provided list of vectors +(`keys_data`, `keys_size`) from the map (`map_type`) in a list of lists +of vectors (`return_map_data`, `return_map_size`) in which the first element +in each list represents a key, followed by a zero or more values. -* params: - - `i32 (proxy_map_type_t) map_type` - - `i32 (const char*) key_data` - - `i32 (size_t) key_size` - - `i32 (const char**) return_values_data` - - `i32 (size_t*) return_values_size` -* returns: - - `i32 (proxy_result_t) call_result` +If the list of keys is empty, then all key-values in the map are returned. -Returns content of the key (`key_data`, `key_size`) from the map (`map_type`). +In context of HTTP header maps, the special key `"*"` can be used to retrieve +all regular HTTP headers, and the special key `":*"` can be used to retrieve +all pseudo-headers. Returns `Ok` on success. Returns `BadArgument` for unknown `map_type`. -Returns `NotFound` when key (`key_data`, `key_size`) doesn't exist. - Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `return_values_data` and/or `return_values_size` point to invalid memory address. -#### `proxy_set_map_key_values` +#### `proxy_set_map_values` * params: - `i32 (proxy_map_type_t) map_type` - - `i32 (const char*) key_data` - - `i32 (size_t) key_size` - - `i32 (const char*) values_data` - - `i32 (size_t) values_size` - - `i32 (bool) multiple_values` + - `i32 (iovec_array_t) remove_keys_data` + - `i32 (size_t) remove_keys_size` + - `i32 (iovec_array_t[]) map_data` + - `i32 (size_t) map_size` * returns: - `i32 (proxy_result_t) call_result` -Sets content of the key (`key_data`, `key_size`) in the map (`map_type`) to the -provided values (`values_data`, `values_size`). +Adds key-values from the provided list of lists of vectors (`map_data`, +`map_size`) to the given map (`map_type`). The first element in each list +represents a key, followed by a zero or more values. For the existing keys, +new values will be added to the existing ones. -If `multiple_values` is `false`, then `values_data`, `values_size` contains -a single value, otherwise it contains multiple values serialized as a list. +Keys to remove and/or which values will be replaced can be provided in an +optional list of vectors (`remove_keys_data`, `remove_keys_size`). -Returns `Ok` on success. - -Returns `BadArgument` for unknown `map_type`. - -Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `values_data` and/or -`values_size` point to invalid memory address. - -#### `proxy_add_map_key_values` - -* params: - - `i32 (proxy_map_type_t) map_type` - - `i32 (const char*) key_data` - - `i32 (size_t) key_size` - - `i32 (const char*) values_data` - - `i32 (size_t) values_size` - - `i32 (bool) multiple_values` -* returns: - - `i32 (proxy_result_t) call_result` - -Adds new values (`values_data`, `values_size`) to the key (`key_data`, -`key_size`) in the map (`map_type`). - -If `multiple_values` is `false`, then `values_data`, `values_size` contains -a single value, otherwise it contains multiple values serialized as a list. +In context of HTTP header maps, the special key `"*"` can be used to remove +all regular HTTP headers, and the special key `":*"` can be used to remove +all pseudo-headers. Returns `Ok` on success. @@ -746,24 +691,6 @@ Returns `BadArgument` for unknown `map_type`. Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `values_data` and/or `values_size` point to invalid memory address. -#### `proxy_remove_map_key` - -* params: - - `i32 (proxy_map_type_t) map_type` - - `i32 (const char*) key_data` - - `i32 (size_t) key_size` -* returns: - - `i32 (proxy_result_t) call_result` - -Removes the key (`key_data`, `key_size`) from the map (`map_type`). - -Returns `Ok` on success. - -Returns `BadArgument` for unknown `map_type`. - -Returns `InvalidMemoryAccess` when `key_data` and/or `key_size` point to invalid -memory address. - ## Shared key-value store @@ -804,7 +731,7 @@ and/or `return_kvstore_id` point to invalid memory address. - `i32 (uint32_t) kvstore_id` - `i32 (const char*) key_data` - `i32 (size_t) key_size` - - `i32 (const char**) return_values_data` + - `i32 (iovec_array_t*) return_values_data` - `i32 (size_t*) return_values_size` - `i32 (uint32_t*) return_cas` * returns: @@ -831,9 +758,8 @@ Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `return_values_data`, - `i32 (uint32_t) kvstore_id` - `i32 (const char*) key_data` - `i32 (size_t) key_size` - - `i32 (const char*) values_data` + - `i32 (iovec_array_t) values_data` - `i32 (size_t) values_size` - - `i32 (bool) multiple_values` - `i32 (uint32_t) cas` * returns: - `i32 (proxy_result_t) call_result` @@ -841,9 +767,6 @@ Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `return_values_data`, Sets the values of the key (`key_data`, `key_size`) in a shared key-value store (`kvstore_id`) to the values (`values_data`, `values_size`). -If `multiple_values` is `false`, then `values_data`, `values_size` contains -a single value, otherwise it contains multiple values serialized as a list. - If compare-and-switch value (`cas`) is provided and non-zero, then it must match the current value in order for update to succeed. @@ -863,9 +786,8 @@ Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `values_data` and/or - `i32 (uint32_t) kvstore_id` - `i32 (const char*) key_data` - `i32 (size_t) key_size` - - `i32 (const char*) values_data` + - `i32 (iovec_array_t) values_data` - `i32 (size_t) values_size` - - `i32 (bool) multiple_values` - `i32 (uint32_t) cas` * returns: - `i32 (proxy_result_t) call_result` @@ -873,9 +795,6 @@ Returns `InvalidMemoryAccess` when `key_data`, `key_size`, `values_data` and/or Adds new values (`values_data`, `values_size`) to the key (`key_data`, `key_size`) in a shared key-value store (`kvstore_id`). -If `multiple_values` is `false`, then `values_data`, `values_size` contains -a single value, otherwise it contains multiple values serialized as a list. - If compare-and-switch value (`cas`) is provided and non-zero, then it must match the current value in order for update to succeed. @@ -965,7 +884,7 @@ Returns `InvalidMemoryAccess` when `queue_name_data`, `queue_name_size` and/or * params: - `i32 (uint32_t) queue_id` - - `i32 (const char**) return_payload_data` + - `i32 (iovec_array_t*) return_payload_data` - `i32 (size_t*) return_payload_size` * returns: - `i32 (proxy_result_t) call_result` @@ -984,7 +903,7 @@ Returns `InvalidMemoryAccess` when `return_payload_data` and/or * params: - `i32 (uint32_t) queue_id` - - `i32 (const char*) payload_data` + - `i32 (iovec_array_t) payload_data` - `i32 (size_t) payload_size` * returns: - `i32 (proxy_result_t) call_result` @@ -1172,11 +1091,11 @@ Returns `BadArgument` when the metric (`metric_id`) doesn't exist. * params: - `i32 (const char*) upstream_name_data` - `i32 (size_t) upstream_name_size` - - `i32 (const char*) headers_map_data` + - `i32 (iovec_array_t[]) headers_map_data` - `i32 (size_t) headers_map_size` - - `i32 (const char*) body_data` + - `i32 (iovec_array_t) body_data` - `i32 (size_t) body_size` - - `i32 (const char*) trailers_map_data` + - `i32 (iovec_array_t[]) trailers_map_data` - `i32 (size_t) trailers_map_size` - `i32 (uint32_t) timeout_milliseconds` - `i32 (uint32_t*) return_callout_id` @@ -1214,7 +1133,7 @@ invalid memory address. Called when the complete response to the HTTP call (`callout_id`) is received. Headers (`num_headers` entries) and trailers (`num_trailers` entries) can be -retrieved using `proxy_get_map` and/or `proxy_get_map_value`. +retrieved using `proxy_get_map_values`. Response body (of size `body_size`) can be retrieved using `proxy_get_buffer`. @@ -1232,9 +1151,9 @@ Response body (of size `body_size`) can be retrieved using `proxy_get_buffer`. - `i32 (size_t) service_name_size` - `i32 (const char*) method_data` - `i32 (size_t) method_size` - - `i32 (const char*) initial_metadata_map_data` + - `i32 (iovec_array_t[]) initial_metadata_map_data` - `i32 (size_t) initial_metadata_map_size` - - `i32 (const char*) grpc_message_data` + - `i32 (iovec_array_t) grpc_message_data` - `i32 (size_t) grpc_message_size` - `i32 (uint32_t) timeout_milliseconds` - `i32 (uint32_t*) return_callout_id` @@ -1270,7 +1189,7 @@ Returns `InvalidMemoryAccess` when `grpc_service_data`, `grpc_service_size`, - `i32 (size_t) service_name_size` - `i32 (const char*) method_data` - `i32 (size_t) method_size` - - `i32 (const char*) initial_metadata_map_data` + - `i32 (iovec_array_t[]) initial_metadata_map_data` - `i32 (size_t) initial_metadata_map_size` - `i32 (uint32_t*) return_callout_id` * returns: @@ -1294,7 +1213,7 @@ Returns `InvalidMemoryAccess` when `grpc_service_data`, `grpc_service_size`, * params: - `i32 (uint32_t) callout_id` - - `i32 (const char*) grpc_message_data` + - `i32 (iovec_array_t) grpc_message_data` - `i32 (size_t) grpc_message_size` * returns: - `i32 (proxy_result_t) call_result` @@ -1341,15 +1260,15 @@ Returns `BadArgument` when the gRPC call (`callout_id`) doesn't exist. * params: - `i32 (uint32_t) callout_id` - - `i32 (size_t) num_elements` + - `i32 (size_t) num_headers` * returns: - none Called when header metadata in the response to the gRPC call (`callout_id`) is received. -Header metadata (`num_headers` entries) can be retrieved using `proxy_get_map` -and/or `proxy_get_map_value`. +Header metadata (`num_headers` entries) can be retrieved using +`proxy_get_map_values`. #### `proxy_on_grpc_call_response_message` @@ -1369,15 +1288,15 @@ Content of the gRPC message (of size `data_size`) can be retrieved using * params: - `i32 (uint32_t) callout_id` - - `i32 (size_t) num_elements` + - `i32 (size_t) num_trailers` * returns: - none Called when trailer metadata in the response to the gRPC call (`callout_id`) is received. -Trailer metadata (`num_headers` entries) can be retrieved using `proxy_get_map` -and/or `proxy_get_map_value`. +Trailer metadata (`num_trailers` entries) can be retrieved using +`proxy_get_map_values`. #### `proxy_on_grpc_call_close` @@ -1417,9 +1336,9 @@ custom callback. Returning `0` indicates unknown `custom_callback_id`. * params: - `i32 (uint32_t) custom_function_id` - - `i32 (const char *) parameters_data` + - `i32 (iovec_array_t) parameters_data` - `i32 (size_t) parameters_size` - - `i32 (const char**) return_results_data` + - `i32 (iovec_array_t*) return_results_data` - `i32 (size_t*) return_results_size` * returns: - `i32 (proxy_result_t) call_result` @@ -1440,23 +1359,35 @@ address. The encoding of integers is little endian. -### List of values. +### Vector (`iovec_t`) -List of values is serialized as: 32-bit number of elements in the list, -followed by a series of 32-bit lengths of each value, followed by a series of -payload of each value. +A vector is represented by a pair of 32-bit integers. First number points to the +address in memory where the value's data starts at, second number represents its +length. -e.g. `{"a", "b"}` is serialized as: `{ 0x2, 0x1, 0x1, "a", "b" }`. +e.g. vector pointing to `"one"` would be represented by `{0xAA, 0x03}`, assuming +that `"one"` starts at address `0xAA`. -### Map with multiple values. +### List of vectors (`iovec_array_t`) -Map with multiple values is serialized as: 32-bit number of keys in the map, -followed by a series of pairs of 32-bit lengths of each key and its serialized -list of values, followed by a series of key names and its serialized list of -values. +A list of vectors is serialized as a continuous list of `iovec_t` elements. + +e.g. a list of 2 vectors pointing to `{"one", "two"}` would be serialized as +`{{0xAA, 0x03}, {0xBB, 0x03}}`, assuming that `"one"` starts at address `0xAA`, +and `"two"` starts at address `0xBB`. + +### List of lists of vectors (`iovec_array_t[]`) + +A list of lists of vectors is serialized as a continuous list of +`iovec_array_t`, where each top-level vector points to a list of vectors. -e.g. `{"key": {"a", "b"}}` is serialized as: -`{ 0x1, 0x3, 0x5, "k", "e", "y", 0x2, 0x1, 0x1, "a", "b" }`. +e.g. a list of lists of vectors pointing to `{{"key", "a", "b"}, {"empty"}}` +would be serialized as `{{0xEE, 0x03}, {0xFF, 0x01}}`, where `0xEE` contains +`{{0xCC, 0x03}, {0xAA, 0x01}, {0xBB, 0x01}}`, which represents a list of 3 +vectors: `"key"`, `"a"`, `"b"`, assuming that `"key"` starts at address `0xCC`, +`"a"` starts at address `0xAA`, and `"b"` starts at address `0xBB`, and `0xFF` +contains `{{0xDD, 0x05}}`, which represents a list of 1 vector: `"empty"`, +assuming that `"empty"` starts at address `0xDD`. # Built-in types From cc53262df056036427476b272fb8f2438aa7975f Mon Sep 17 00:00:00 2001 From: Piotr Sikora Date: Tue, 18 Aug 2020 20:44:21 +0000 Subject: [PATCH 4/4] Clarify gRPC field names. Signed-off-by: Piotr Sikora --- abi-versions/vNEXT/README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/abi-versions/vNEXT/README.md b/abi-versions/vNEXT/README.md index 85df56d..4d9282e 100644 --- a/abi-versions/vNEXT/README.md +++ b/abi-versions/vNEXT/README.md @@ -1145,12 +1145,12 @@ Response body (of size `body_size`) can be retrieved using `proxy_get_buffer`. #### `proxy_dispatch_grpc_call` * params: - - `i32 (const char*) grpc_service_data` - - `i32 (size_t) grpc_service_size` + - `i32 (const char*) upstream_name_data` + - `i32 (size_t) upstream_name_size` - `i32 (const char*) service_name_data` - `i32 (size_t) service_name_size` - - `i32 (const char*) method_data` - - `i32 (size_t) method_size` + - `i32 (const char*) service_method_data` + - `i32 (size_t) service_method_size` - `i32 (iovec_array_t[]) initial_metadata_map_data` - `i32 (size_t) initial_metadata_map_size` - `i32 (iovec_array_t) grpc_message_data` @@ -1160,7 +1160,8 @@ Response body (of size `body_size`) can be retrieved using `proxy_get_buffer`. * returns: - `i32 (proxy_result_t) call_result` -Dispatch a gRPC call to a service (`service_name_data`, `service_name_size`). +Dispatch a call to a gRPC service (`service_name_data`, `service_name_size`) +using upstream (`upstream_name_data`, `upstream_name_size`). Once the response is returned to the host, `proxy_on_grpc_call_response` and/or `proxy_on_grpc_call_close` will be called with an unique call identifier @@ -1183,19 +1184,20 @@ Returns `InvalidMemoryAccess` when `grpc_service_data`, `grpc_service_size`, #### `proxy_open_grpc_stream` * params: - - `i32 (const char*) grpc_service_data` - - `i32 (size_t) grpc_service_size` + - `i32 (const char*) upstream_name_data` + - `i32 (size_t) upstream_name_size` - `i32 (const char*) service_name_data` - `i32 (size_t) service_name_size` - - `i32 (const char*) method_data` - - `i32 (size_t) method_size` + - `i32 (const char*) service_method_data` + - `i32 (size_t) service_method_size` - `i32 (iovec_array_t[]) initial_metadata_map_data` - `i32 (size_t) initial_metadata_map_size` - `i32 (uint32_t*) return_callout_id` * returns: - `i32 (proxy_result_t) call_result` -Opens connection to the gRPC service (`service_name_data`, `service_name_size`). +Opens connection to a gRPC service (`service_name_data`, `service_name_size`) +using upstream (`upstream_name_data`, `upstream_name_size`). Returns `Ok` on success.