1use std::ffi::CString;
2use std::os::raw::c_char;
3use std::os::raw::c_int;
4use std::sync::atomic::{AtomicI32, Ordering};
5use std::sync::Arc;
6use tide::{Middleware, Next, Request, Result};
7
8#[derive(Debug, Clone)]
17pub struct USDTMiddleware {
18 reqid: Arc<AtomicI32>,
19}
20impl USDTMiddleware {
21 pub fn new() -> Self {
23 Self {
24 reqid: Arc::new(<AtomicI32>::new(1)),
25 }
26 }
27}
28
29#[tide::utils::async_trait]
30impl<State: Clone + Send + Sync + 'static> Middleware<State> for USDTMiddleware {
31 async fn handle(&self, req: Request<State>, next: Next<'_, State>) -> Result {
32 let count = self.reqid.fetch_add(1, Ordering::SeqCst);
34 let path = CString::new(req.url().path().to_owned()).expect("CString::new path failed");
35 let method =
36 CString::new(req.method().to_string()).expect("CString::new method failed");
37 let req_headers_coll = req
38 .iter()
39 .map(|h| format!("{:?};", h))
40 .collect::<Vec<String>>()
41 .join("; ");
42 let req_headers = CString::new(req_headers_coll).expect("CString::new header failed");
43 unsafe {
44 startroute(method.as_ptr(), path.as_ptr(), count, req_headers.as_ptr());
45 }
46
47 let res = next.run(req).await;
48 let status = res.status() as i32;
49 let res_headers_coll = res
50 .iter()
51 .map(|h| format!("{:?};", h))
52 .collect::<Vec<String>>()
53 .join("; ");
54 let res_headers = CString::new(res_headers_coll).expect("CString::new header failed");
55 unsafe {
56 endroute(
57 method.as_ptr(),
58 path.as_ptr(),
59 count,
60 status,
61 res_headers.as_ptr(),
62 );
63 }
64 self.reqid.load(Ordering::SeqCst);
65 Ok(res)
66 }
68}
69
70extern "C" {
71 fn startroute(method: *const c_char, path: *const c_char, reqid: c_int, headers: *const c_char);
72 fn endroute(
73 method: *const c_char,
74 path: *const c_char,
75 reqid: c_int,
76 status: c_int,
77 headers: *const c_char,
78 );
79 fn fire(tag: *const c_char, data: *const c_char);
80}
81pub fn probe(tag: String, data: String) {
89 let c_data = CString::new(data).expect("CString::new data failed");
90 let c_tag = CString::new(tag).expect("CString::new tag failed");
91 unsafe {
92 fire(c_tag.as_ptr(), c_data.as_ptr());
93 }
94}