From e99854afdf555678df5af149e53659c5b30a2f6d Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Wed, 9 Aug 2023 16:59:50 +0100 Subject: Wasm: Wire up Wasm language module support to the config system. This exposes various WebAssembly language module specific options. The application type is "wasm". There is a "module" option that is required, this specifies the full path to the WebAssembly module to be run. This module should be in binary format, i.e a .wasm file. There are also currently eight function handlers that can be specified. Three of them are _required_ 1) request_handler The main driving function. This may be called multiple times for a single HTTP request if the request is larger than the shared memory. 2) malloc_handler Used to allocate a chunk of memory at language module startup. This memory is allocated from the WASM modules address space and is what is sued for communicating between the WASM module (the guest) and Unit (the host). 3) free_handler Used to free the memory from above at language module shutdown. Then there are the following five _optional_ handlers 1) module_init_handler If set, called at language module startup. 2) module_end_handler If set, called at language module shutdown. 3) request_init_handler If set, called at the start of request. Called only once per HTTP request. 4) request_end_handler If set, called once all of a request has been sent to the WASM module. 5) response_end_handler If set, called at the end of a request, once the WASM module has sent all its headers and data. Example config "applications": { "luw-echo-request": { "type": "wasm", "module": "/path/to/unit-wasm/examples/c/luw-echo-request.wasm", "request_handler": "luw_request_handler", "malloc_handler": "luw_malloc_handler", "free_handler": "luw_free_handler", "module_init_handler": "luw_module_init_handler", "module_end_handler": "luw_module_end_handler", } } Reviewed-by: Alejandro Colomar Signed-off-by: Andrew Clayton --- src/nxt_application.c | 3 +++ src/nxt_conf_validation.c | 39 ++++++++++++++++++++++++++++++++++++ src/nxt_main_process.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/src/nxt_application.c b/src/nxt_application.c index ffa8eb53..872e387a 100644 --- a/src/nxt_application.c +++ b/src/nxt_application.c @@ -1099,6 +1099,9 @@ nxt_app_parse_type(u_char *p, size_t length) } else if (nxt_str_eq(&str, "java", 4)) { return NXT_APP_JAVA; + + } else if (nxt_str_eq(&str, "wasm", 4)) { + return NXT_APP_WASM; } return NXT_APP_UNKNOWN; diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 09f5598e..0603c98d 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -1049,6 +1049,44 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_java_members[] = { }; +static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_members[] = { + { + .name = nxt_string("module"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, { + .name = nxt_string("request_handler"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + },{ + .name = nxt_string("malloc_handler"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, { + .name = nxt_string("free_handler"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + }, { + .name = nxt_string("module_init_handler"), + .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("module_end_handler"), + .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("request_init_handler"), + .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("request_end_handler"), + .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("response_end_handler"), + .type = NXT_CONF_VLDT_STRING, + }, + + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members) +}; + + static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = { { .name = nxt_string("type"), @@ -2562,6 +2600,7 @@ nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name, { nxt_conf_vldt_object, nxt_conf_vldt_perl_members }, { nxt_conf_vldt_object, nxt_conf_vldt_ruby_members }, { nxt_conf_vldt_object, nxt_conf_vldt_java_members }, + { nxt_conf_vldt_object, nxt_conf_vldt_wasm_members }, }; ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c index 7cba08d4..b7a93341 100644 --- a/src/nxt_main_process.c +++ b/src/nxt_main_process.c @@ -323,6 +323,55 @@ static nxt_conf_map_t nxt_java_app_conf[] = { }; +static nxt_conf_map_t nxt_wasm_app_conf[] = { + { + nxt_string("module"), + NXT_CONF_MAP_CSTRZ, + offsetof(nxt_common_app_conf_t, u.wasm.module), + }, + { + nxt_string("request_handler"), + NXT_CONF_MAP_CSTRZ, + offsetof(nxt_common_app_conf_t, u.wasm.request_handler), + }, + { + nxt_string("malloc_handler"), + NXT_CONF_MAP_CSTRZ, + offsetof(nxt_common_app_conf_t, u.wasm.malloc_handler), + }, + { + nxt_string("free_handler"), + NXT_CONF_MAP_CSTRZ, + offsetof(nxt_common_app_conf_t, u.wasm.free_handler), + }, + { + nxt_string("module_init_handler"), + NXT_CONF_MAP_CSTRZ, + offsetof(nxt_common_app_conf_t, u.wasm.module_init_handler), + }, + { + nxt_string("module_end_handler"), + NXT_CONF_MAP_CSTRZ, + offsetof(nxt_common_app_conf_t, u.wasm.module_end_handler), + }, + { + nxt_string("request_init_handler"), + NXT_CONF_MAP_CSTRZ, + offsetof(nxt_common_app_conf_t, u.wasm.request_init_handler), + }, + { + nxt_string("request_end_handler"), + NXT_CONF_MAP_CSTRZ, + offsetof(nxt_common_app_conf_t, u.wasm.request_end_handler), + }, + { + nxt_string("response_end_handler"), + NXT_CONF_MAP_CSTRZ, + offsetof(nxt_common_app_conf_t, u.wasm.response_end_handler), + }, +}; + + static nxt_conf_app_map_t nxt_app_maps[] = { { nxt_nitems(nxt_external_app_conf), nxt_external_app_conf }, { nxt_nitems(nxt_python_app_conf), nxt_python_app_conf }, @@ -330,6 +379,7 @@ static nxt_conf_app_map_t nxt_app_maps[] = { { nxt_nitems(nxt_perl_app_conf), nxt_perl_app_conf }, { nxt_nitems(nxt_ruby_app_conf), nxt_ruby_app_conf }, { nxt_nitems(nxt_java_app_conf), nxt_java_app_conf }, + { nxt_nitems(nxt_wasm_app_conf), nxt_wasm_app_conf }, }; -- cgit