falco_plugin/tables/vtable/
mod.rs

1use crate::error::last_error::LastError;
2use falco_plugin_api::{
3    ss_plugin_init_input, ss_plugin_owner_t, ss_plugin_rc, ss_plugin_state_type,
4    ss_plugin_table_info, ss_plugin_table_input, ss_plugin_table_t,
5};
6use thiserror::Error;
7
8pub mod fields;
9pub mod reader;
10pub mod writer;
11
12use crate::tables::LazyTableReader;
13use fields::TableFields;
14use writer::LazyTableWriter;
15
16#[derive(Error, Debug)]
17pub enum TableError {
18    #[error("Missing entry {0} in table operations vtable")]
19    BadVtable(&'static str),
20}
21
22#[derive(Debug)]
23/// An object containing table-related vtables
24///
25/// It's used as a token to prove you're allowed to read/write tables
26/// or manage their fields
27pub struct TablesInput<'t> {
28    pub(crate) owner: *mut ss_plugin_owner_t,
29    pub(crate) last_error: LastError,
30    pub(crate) list_tables: unsafe extern "C-unwind" fn(
31        o: *mut ss_plugin_owner_t,
32        ntables: *mut u32,
33    ) -> *mut ss_plugin_table_info,
34    pub(crate) get_table: unsafe extern "C-unwind" fn(
35        o: *mut ss_plugin_owner_t,
36        name: *const ::std::os::raw::c_char,
37        key_type: ss_plugin_state_type,
38    ) -> *mut ss_plugin_table_t,
39    pub(crate) add_table: unsafe extern "C-unwind" fn(
40        o: *mut ss_plugin_owner_t,
41        in_: *const ss_plugin_table_input,
42    ) -> ss_plugin_rc,
43
44    /// accessor object for reading tables
45    pub(crate) reader_ext: LazyTableReader<'t>,
46
47    /// accessor object for writing tables
48    pub(crate) writer_ext: LazyTableWriter<'t>,
49
50    /// accessor object for manipulating fields
51    pub(crate) fields_ext: TableFields<'t>,
52}
53
54impl TablesInput<'_> {
55    pub(crate) fn try_from(value: &ss_plugin_init_input) -> Result<Option<Self>, TableError> {
56        if let Some(table_init_input) = unsafe { value.tables.as_ref() } {
57            let reader_ext = unsafe {
58                table_init_input
59                    .reader_ext
60                    .as_ref()
61                    .ok_or(TableError::BadVtable("reader_ext"))?
62            };
63            let writer_ext = unsafe {
64                table_init_input
65                    .writer_ext
66                    .as_ref()
67                    .ok_or(TableError::BadVtable("writer_ext"))?
68            };
69            let fields_ext = unsafe {
70                table_init_input
71                    .fields_ext
72                    .as_ref()
73                    .ok_or(TableError::BadVtable("fields_ext"))?
74            };
75
76            let get_owner_last_error = value
77                .get_owner_last_error
78                .ok_or(TableError::BadVtable("get_owner_last_error"))?;
79            let last_error = unsafe { LastError::new(value.owner, get_owner_last_error) };
80
81            Ok(Some(TablesInput {
82                owner: value.owner,
83                last_error: last_error.clone(),
84                list_tables: table_init_input
85                    .list_tables
86                    .ok_or(TableError::BadVtable("list_tables"))?,
87                get_table: table_init_input
88                    .get_table
89                    .ok_or(TableError::BadVtable("get_table"))?,
90                add_table: table_init_input
91                    .add_table
92                    .ok_or(TableError::BadVtable("add_table"))?,
93                reader_ext: LazyTableReader::new(reader_ext, last_error.clone()),
94                writer_ext: LazyTableWriter::try_from(writer_ext, last_error)?,
95                fields_ext: TableFields::try_from(fields_ext)?,
96            }))
97        } else {
98            Ok(None)
99        }
100    }
101}
102
103impl TablesInput<'_> {
104    /// # List the available tables
105    ///
106    /// **Note**: this method is of limited utility in actual plugin code (you know the tables you
107    /// want to access), so it returns the unmodified structure from the plugin API, including
108    /// raw pointers to C-style strings. This may change later.
109    pub fn list_tables(&self) -> &[ss_plugin_table_info] {
110        let mut num_tables = 0u32;
111        let tables = unsafe { (self.list_tables)(self.owner, &mut num_tables as *mut _) };
112        if tables.is_null() {
113            &[]
114        } else {
115            unsafe { std::slice::from_raw_parts(tables, num_tables as usize) }
116        }
117    }
118}