From d6ed6a219b31a58526721f96195c80061d41ce54 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Wed, 2 Aug 2023 17:03:48 +0100 Subject: Initial commit libunit-wasm and example C and Rust WebAssembly modules for NGINX Unit. Co-developed-by: Timo Stark Co-developed-by: Liam Crilly Signed-off-by: Andrew Clayton --- examples/rust/upload-reflector/Cargo.toml | 12 +++ examples/rust/upload-reflector/src/lib.rs | 131 ++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 examples/rust/upload-reflector/Cargo.toml create mode 100644 examples/rust/upload-reflector/src/lib.rs (limited to 'examples/rust/upload-reflector') diff --git a/examples/rust/upload-reflector/Cargo.toml b/examples/rust/upload-reflector/Cargo.toml new file mode 100644 index 0000000..dc9d23f --- /dev/null +++ b/examples/rust/upload-reflector/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "rust-upload-reflector" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +unit-wasm = { path = "../../../src/rust", version = "0.1.0-beta" } + +[lib] +crate-type = ["cdylib"] diff --git a/examples/rust/upload-reflector/src/lib.rs b/examples/rust/upload-reflector/src/lib.rs new file mode 100644 index 0000000..9893d5a --- /dev/null +++ b/examples/rust/upload-reflector/src/lib.rs @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* + * Copyright (C) Andrew Clayton + * Copyright (C) Timo Stark + * Copyright (C) F5, Inc. + */ + +// Include RAW FFI Bindings. +// @todo: Replace this with the new native Rust API +use unit_wasm::ffi::*; + +use std::os::raw::c_char; +use std::os::raw::c_void; +use std::ptr; + +static mut CTX: luw_ctx_t = luw_ctx_t { + addr: ptr::null_mut(), + mem: ptr::null_mut(), + req: ptr::null_mut(), + resp: ptr::null_mut(), + resp_hdr: ptr::null_mut(), + resp_offset: 0, + req_buf: ptr::null_mut(), + hdrp: ptr::null_mut(), + reqp: ptr::null_mut(), +}; + +static mut TOTAL_RESPONSE_SENT: usize = 0; + +// Buffer of some size to store the copy of the request +static mut REQUEST_BUF: *mut u8 = ptr::null_mut(); + +#[no_mangle] +pub extern "C" fn luw_response_end_handler() { + unsafe { + TOTAL_RESPONSE_SENT = 0; + } +} + +#[no_mangle] +pub extern "C" fn luw_request_end_handler() { + unsafe { + if REQUEST_BUF.is_null() { + return; + } + + luw_free(REQUEST_BUF as *mut c_void); + REQUEST_BUF = ptr::null_mut(); + } +} + +pub fn upload_reflector(ctx: *mut luw_ctx_t) -> i32 { + let write_bytes: usize; + + unsafe { + // Send headers + if TOTAL_RESPONSE_SENT == 0 { + let content_len = format!("{}\0", luw_get_http_content_len(ctx)); + let defct = "application/octet-stream\0".as_ptr() as *const c_char; + let mut ct = luw_http_hdr_get_value( + ctx, + "Content-Type\0".as_ptr() as *const c_char, + ); + + if ct == ptr::null_mut() { + ct = defct; + } + + luw_http_init_headers(ctx, 2, 0); + luw_http_add_header( + ctx, + 0, + "Content-Type\0".as_ptr() as *const c_char, + ct, + ); + luw_http_add_header( + ctx, + 1, + "Content-Length\0".as_ptr() as *const c_char, + content_len.as_ptr() as *const c_char, + ); + luw_http_send_headers(ctx); + } + + write_bytes = luw_mem_fill_buf_from_req(ctx, TOTAL_RESPONSE_SENT); + TOTAL_RESPONSE_SENT += write_bytes; + + luw_http_send_response(ctx); + + if TOTAL_RESPONSE_SENT == luw_get_http_content_len(ctx) { + // Tell Unit no more data to send + luw_http_response_end(); + } + } + + return 0; +} + +#[no_mangle] +pub extern "C" fn luw_request_handler(addr: *mut u8) -> i32 { + unsafe { + let ctx: *mut luw_ctx_t = &mut CTX; + + if REQUEST_BUF.is_null() { + luw_init_ctx(ctx, addr, 0 /* Response offset */); + /* + * Take a copy of the request and use that, we do this + * in APPEND mode so we can build up request_buf from + * multiple requests. + * + * Just allocate memory for the total amount of data we + * expect to get, this includes the request structure + * itself as well as any body content. + */ + luw_set_req_buf( + ctx, + &mut REQUEST_BUF, + luw_srb_flags_t_LUW_SRB_APPEND + | luw_srb_flags_t_LUW_SRB_ALLOC + | luw_srb_flags_t_LUW_SRB_FULL_SIZE, + ); + } else { + luw_req_buf_append(ctx, addr); + } + + upload_reflector(ctx); + } + + return 0; +} -- cgit