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