From 016ae29e0d69cc6b919b9011894802bb70ce5fad Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Tue, 13 Feb 2024 22:12:38 +0000 Subject: Add a wasi-http 0.2.0 large-upload component in C This makes use of the 'reactor' adaptor for filesystem access via the preopens method. Signed-off-by: Andrew Clayton --- c/wasi-http/0.2.0/large-upload/Makefile | 29 +++++++ c/wasi-http/0.2.0/large-upload/component.c | 90 +++++++++++++++++++++ .../wasi_snapshot_preview1.reactor.wasm | Bin 0 -> 96758 bytes 3 files changed, 119 insertions(+) create mode 100644 c/wasi-http/0.2.0/large-upload/Makefile create mode 100644 c/wasi-http/0.2.0/large-upload/component.c create mode 100644 c/wasi-http/0.2.0/large-upload/wasi_snapshot_preview1.reactor.wasm diff --git a/c/wasi-http/0.2.0/large-upload/Makefile b/c/wasi-http/0.2.0/large-upload/Makefile new file mode 100644 index 0000000..d84c222 --- /dev/null +++ b/c/wasi-http/0.2.0/large-upload/Makefile @@ -0,0 +1,29 @@ +# Look for wasi-sysroot in some common places, falling back +# to provided WASI_SYSROOT +ifneq ("$(wildcard /usr/wasm32-wasi)", "") + # Fedora + WASI_SYSROOT ?= /usr/wasm32-wasi +endif + +export WASI_SYSROOT + +CC = clang +CFLAGS = -Wall -Wextra -g --target=wasm32-wasi --sysroot=$(WASI_SYSROOT) +LDFLAGS = -Wl,--no-entry,--export=__heap_base,--export=__data_end,--export=malloc,--export=free,--stack-first,-z,stack-size=$$((8*1024*1024)) -mexec-model=reactor --rtlib=compiler-rt + +all: component.wasm + +bindgen: + /home/andrew/src/c/wasm/git/wit-bindgen/target/release/wit-bindgen c /home/andrew/src/c/wasm/git/wasi-http/wit --autodrop-borrows yes --world wasi:http/proxy + /home/andrew/src/c/wasm/git/wit-bindgen/target/release/wit-bindgen markdown /home/andrew/src/c/wasm/git/wasi-http/wit --world wasi:http/proxy + +.PHONY: +module.wasm: bindgen + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ proxy.c proxy_component_type.o component.c + +.PHONY: +component.wasm: module.wasm + /home/andrew/src/c/wasm/git/wasm-tools/target/release/wasm-tools component new module.wasm --adapt wasi_snapshot_preview1.reactor.wasm -o component.wasm + +clean: + rm -f component.wasm module.wasm proxy* diff --git a/c/wasi-http/0.2.0/large-upload/component.c b/c/wasi-http/0.2.0/large-upload/component.c new file mode 100644 index 0000000..148100d --- /dev/null +++ b/c/wasi-http/0.2.0/large-upload/component.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* + * component.c - Example of writing a wasi-http Wasm component + * + * Copyright (C) Andrew Clayton + * Copyright (C) F5, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "proxy.h" + +#define ex(...) \ + do { \ + printf(__VA_ARGS__); \ + return; \ + } while (0) + +void exports_wasi_http_incoming_handler_handle( + exports_wasi_http_incoming_handler_own_incoming_request_t request, + exports_wasi_http_incoming_handler_own_response_outparam_t response_out) +{ + wasi_http_types_borrow_incoming_request_t b_req; + wasi_http_types_own_incoming_body_t r_body; + wasi_http_types_borrow_incoming_body_t b_r_body; + wasi_http_types_result_own_outgoing_response_error_code_t rerr = { }; + wasi_http_types_own_fields_t hdrs; + wasi_http_types_borrow_fields_t b_hdrs; + wasi_http_types_own_fields_t fields; + wasi_http_types_own_input_stream_t in_stream; + wasi_io_streams_borrow_input_stream_t b_in_stream; + wasi_io_streams_stream_error_t in_stream_err; + proxy_list_u8_t data; + proxy_list_field_value_t f_clen; + unsigned long long total_bytes_wrote = 0; + unsigned long long content_len; + bool ok; + int fd; + + fd = open("/var/tmp/wasm-wasi-component-upload.dat", + O_CREAT|O_TRUNC|O_WRONLY, 0666); + + b_req = wasi_http_types_borrow_incoming_request(request); + + hdrs = wasi_http_types_method_incoming_request_headers(b_req); + b_hdrs = wasi_http_types_borrow_fields(hdrs); + + wasi_http_types_method_fields_get( + b_hdrs, + &(proxy_string_t){ .ptr = (uint8_t *)"content-length", + .len = strlen("content-length") }, + &f_clen); + + content_len = strtoull((const char *)f_clen.ptr[0].ptr, NULL, 10); + + ok = wasi_http_types_method_incoming_request_consume(b_req, &r_body); + if (!ok) + ex("wasi_http_types_method_incoming_request_consume() failed\n"); + b_r_body = wasi_http_types_borrow_incoming_body(r_body); + ok = wasi_http_types_method_incoming_body_stream(b_r_body, &in_stream); + if (!ok) + ex("wasi_http_types_method_incoming_body_stream() failed\n"); + b_in_stream = wasi_io_streams_borrow_input_stream(in_stream); + + do { + ok = wasi_io_streams_method_input_stream_blocking_read( + b_in_stream, + 8 * 1024*1024, + &data, + &in_stream_err); + if (!ok) + break; + + write(fd, data.ptr, data.len); + total_bytes_wrote += data.len; + } while (total_bytes_wrote < content_len); + + fields = wasi_http_types_constructor_fields(); + wasi_http_types_constructor_outgoing_response(fields); + wasi_http_types_static_response_outparam_set(response_out, &rerr); + + close(fd); +} diff --git a/c/wasi-http/0.2.0/large-upload/wasi_snapshot_preview1.reactor.wasm b/c/wasi-http/0.2.0/large-upload/wasi_snapshot_preview1.reactor.wasm new file mode 100644 index 0000000..0717d98 Binary files /dev/null and b/c/wasi-http/0.2.0/large-upload/wasi_snapshot_preview1.reactor.wasm differ -- cgit