retina_core/subscription/
quic_stream.rs1use crate::conntrack::conn_id::FiveTuple;
8use crate::conntrack::pdu::{L4Context, L4Pdu};
9use crate::conntrack::ConnTracker;
10use crate::filter::FilterResult;
11use crate::memory::mbuf::Mbuf;
12use crate::protocols::stream::quic::parser::QuicParser;
13use crate::protocols::stream::quic::QuicConn;
14use crate::protocols::stream::{ConnParser, Session, SessionData};
15use crate::subscription::{Level, Subscribable, Subscription, Trackable};
16use std::collections::HashSet;
17
18use serde::Serialize;
19
20use std::net::SocketAddr;
21
22#[derive(Debug, Serialize)]
24pub struct QuicStream {
25 pub five_tuple: FiveTuple,
26 pub data: QuicConn,
27}
28
29impl QuicStream {
30 #[inline]
32 pub fn client(&self) -> SocketAddr {
33 self.five_tuple.orig
34 }
35
36 #[inline]
38 pub fn server(&self) -> SocketAddr {
39 self.five_tuple.resp
40 }
41}
42
43impl Subscribable for QuicStream {
44 type Tracked = TrackedQuic;
45
46 fn level() -> Level {
47 Level::Session
48 }
49
50 fn parsers() -> Vec<ConnParser> {
51 vec![ConnParser::Quic(QuicParser::default())]
52 }
53
54 fn process_packet(
55 mbuf: Mbuf,
56 subscription: &Subscription<Self>,
57 conn_tracker: &mut ConnTracker<Self::Tracked>,
58 ) {
59 match subscription.filter_packet(&mbuf) {
60 FilterResult::MatchTerminal(idx) | FilterResult::MatchNonTerminal(idx) => {
61 if let Ok(ctxt) = L4Context::new(&mbuf, idx) {
62 conn_tracker.process(mbuf, ctxt, subscription);
63 }
64 }
65 FilterResult::NoMatch => drop(mbuf),
66 }
67 }
68}
69
70#[doc(hidden)]
82pub struct TrackedQuic {
83 five_tuple: FiveTuple,
84 connection_id: HashSet<String>,
85}
86
87impl Trackable for TrackedQuic {
88 type Subscribed = QuicStream;
89
90 fn new(five_tuple: FiveTuple) -> Self {
91 TrackedQuic {
92 five_tuple,
93 connection_id: HashSet::new(),
94 }
95 }
96
97 fn pre_match(&mut self, _pdu: L4Pdu, _session_id: Option<usize>) {}
98
99 fn on_match(&mut self, session: Session, subscription: &Subscription<Self::Subscribed>) {
100 if let SessionData::Quic(quic) = session.data {
101 let quic_clone = *quic;
102 for cid in &quic_clone.cids {
103 self.connection_id.insert(cid.to_string());
104 }
105
106 subscription.invoke(QuicStream {
107 five_tuple: self.five_tuple,
108 data: quic_clone,
109 });
110 }
111 }
112
113 fn post_match(&mut self, _pdu: L4Pdu, _subscription: &Subscription<Self::Subscribed>) {}
114
115 fn on_terminate(&mut self, _subscription: &Subscription<Self::Subscribed>) {
116 self.connection_id.clear();
117 }
118}