falco_plugin/listen/
wrappers.rs1use crate::base::wrappers::PluginWrapper;
2use crate::error::ffi_result::FfiResult;
3use crate::error::panic::catch_panic;
4use crate::listen::CaptureListenInput;
5use crate::listen::CaptureListenPlugin;
6use falco_plugin_api::{
7 plugin_api__bindgen_ty_5 as listen_plugin_api, ss_plugin_capture_listen_input, ss_plugin_rc,
8 ss_plugin_rc_SS_PLUGIN_FAILURE, ss_plugin_rc_SS_PLUGIN_SUCCESS, ss_plugin_t,
9};
10use std::panic::AssertUnwindSafe;
11
12#[diagnostic::on_unimplemented(
20 message = "Capture listen plugin is not exported",
21 note = "use either `capture_listen_plugin!` or `static_plugin!`"
22)]
23pub unsafe trait CaptureListenPluginExported {}
24
25pub trait CaptureListenFallbackApi {
26 const LISTEN_API: listen_plugin_api = listen_plugin_api {
27 capture_open: None,
28 capture_close: None,
29 };
30
31 const IMPLEMENTS_LISTEN: bool = false;
32}
33
34impl<T> CaptureListenFallbackApi for T {}
35
36#[derive(Debug)]
37pub struct CaptureListenApi<T>(std::marker::PhantomData<T>);
38impl<T: CaptureListenPlugin + 'static> CaptureListenApi<T> {
39 pub const LISTEN_API: listen_plugin_api = listen_plugin_api {
40 capture_open: Some(plugin_capture_open::<T>),
41 capture_close: Some(plugin_capture_close::<T>),
42 };
43
44 pub const IMPLEMENTS_LISTEN: bool = true;
45}
46
47pub unsafe extern "C" fn plugin_capture_open<T: CaptureListenPlugin>(
48 plugin: *mut ss_plugin_t,
49 listen_input: *const ss_plugin_capture_listen_input,
50) -> ss_plugin_rc {
51 let plugin = unsafe {
52 let Some(plugin) = (plugin as *mut PluginWrapper<T>).as_mut() else {
53 return ss_plugin_rc_SS_PLUGIN_FAILURE;
54 };
55 plugin
56 };
57
58 let Some(actual_plugin) = &mut plugin.plugin else {
59 return ss_plugin_rc_SS_PLUGIN_FAILURE;
60 };
61
62 let listen_input = unsafe {
63 let Ok(listen_input) =
64 CaptureListenInput::try_from(listen_input, actual_plugin.last_error.clone())
65 else {
66 return ss_plugin_rc_SS_PLUGIN_FAILURE;
67 };
68 listen_input
69 };
70
71 if let Err(e) = catch_panic(AssertUnwindSafe(|| {
72 actual_plugin.plugin.capture_open(&listen_input)
73 })) {
74 e.set_last_error(&mut plugin.error_buf);
75 return e.status_code();
76 }
77
78 ss_plugin_rc_SS_PLUGIN_SUCCESS
79}
80
81pub unsafe extern "C" fn plugin_capture_close<T: CaptureListenPlugin>(
82 plugin: *mut ss_plugin_t,
83 listen_input: *const ss_plugin_capture_listen_input,
84) -> ss_plugin_rc {
85 let plugin = unsafe {
86 let Some(plugin) = (plugin as *mut PluginWrapper<T>).as_mut() else {
87 return ss_plugin_rc_SS_PLUGIN_FAILURE;
88 };
89 plugin
90 };
91
92 let Some(actual_plugin) = &mut plugin.plugin else {
93 return ss_plugin_rc_SS_PLUGIN_FAILURE;
94 };
95
96 let listen_input = unsafe {
97 let Ok(listen_input) =
98 CaptureListenInput::try_from(listen_input, actual_plugin.last_error.clone())
99 else {
100 return ss_plugin_rc_SS_PLUGIN_FAILURE;
101 };
102 listen_input
103 };
104
105 if let Err(e) = catch_panic(AssertUnwindSafe(|| {
106 actual_plugin.plugin.capture_close(&listen_input)
107 })) {
108 e.set_last_error(&mut plugin.error_buf);
109 return e.status_code();
110 }
111
112 ss_plugin_rc_SS_PLUGIN_SUCCESS
113}
114
115#[macro_export]
121macro_rules! capture_listen_plugin {
122 ($ty:ty) => {
123 unsafe impl $crate::listen::wrappers::CaptureListenPluginExported for $ty {}
124
125 $crate::wrap_ffi! {
126 #[unsafe(no_mangle)]
127 use $crate::listen::wrappers: <$ty>;
128
129 unsafe fn plugin_capture_open(
130 plugin: *mut falco_plugin::api::ss_plugin_t,
131 listen_input: *const falco_plugin::api::ss_plugin_capture_listen_input,
132 ) -> falco_plugin::api::ss_plugin_rc;
133 unsafe fn plugin_capture_close(
134 plugin: *mut falco_plugin::api::ss_plugin_t,
135 listen_input: *const falco_plugin::api::ss_plugin_capture_listen_input,
136 ) -> falco_plugin::api::ss_plugin_rc;
137 }
138
139 #[allow(dead_code)]
140 fn __typecheck_plugin_listen_api() -> falco_plugin::api::plugin_api__bindgen_ty_5 {
141 falco_plugin::api::plugin_api__bindgen_ty_5 {
142 capture_open: Some(plugin_capture_open),
143 capture_close: Some(plugin_capture_close),
144 }
145 }
146 };
147}