falco_plugin/plugin/source/
wrappers.rs1use crate::plugin::base::PluginWrapper;
2use crate::plugin::error::ffi_result::FfiResult;
3use crate::plugin::source::SourcePluginInstanceWrapper;
4use crate::source::{EventBatch, EventInput, SourcePlugin, SourcePluginInstance};
5use crate::strings::cstring_writer::WriteIntoCString;
6use crate::strings::from_ptr::try_str_from_ptr;
7use falco_plugin_api::plugin_api__bindgen_ty_1 as source_plugin_api;
8use falco_plugin_api::{
9 ss_instance_t, ss_plugin_event, ss_plugin_event_input, ss_plugin_rc,
10 ss_plugin_rc_SS_PLUGIN_FAILURE, ss_plugin_rc_SS_PLUGIN_SUCCESS, ss_plugin_t,
11};
12use std::ffi::c_char;
13use std::io::Write;
14
15#[diagnostic::on_unimplemented(
23 message = "Source plugin is not exported",
24 note = "use either `source_plugin!` or `static_plugin!`"
25)]
26pub unsafe trait SourcePluginExported {}
27
28pub trait SourcePluginFallbackApi {
29 const SOURCE_API: source_plugin_api = source_plugin_api {
30 get_id: None,
31 get_event_source: None,
32 open: None,
33 close: None,
34 list_open_params: None,
35 get_progress: None,
36 event_to_string: None,
37 next_batch: None,
38 };
39
40 const IMPLEMENTS_SOURCE: bool = false;
41}
42impl<T> SourcePluginFallbackApi for T {}
43
44#[allow(missing_debug_implementations)]
45pub struct SourcePluginApi<T>(std::marker::PhantomData<T>);
46
47impl<T: SourcePlugin> SourcePluginApi<T> {
48 pub const SOURCE_API: source_plugin_api = source_plugin_api {
49 get_id: Some(plugin_get_id::<T>),
50 get_event_source: Some(plugin_get_event_source::<T>),
51 open: Some(plugin_open::<T>),
52 close: Some(plugin_close::<T>),
53 list_open_params: Some(plugin_list_open_params::<T>),
54 get_progress: Some(plugin_get_progress::<T>),
55 event_to_string: Some(plugin_event_to_string::<T>),
56 next_batch: Some(plugin_next_batch::<T>),
57 };
58
59 pub const IMPLEMENTS_SOURCE: bool = true;
60}
61
62pub extern "C-unwind" fn plugin_get_event_source<T: SourcePlugin>() -> *const c_char {
63 T::EVENT_SOURCE.as_ptr()
64}
65
66pub extern "C-unwind" fn plugin_get_id<T: SourcePlugin>() -> u32 {
67 T::PLUGIN_ID
68}
69
70pub unsafe extern "C-unwind" fn plugin_list_open_params<T: SourcePlugin>(
74 plugin: *mut ss_plugin_t,
75 rc: *mut i32,
76) -> *const c_char {
77 let plugin = plugin as *mut PluginWrapper<T>;
78 let plugin = unsafe {
79 let Some(plugin) = plugin.as_mut() else {
80 return std::ptr::null();
81 };
82 plugin
83 };
84 let Some(actual_plugin) = &mut plugin.plugin else {
85 return std::ptr::null();
86 };
87
88 match actual_plugin.plugin.list_open_params() {
89 Ok(s) => {
90 unsafe {
91 *rc = ss_plugin_rc_SS_PLUGIN_SUCCESS;
92 }
93 s.as_ptr()
94 }
95 Err(e) => {
96 unsafe {
97 *rc = e.status_code();
98 }
99 e.set_last_error(&mut plugin.error_buf);
100 std::ptr::null()
101 }
102 }
103}
104
105pub unsafe extern "C-unwind" fn plugin_open<T: SourcePlugin>(
109 plugin: *mut ss_plugin_t,
110 params: *const c_char,
111 rc: *mut ss_plugin_rc,
112) -> *mut ss_instance_t {
113 let plugin = plugin as *mut PluginWrapper<T>;
114 unsafe {
115 let Some(plugin) = plugin.as_mut() else {
116 return std::ptr::null_mut();
117 };
118 let Some(actual_plugin) = &mut plugin.plugin else {
119 return std::ptr::null_mut();
120 };
121
122 let Some(rc) = rc.as_mut() else {
123 return std::ptr::null_mut();
124 };
125
126 let params = if params.is_null() {
127 None
128 } else {
129 match try_str_from_ptr(¶ms) {
130 Ok(params) => Some(params),
131 Err(e) => {
132 plugin
133 .error_buf
134 .write_into(|w| w.write_all(e.to_string().as_bytes()))
135 .ok();
136 *rc = ss_plugin_rc_SS_PLUGIN_FAILURE;
137
138 return std::ptr::null_mut();
139 }
140 }
141 };
142
143 match actual_plugin.plugin.open(params) {
144 Ok(instance) => {
145 *rc = ss_plugin_rc_SS_PLUGIN_SUCCESS;
146 Box::into_raw(Box::new(SourcePluginInstanceWrapper {
147 instance,
148 batch: Default::default(),
149 }))
150 .cast()
151 }
152 Err(e) => {
153 e.set_last_error(&mut plugin.error_buf);
154 *rc = e.status_code();
155 std::ptr::null_mut()
156 }
157 }
158 }
159}
160
161pub unsafe extern "C-unwind" fn plugin_close<T: SourcePlugin>(
165 plugin: *mut ss_plugin_t,
166 instance: *mut ss_instance_t,
167) {
168 let plugin = plugin as *mut PluginWrapper<T>;
169 let plugin = unsafe {
170 let Some(plugin) = plugin.as_mut() else {
171 return;
172 };
173 plugin
174 };
175 let Some(actual_plugin) = &mut plugin.plugin else {
176 return;
177 };
178
179 let instance = instance as *mut SourcePluginInstanceWrapper<T::Instance>;
180 if instance.is_null() {
181 return;
182 }
183 unsafe {
184 let mut inst = Box::from_raw(instance);
185 actual_plugin.plugin.close(&mut inst.instance);
186 }
187}
188
189pub unsafe extern "C-unwind" fn plugin_next_batch<T: SourcePlugin>(
193 plugin: *mut ss_plugin_t,
194 instance: *mut ss_instance_t,
195 nevts: *mut u32,
196 evts: *mut *mut *mut ss_plugin_event,
197) -> ss_plugin_rc {
198 let plugin = plugin as *mut PluginWrapper<T>;
199 let instance = instance as *mut SourcePluginInstanceWrapper<T::Instance>;
200 unsafe {
201 let Some(plugin) = plugin.as_mut() else {
202 return ss_plugin_rc_SS_PLUGIN_FAILURE;
203 };
204 let Some(actual_plugin) = &mut plugin.plugin else {
205 return ss_plugin_rc_SS_PLUGIN_FAILURE;
206 };
207
208 let Some(instance) = instance.as_mut() else {
209 return ss_plugin_rc_SS_PLUGIN_FAILURE;
210 };
211
212 instance.batch.reset();
213 let mut batch = EventBatch::new(&instance.batch);
214 let batch_result = instance
215 .instance
216 .next_batch(&mut actual_plugin.plugin, &mut batch);
217 match batch_result {
218 Ok(()) => {
219 let events = batch.get_events();
220 *nevts = events.len() as u32;
221 *evts = events as *const _ as *mut _;
222 ss_plugin_rc_SS_PLUGIN_SUCCESS
223 }
224 Err(e) => {
225 *nevts = 0;
226 *evts = std::ptr::null_mut();
227 e.set_last_error(&mut plugin.error_buf);
228 e.status_code()
229 }
230 }
231 }
232}
233
234pub unsafe extern "C-unwind" fn plugin_get_progress<T: SourcePlugin>(
238 _plugin: *mut ss_plugin_t,
239 instance: *mut ss_instance_t,
240 progress_pct: *mut u32,
241) -> *const c_char {
242 let instance = instance as *mut SourcePluginInstanceWrapper<T::Instance>;
243 let progress = unsafe { instance.as_mut() }.map(|instance| instance.instance.get_progress());
244
245 if let Some(progress) = progress {
246 unsafe {
247 *progress_pct = (progress.value * 100.0) as u32;
248 }
249
250 match progress.detail {
251 Some(s) => s.as_ptr(),
252 None => std::ptr::null(),
253 }
254 } else {
255 unsafe {
256 *progress_pct = 0;
257 }
258
259 std::ptr::null()
260 }
261}
262
263pub unsafe extern "C-unwind" fn plugin_event_to_string<T: SourcePlugin>(
267 plugin: *mut ss_plugin_t,
268 event: *const ss_plugin_event_input,
269) -> *const c_char {
270 let plugin = plugin as *mut PluginWrapper<T>;
271 unsafe {
272 let Some(plugin) = plugin.as_mut() else {
273 return std::ptr::null();
274 };
275 let Some(actual_plugin) = &mut plugin.plugin else {
276 return std::ptr::null();
277 };
278
279 let Some(event) = event.as_ref() else {
280 return std::ptr::null();
281 };
282 let event = EventInput(*event);
283
284 match actual_plugin.plugin.event_to_string(&event) {
285 Ok(s) => {
286 plugin.string_storage = s;
287 plugin.string_storage.as_ptr()
288 }
289 Err(_) => std::ptr::null(),
290 }
291 }
292}
293
294#[macro_export]
299macro_rules! source_plugin {
300 ($ty:ty) => {
301 unsafe impl $crate::internals::source::wrappers::SourcePluginExported for $ty {}
302
303 $crate::wrap_ffi! {
304 #[unsafe(no_mangle)]
305 use $crate::internals::source::wrappers: <$ty>;
306 unsafe fn plugin_next_batch(
307 plugin: *mut falco_plugin::api::ss_plugin_t,
308 instance: *mut falco_plugin::api::ss_instance_t,
309 nevts: *mut u32,
310 evts: *mut *mut *mut falco_plugin::api::ss_plugin_event,
311 ) -> i32;
312 unsafe fn plugin_get_progress(
313 plugin: *mut falco_plugin::api::ss_plugin_t,
314 instance: *mut falco_plugin::api::ss_instance_t,
315 progress_pct: *mut u32,
316 ) -> *const ::std::ffi::c_char;
317 unsafe fn plugin_get_id() -> u32;
318 unsafe fn plugin_get_event_source() -> *const ::std::ffi::c_char;
319 unsafe fn plugin_list_open_params(
320 plugin: *mut falco_plugin::api::ss_plugin_t,
321 rc: *mut i32,
322 ) -> *const ::std::ffi::c_char;
323 unsafe fn plugin_open(
324 plugin: *mut falco_plugin::api::ss_plugin_t,
325 params: *const ::std::ffi::c_char,
326 rc: *mut i32,
327 ) -> *mut falco_plugin::api::ss_instance_t;
328 unsafe fn plugin_close(
329 plugin: *mut falco_plugin::api::ss_plugin_t,
330 instance: *mut falco_plugin::api::ss_instance_t,
331 ) -> ();
332 unsafe fn plugin_event_to_string(
333 plugin: *mut falco_plugin::api::ss_plugin_t,
334 event_input: *const falco_plugin::api::ss_plugin_event_input,
335 ) -> *const std::ffi::c_char;
336 }
337
338 #[allow(dead_code)]
339 fn __typecheck_plugin_source_api() -> falco_plugin::api::plugin_api__bindgen_ty_1 {
340 falco_plugin::api::plugin_api__bindgen_ty_1 {
341 next_batch: Some(plugin_next_batch),
342 get_progress: Some(plugin_get_progress),
343 get_id: Some(plugin_get_id),
344 get_event_source: Some(plugin_get_event_source),
345 list_open_params: Some(plugin_list_open_params),
346 open: Some(plugin_open),
347 close: Some(plugin_close),
348 event_to_string: Some(plugin_event_to_string),
349 }
350 }
351 };
352}