diff options
Diffstat (limited to 'examples/rust/upload-reflector/src/lib.rs')
-rw-r--r-- | examples/rust/upload-reflector/src/lib.rs | 131 |
1 files changed, 131 insertions, 0 deletions
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; +} |