use crate::Timestamp;
use crate::extractor::L4Proto;
use crate::history::HistoryString;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FlowSide {
Initiator,
Responder,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EndReason {
Fin,
Rst,
IdleTimeout,
Evicted,
}
#[derive(Debug, Clone, Default)]
pub struct FlowStats {
pub packets_initiator: u64,
pub packets_responder: u64,
pub bytes_initiator: u64,
pub bytes_responder: u64,
pub started: Timestamp,
pub last_seen: Timestamp,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FlowState {
SynSent,
SynReceived,
Established,
FinWait,
ClosingTcp,
Active,
Closed,
Reset,
Aborted,
}
impl FlowState {
pub fn is_terminal(self) -> bool {
matches!(
self,
FlowState::Closed | FlowState::Reset | FlowState::Aborted
)
}
}
#[derive(Debug, Clone)]
pub enum FlowEvent<K> {
Started {
key: K,
side: FlowSide,
ts: Timestamp,
l4: Option<L4Proto>,
},
Packet {
key: K,
side: FlowSide,
len: usize,
ts: Timestamp,
},
Established { key: K, ts: Timestamp },
StateChange {
key: K,
from: FlowState,
to: FlowState,
ts: Timestamp,
},
Ended {
key: K,
reason: EndReason,
stats: FlowStats,
history: HistoryString,
},
}
impl<K> FlowEvent<K> {
pub fn key(&self) -> &K {
match self {
FlowEvent::Started { key, .. }
| FlowEvent::Packet { key, .. }
| FlowEvent::Established { key, .. }
| FlowEvent::StateChange { key, .. }
| FlowEvent::Ended { key, .. } => key,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn flow_state_terminal() {
assert!(FlowState::Closed.is_terminal());
assert!(FlowState::Reset.is_terminal());
assert!(FlowState::Aborted.is_terminal());
assert!(!FlowState::Active.is_terminal());
assert!(!FlowState::Established.is_terminal());
assert!(!FlowState::SynSent.is_terminal());
}
#[test]
fn flow_event_key_borrow() {
let evt: FlowEvent<u32> = FlowEvent::Packet {
key: 7,
side: FlowSide::Initiator,
len: 100,
ts: Timestamp::default(),
};
assert_eq!(*evt.key(), 7);
}
}