From b79b84ce06ee34b5957d7f19aa19ebeff2af1df9 Mon Sep 17 00:00:00 2001 From: gennyble Date: Thu, 27 Mar 2025 05:11:46 -0500 Subject: add smalldog as the module ffi crate --- stats_module/Cargo.toml | 1 + stats_module/src/lib.rs | 99 +++++++++++-------------------------------------- 2 files changed, 23 insertions(+), 77 deletions(-) (limited to 'stats_module') diff --git a/stats_module/Cargo.toml b/stats_module/Cargo.toml index ea0f965..95b6d41 100644 --- a/stats_module/Cargo.toml +++ b/stats_module/Cargo.toml @@ -10,3 +10,4 @@ crate-type = ["cdylib"] [dependencies] rusqlite = { version = "0.34.0", features = ["bundled", "time"] } time = "0.3.40" +smalldog = { path = "../smalldog" } diff --git a/stats_module/src/lib.rs b/stats_module/src/lib.rs index 18c0e63..96cbaa9 100644 --- a/stats_module/src/lib.rs +++ b/stats_module/src/lib.rs @@ -1,55 +1,20 @@ -use std::{ - ffi::{self, CStr, CString}, - sync::Mutex, -}; +use std::ffi::CStr; use rusqlite::{Connection, params}; +use smalldog::{ModuleRequest, ModuleResponse, Request, Response}; use time::{Duration, OffsetDateTime}; -#[repr(C)] -struct ModuleRequest<'req> { - headers_len: ffi::c_ulong, - headers: &'req [[*const ffi::c_char; 2]], - body_len: ffi::c_ulong, - body: *const u8, -} - -#[repr(C)] -struct ModuleResponse { - status: ffi::c_ushort, - headers_len: ffi::c_ulong, - headers: &'static [[*const ffi::c_char; 2]], - body_len: ffi::c_ulong, - body: *const u8, -} - -const HEADERS: &'static [[*const ffi::c_char; 2]] = - &[[c"Content-Type".as_ptr(), c"text/html".as_ptr()]]; - #[unsafe(no_mangle)] extern "C" fn cgi_handle(req: *const ModuleRequest) -> *const ModuleResponse { - let mut ret = String::new(); - - // unwrap is bad here - let reqref = unsafe { req.as_ref() }.unwrap(); - - let mut stats_path = None; - for idx in 0..reqref.headers_len { - let kvarr = reqref.headers[idx as usize]; - let k = unsafe { CStr::from_ptr(kvarr[0]) }.to_string_lossy(); - let v = unsafe { CStr::from_ptr(kvarr[1]) }.to_string_lossy(); - - match k.as_ref() { - "CORGI_STATS_DB" => stats_path = Some(v.into_owned()), - _ => (), - } - } + let mut response = Response::new(); - let db = if let Some(path) = stats_path { + let request = Request::from_mod_request(req); + let db = if let Some(path) = request.header("CORGI_STATS_DB") { Connection::open(path).unwrap() } else { - return make_error(500, c"could not open stats database"); + return make_error(500, "could not open stats database"); }; + let now = OffsetDateTime::now_utc(); let fifteen_ago = now - Duration::minutes(15); @@ -67,52 +32,32 @@ extern "C" fn cgi_handle(req: *const ModuleRequest) -> *const ModuleResponse { agents.sort_by(|a, b| a.0.cmp(&b.0).reverse()); - ret.push_str("

In the last fifteen minutes:

");
-	ret.push_str("total | req/m | agent\n");
+	response.push_str("

In the last fifteen minutes:

");
+	response.push_str("total | req/m | agent\n");
 	for (count, agent) in &agents {
-		ret.push_str(&format!(
+		response.push_str(&format!(
 			"{count:<5} | {:<5.1} | {agent}\n",
 			*count as f32 / 15.0
 		));
 	}
-	ret.push_str("

"); - - let body = CString::new(ret).unwrap(); - - let resp = ModuleResponse { - status: 200, - headers_len: 1, - headers: HEADERS, - body_len: body.as_bytes().len() as u64, - body: body.into_raw() as *const u8, - }; + response.push_str("

"); - let boxed = Box::new(resp); - Box::::into_raw(boxed) + response.into_mod_response(200) } -fn make_error>(code: u16, msg: S) -> *const ModuleResponse { - let body = msg.into(); +fn make_error>(code: u16, msg: S) -> *const ModuleResponse { + unsafe { + smalldog::HEADERS[0][0] = c"Content-Length".as_ptr(); + smalldog::HEADERS[0][1] = c"text/html".as_ptr(); + } - let resp = ModuleResponse { - status: code, - headers_len: 1, - headers: HEADERS, - body_len: body.as_bytes().len() as u64, - body: body.into_raw() as *const u8, - }; + let mut response = Response::new(); + response.push_str(msg.as_ref()); - let boxed = Box::new(resp); - Box::::into_raw(boxed) + response.into_mod_response(code) } #[unsafe(no_mangle)] -extern "C" fn cgi_cleanup(req: *const ModuleResponse) { - // from_raw what we need to here so that these get dropped - let boxed = unsafe { Box::from_raw(req as *mut ModuleResponse) }; - let body = unsafe { CString::from_raw(boxed.body as *mut i8) }; - - // Explicitly calling drop here to feel good about myself - drop(body); - drop(boxed); +extern "C" fn cgi_cleanup(response: *const ModuleResponse) { + Response::cleanup(response); } -- cgit 1.4.1-3-g733a5