falco_event/events/payload.rs
1use crate::events::EventMetadata;
2use crate::fields::FromBytesError;
3use std::collections::BTreeSet;
4use std::io::Write;
5use thiserror::Error;
6
7/// Represents the direction of an event, either an entry or an exit.
8#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
9#[allow(missing_docs)]
10pub enum EventDirection {
11 Entry,
12 Exit,
13}
14
15/// A trait to identify event payloads in the plugin framework.
16///
17/// Each event has two main identifiers:
18/// - `ID`: a unique identifier for the event type, which is a 16-bit unsigned integer.
19/// - `SOURCE`: the name of the event source. For plugin events, this is the name of the plugin
20/// that generated the event. For syscall events, this is always `Some("syscall")`.
21///
22/// The source can be `None` if the event can come from multiple sources, such as in the case of
23/// async or plugin events coming from different plugins.
24#[allow(missing_docs)]
25pub trait EventPayload {
26 const ID: u16;
27 const SOURCE: Option<&'static str>;
28}
29
30/// Get the event direction from the event type ID.
31#[inline]
32pub const fn event_direction(event_type_id: u16) -> EventDirection {
33 match event_type_id % 2 {
34 0 => EventDirection::Entry,
35 1 => EventDirection::Exit,
36 _ => unreachable!(),
37 }
38}
39
40/// A trait to identify a group of event payloads, each having a unique identifier and source.
41pub trait AnyEventPayload {
42 /// The sources of the events that this payload type can represent.
43 const SOURCES: &'static [Option<&'static str>];
44
45 /// The event types that this payload type can represent.
46 const EVENT_TYPES: &'static [u16];
47
48 /// Get all the event sources for this payload type
49 ///
50 /// This is intended for internal use only. If all the items in `SOURCES` are `Some()`,
51 /// the function returns the inner strings with duplicates removed. If any item is `None`
52 /// (indicating a supported event may come from any source), an empty vector is returned
53 /// (again, indicating all sources).
54 fn event_sources() -> Vec<&'static str> {
55 let mut sources = BTreeSet::new();
56 for source in Self::SOURCES {
57 if let Some(source) = source {
58 sources.insert(*source);
59 } else {
60 return Vec::new();
61 }
62 }
63
64 sources.into_iter().collect()
65 }
66}
67
68impl<T: EventPayload> AnyEventPayload for T {
69 const SOURCES: &'static [Option<&'static str>] = const {
70 match T::SOURCE {
71 Some(s) => &[Some(s)],
72 None => &[],
73 }
74 };
75 const EVENT_TYPES: &'static [u16] = &[T::ID];
76}
77
78/// Error type for parsing event payloads from bytes
79#[derive(Debug, Error)]
80pub enum PayloadFromBytesError {
81 /// Failed to parse a particular field
82 #[error("failed to parse field {0}")]
83 NamedField(&'static str, #[source] FromBytesError),
84
85 /// Type mismatch
86 #[error("type mismatch")]
87 TypeMismatch,
88
89 /// Truncated event
90 #[error("truncated event (wanted {wanted}, got {got})")]
91 TruncatedEvent {
92 /// expected length
93 wanted: usize,
94 /// actual length
95 got: usize,
96 },
97
98 /// Unsupported event type
99 #[error("unsupported event type {0}")]
100 UnsupportedEventType(u16),
101}
102
103/// Trait for converting event payloads to bytes
104pub trait PayloadToBytes {
105 /// Get the binary size of the payload
106 ///
107 /// This is the size of the payload in bytes, excluding the event header. This can (and should)
108 /// be used to preallocate buffers for writing the payload.
109 fn binary_size(&self) -> usize;
110
111 /// Write the payload to a writer implementing `[std::io::Write]`.
112 fn write<W: Write>(&self, metadata: &EventMetadata, writer: W) -> std::io::Result<()>;
113}