about summary refs log tree commit diff
path: root/parrot_module/src/lib.rs
blob: 38148ae3c1dc741fa61f67203c58ab44928a6901 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use std::ffi::{self, CStr, CString};

#[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/plain".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();

	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();

		// While debugging I removed the format!() because it was SIGSEGVing
		// as the String it allocated freed, and now that this is here it can stay
		ret.push_str(&k);
		ret.push(':');
		ret.push(' ');
		ret.push_str(&v);
		ret.push('\n')
	}

	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,
	};

	let boxed = Box::new(resp);
	Box::<ModuleResponse>::into_raw(boxed)
}

#[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);
}