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 Some(plugin) = plugin.as_mut() else {
79 return std::ptr::null();
80 };
81 let Some(ref mut actual_plugin) = &mut plugin.plugin else {
82 return std::ptr::null();
83 };
84
85 match actual_plugin.plugin.list_open_params() {
86 Ok(s) => {
87 unsafe {
88 *rc = ss_plugin_rc_SS_PLUGIN_SUCCESS;
89 }
90 s.as_ptr()
91 }
92 Err(e) => {
93 unsafe {
94 *rc = e.status_code();
95 }
96 e.set_last_error(&mut plugin.error_buf);
97 std::ptr::null()
98 }
99 }
100}
101
102pub unsafe extern "C-unwind" fn plugin_open<T: SourcePlugin>(
106 plugin: *mut ss_plugin_t,
107 params: *const c_char,
108 rc: *mut ss_plugin_rc,
109) -> *mut ss_instance_t {
110 let plugin = plugin as *mut PluginWrapper<T>;
111 unsafe {
112 let Some(plugin) = plugin.as_mut() else {
113 return std::ptr::null_mut();
114 };
115 let Some(ref mut actual_plugin) = &mut plugin.plugin else {
116 return std::ptr::null_mut();
117 };
118
119 let Some(rc) = rc.as_mut() else {
120 return std::ptr::null_mut();
121 };
122
123 let params = if params.is_null() {
124 None
125 } else {
126 match try_str_from_ptr(¶ms) {
127 Ok(params) => Some(params),
128 Err(e) => {
129 plugin
130 .error_buf
131 .write_into(|w| w.write_all(e.to_string().as_bytes()))
132 .ok();
133 *rc = ss_plugin_rc_SS_PLUGIN_FAILURE;
134
135 return std::ptr::null_mut();
136 }
137 }
138 };
139
140 match actual_plugin.plugin.open(params) {
141 Ok(instance) => {
142 *rc = ss_plugin_rc_SS_PLUGIN_SUCCESS;
143 Box::into_raw(Box::new(SourcePluginInstanceWrapper {
144 instance,
145 batch: Default::default(),
146 }))
147 .cast()
148 }
149 Err(e) => {
150 e.set_last_error(&mut plugin.error_buf);
151 *rc = e.status_code();
152 std::ptr::null_mut()
153 }
154 }
155 }
156}
157
158pub unsafe extern "C-unwind" fn plugin_close<T: SourcePlugin>(
162 plugin: *mut ss_plugin_t,
163 instance: *mut ss_instance_t,
164) {
165 let plugin = plugin as *mut PluginWrapper<T>;
166 let Some(plugin) = plugin.as_mut() else {
167 return;
168 };
169 let Some(ref mut actual_plugin) = &mut plugin.plugin else {
170 return;
171 };
172
173 let instance = instance as *mut SourcePluginInstanceWrapper<T::Instance>;
174 if instance.is_null() {
175 return;
176 }
177 unsafe {
178 let mut inst = Box::from_raw(instance);
179 actual_plugin.plugin.close(&mut inst.instance);
180 }
181}
182
183pub unsafe extern "C-unwind" fn plugin_next_batch<T: SourcePlugin>(
187 plugin: *mut ss_plugin_t,
188 instance: *mut ss_instance_t,
189 nevts: *mut u32,
190 evts: *mut *mut *mut ss_plugin_event,
191) -> ss_plugin_rc {
192 let plugin = plugin as *mut PluginWrapper<T>;
193 let instance = instance as *mut SourcePluginInstanceWrapper<T::Instance>;
194 unsafe {
195 let Some(plugin) = plugin.as_mut() else {
196 return ss_plugin_rc_SS_PLUGIN_FAILURE;
197 };
198 let Some(ref mut actual_plugin) = &mut plugin.plugin else {
199 return ss_plugin_rc_SS_PLUGIN_FAILURE;
200 };
201
202 let Some(instance) = instance.as_mut() else {
203 return ss_plugin_rc_SS_PLUGIN_FAILURE;
204 };
205
206 instance.batch.reset();
207 let mut batch = EventBatch::new(&mut instance.batch);
208 match instance
209 .instance
210 .next_batch(&mut actual_plugin.plugin, &mut batch)
211 {
212 Ok(()) => {
213 let events = batch.get_events();
214 *nevts = events.len() as u32;
215 *evts = events as *const _ as *mut _;
216 ss_plugin_rc_SS_PLUGIN_SUCCESS
217 }
218 Err(e) => {
219 *nevts = 0;
220 *evts = std::ptr::null_mut();
221 e.set_last_error(&mut plugin.error_buf);
222 e.status_code()
223 }
224 }
225 }
226}
227
228pub unsafe extern "C-unwind" fn plugin_get_progress<T: SourcePlugin>(
232 _plugin: *mut ss_plugin_t,
233 instance: *mut ss_instance_t,
234 progress_pct: *mut u32,
235) -> *const c_char {
236 let instance = instance as *mut SourcePluginInstanceWrapper<T::Instance>;
237 let progress = unsafe { instance.as_mut() }.map(|instance| instance.instance.get_progress());
238
239 if let Some(progress) = progress {
240 unsafe {
241 *progress_pct = (progress.value * 100.0) as u32;
242 }
243
244 match progress.detail {
245 Some(s) => s.as_ptr(),
246 None => std::ptr::null(),
247 }
248 } else {
249 unsafe {
250 *progress_pct = 0;
251 }
252
253 std::ptr::null()
254 }
255}
256
257pub unsafe extern "C-unwind" fn plugin_event_to_string<T: SourcePlugin>(
261 plugin: *mut ss_plugin_t,
262 event: *const ss_plugin_event_input,
263) -> *const c_char {
264 let plugin = plugin as *mut PluginWrapper<T>;
265 unsafe {
266 let Some(plugin) = plugin.as_mut() else {
267 return std::ptr::null();
268 };
269 let Some(ref mut actual_plugin) = &mut plugin.plugin else {
270 return std::ptr::null();
271 };
272
273 let Some(event) = event.as_ref() else {
274 return std::ptr::null();
275 };
276 let event = EventInput(*event);
277
278 match actual_plugin.plugin.event_to_string(&event) {
279 Ok(s) => {
280 plugin.string_storage = s;
281 plugin.string_storage.as_ptr()
282 }
283 Err(_) => std::ptr::null(),
284 }
285 }
286}
287
288#[macro_export]
293macro_rules! source_plugin {
294 ($ty:ty) => {
295 unsafe impl $crate::internals::source::wrappers::SourcePluginExported for $ty {}
296
297 $crate::wrap_ffi! {
298 #[no_mangle]
299 use $crate::internals::source::wrappers: <$ty>;
300 unsafe fn plugin_next_batch(
301 plugin: *mut falco_plugin::api::ss_plugin_t,
302 instance: *mut falco_plugin::api::ss_instance_t,
303 nevts: *mut u32,
304 evts: *mut *mut *mut falco_plugin::api::ss_plugin_event,
305 ) -> i32;
306 unsafe fn plugin_get_progress(
307 plugin: *mut falco_plugin::api::ss_plugin_t,
308 instance: *mut falco_plugin::api::ss_instance_t,
309 progress_pct: *mut u32,
310 ) -> *const ::std::ffi::c_char;
311 unsafe fn plugin_get_id() -> u32;
312 unsafe fn plugin_get_event_source() -> *const ::std::ffi::c_char;
313 unsafe fn plugin_list_open_params(
314 plugin: *mut falco_plugin::api::ss_plugin_t,
315 rc: *mut i32,
316 ) -> *const ::std::ffi::c_char;
317 unsafe fn plugin_open(
318 plugin: *mut falco_plugin::api::ss_plugin_t,
319 params: *const ::std::ffi::c_char,
320 rc: *mut i32,
321 ) -> *mut falco_plugin::api::ss_instance_t;
322 unsafe fn plugin_close(
323 plugin: *mut falco_plugin::api::ss_plugin_t,
324 instance: *mut falco_plugin::api::ss_instance_t,
325 ) -> ();
326 unsafe fn plugin_event_to_string(
327 plugin: *mut falco_plugin::api::ss_plugin_t,
328 event_input: *const falco_plugin::api::ss_plugin_event_input,
329 ) -> *const std::ffi::c_char;
330 }
331
332 #[allow(dead_code)]
333 fn __typecheck_plugin_source_api() -> falco_plugin::api::plugin_api__bindgen_ty_1 {
334 falco_plugin::api::plugin_api__bindgen_ty_1 {
335 next_batch: Some(plugin_next_batch),
336 get_progress: Some(plugin_get_progress),
337 get_id: Some(plugin_get_id),
338 get_event_source: Some(plugin_get_event_source),
339 list_open_params: Some(plugin_list_open_params),
340 open: Some(plugin_open),
341 close: Some(plugin_close),
342 event_to_string: Some(plugin_event_to_string),
343 }
344 }
345 };
346}