falco_plugin/plugin/async_event/
async_handler.rs

1use crate::plugin::error::as_result::AsResult;
2use crate::strings::from_ptr::try_str_from_ptr;
3use anyhow::Context;
4use falco_event::events::EventToBytes;
5use falco_plugin_api::{ss_plugin_event, ss_plugin_owner_t, ss_plugin_rc, PLUGIN_MAX_ERRLEN};
6use std::ffi::c_char;
7
8/// # A handle to emit asynchronous events
9///
10/// This handle gets created from the asynchronous event handler. Whenever you have
11/// an event to submit to the main event loop, call [`AsyncHandler::emit`].
12#[derive(Debug, Clone)]
13pub struct AsyncHandler {
14    pub(crate) owner: *mut ss_plugin_owner_t,
15    pub(crate) raw_handler: unsafe extern "C-unwind" fn(
16        o: *mut ss_plugin_owner_t,
17        evt: *const ss_plugin_event,
18        err: *mut c_char,
19    ) -> ss_plugin_rc,
20}
21
22unsafe impl Send for AsyncHandler {}
23unsafe impl Sync for AsyncHandler {}
24
25impl AsyncHandler {
26    /// # Emit an event asynchronously
27    ///
28    /// Submit an event to the main event loop asynchronously
29    ///
30    /// This method returns an error if and only if the asynchronous handler
31    /// returns an error.
32    pub fn emit(&self, event: impl EventToBytes) -> Result<(), anyhow::Error> {
33        let mut err = [0 as c_char; PLUGIN_MAX_ERRLEN as usize];
34        let mut buf = Vec::new();
35        let err_ptr = &err as *const [c_char] as *const c_char;
36
37        event.write(&mut buf)?;
38        match unsafe {
39            (self.raw_handler)(self.owner, buf.as_ptr() as *const _, err.as_mut_ptr()).as_result()
40        } {
41            Ok(()) => Ok(()),
42            Err(e) => {
43                let msg = try_str_from_ptr(&err_ptr)?;
44                Err(e).context(msg.to_string())
45            }
46        }
47    }
48}