use crate::{DatagramParser, FlowSide, SessionParser, Timestamp};
#[derive(Debug, Default, Clone)]
pub struct NoopSessionParser;
impl SessionParser for NoopSessionParser {
type Message = ();
fn feed_initiator(&mut self, _bytes: &[u8], _ts: Timestamp, _out: &mut Vec<()>) {}
fn feed_responder(&mut self, _bytes: &[u8], _ts: Timestamp, _out: &mut Vec<()>) {}
}
#[derive(Debug, Default, Clone)]
pub struct NoopDatagramParser;
impl DatagramParser for NoopDatagramParser {
type Message = ();
fn parse(&mut self, _payload: &[u8], _side: FlowSide, _ts: Timestamp, _out: &mut Vec<()>) {}
}
#[derive(Debug, Default, Clone)]
pub struct EchoSessionParser;
impl SessionParser for EchoSessionParser {
type Message = (FlowSide, Vec<u8>);
fn feed_initiator(&mut self, bytes: &[u8], _ts: Timestamp, out: &mut Vec<Self::Message>) {
out.push((FlowSide::Initiator, bytes.to_vec()));
}
fn feed_responder(&mut self, bytes: &[u8], _ts: Timestamp, out: &mut Vec<Self::Message>) {
out.push((FlowSide::Responder, bytes.to_vec()));
}
}
#[derive(Debug, Default, Clone)]
pub struct OneShotSessionParser {
done: bool,
}
impl SessionParser for OneShotSessionParser {
type Message = ();
fn feed_initiator(&mut self, _bytes: &[u8], _ts: Timestamp, out: &mut Vec<()>) {
self.done = true;
out.push(());
}
fn feed_responder(&mut self, _bytes: &[u8], _ts: Timestamp, _out: &mut Vec<()>) {}
fn is_done(&self) -> bool {
self.done
}
fn parser_kind(&self) -> &'static str {
"one-shot-session"
}
}
#[derive(Debug, Default, Clone)]
pub struct OneShotDatagramParser {
done: bool,
}
impl DatagramParser for OneShotDatagramParser {
type Message = ();
fn parse(&mut self, _payload: &[u8], _side: FlowSide, _ts: Timestamp, out: &mut Vec<()>) {
self.done = true;
out.push(());
}
fn is_done(&self) -> bool {
self.done
}
fn parser_kind(&self) -> &'static str {
"one-shot-datagram"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn noop_session_compiles() {
let mut p = NoopSessionParser;
let mut out = Vec::new();
p.feed_initiator(b"hi", Timestamp::default(), &mut out);
assert!(out.is_empty());
p.feed_responder(b"hi", Timestamp::default(), &mut out);
assert!(out.is_empty());
}
#[test]
fn noop_datagram_compiles() {
let mut p = NoopDatagramParser;
let mut out = Vec::new();
p.parse(b"hi", FlowSide::Initiator, Timestamp::default(), &mut out);
assert!(out.is_empty());
}
#[test]
fn echo_session_emits_chunks() {
let mut p = EchoSessionParser;
let mut m = Vec::new();
p.feed_initiator(b"hello", Timestamp::default(), &mut m);
assert_eq!(m.len(), 1);
assert_eq!(m[0].0, FlowSide::Initiator);
assert_eq!(m[0].1, b"hello");
}
}
pub mod events {
use crate::Timestamp;
use crate::event::{AnomalyKind, EndReason, FlowEvent, FlowSide, FlowStats};
use crate::extractor::L4Proto;
pub fn started<K>(key: K, ts: Timestamp) -> FlowEvent<K> {
FlowEvent::Started {
key,
side: FlowSide::Initiator,
ts,
l4: None,
}
}
pub fn started_with_l4<K>(key: K, l4: L4Proto, ts: Timestamp) -> FlowEvent<K> {
FlowEvent::Started {
key,
side: FlowSide::Initiator,
ts,
l4: Some(l4),
}
}
pub fn established<K>(key: K, ts: Timestamp) -> FlowEvent<K> {
FlowEvent::Established { key, ts, l4: None }
}
pub fn ended<K>(key: K, ts: Timestamp) -> FlowEvent<K> {
let stats = FlowStats {
last_seen: ts,
..FlowStats::default()
};
FlowEvent::Ended {
key,
reason: EndReason::IdleTimeout,
stats,
history: Default::default(),
l4: None,
}
}
pub fn ended_with<K>(key: K, reason: EndReason, stats: FlowStats) -> FlowEvent<K> {
FlowEvent::Ended {
key,
reason,
stats,
history: Default::default(),
l4: None,
}
}
pub fn tick<K>(key: K, ts: Timestamp) -> FlowEvent<K> {
FlowEvent::Tick {
key,
stats: FlowStats::default(),
ts,
}
}
pub fn flow_anomaly<K>(key: K, kind: AnomalyKind, ts: Timestamp) -> FlowEvent<K> {
FlowEvent::FlowAnomaly { key, kind, ts }
}
pub fn tracker_anomaly<K>(kind: AnomalyKind, ts: Timestamp) -> FlowEvent<K> {
FlowEvent::TrackerAnomaly { kind, ts }
}
pub fn packet<K>(key: K, len: usize, ts: Timestamp) -> FlowEvent<K> {
FlowEvent::Packet {
key,
side: FlowSide::Initiator,
len,
ts,
}
}
pub fn packet_side<K>(key: K, side: FlowSide, len: usize, ts: Timestamp) -> FlowEvent<K> {
FlowEvent::Packet { key, side, len, ts }
}
pub mod driver {
use crate::Timestamp;
use crate::driver::Event;
use crate::event::{AnomalyKind, EndReason, FlowSide, FlowStats};
use crate::extractor::{L4Proto, TcpInfo};
pub fn flow_started<K>(key: K, ts: Timestamp) -> Event<K> {
Event::FlowStarted { key, ts, l4: None }
}
pub fn flow_started_with_l4<K>(key: K, l4: L4Proto, ts: Timestamp) -> Event<K> {
Event::FlowStarted {
key,
ts,
l4: Some(l4),
}
}
pub fn flow_established<K>(key: K, ts: Timestamp) -> Event<K> {
Event::FlowEstablished { key, ts, l4: None }
}
pub fn flow_ended<K>(key: K, ts: Timestamp) -> Event<K> {
Event::FlowEnded {
key,
reason: EndReason::IdleTimeout,
stats: FlowStats::default(),
history: Default::default(),
l4: None,
ts,
}
}
pub fn flow_packet<K>(key: K, len: usize, ts: Timestamp) -> Event<K> {
Event::FlowPacket {
key,
side: FlowSide::Initiator,
len,
ts,
tcp: None,
}
}
pub fn flow_packet_full<K>(
key: K,
side: FlowSide,
len: usize,
tcp: Option<TcpInfo>,
ts: Timestamp,
) -> Event<K> {
Event::FlowPacket {
key,
side,
len,
ts,
tcp,
}
}
pub fn flow_tick<K>(key: K, ts: Timestamp) -> Event<K> {
Event::FlowTick {
key,
stats: FlowStats::default(),
ts,
}
}
pub fn parser_closed<K>(key: K, parser_kind: &'static str, ts: Timestamp) -> Event<K> {
Event::ParserClosed {
key,
parser_kind,
reason: EndReason::ParserDone,
ts,
}
}
pub fn flow_anomaly<K>(key: K, kind: AnomalyKind, ts: Timestamp) -> Event<K> {
Event::FlowAnomaly { key, kind, ts }
}
pub fn tracker_anomaly<K>(kind: AnomalyKind, ts: Timestamp) -> Event<K> {
Event::TrackerAnomaly { kind, ts }
}
}
}