Skip to main content

vane_core/
conn_context.rs

1use std::net::SocketAddr;
2use std::sync::OnceLock;
3use std::time::Instant;
4
5use parking_lot::Mutex;
6use rustls_pki_types::CertificateDer;
7
8#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
9pub struct ConnId(pub u64);
10
11impl std::fmt::Display for ConnId {
12	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13		write!(f, "{:016x}", self.0)
14	}
15}
16
17#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
18pub enum Transport {
19	Tcp,
20	Udp,
21}
22
23#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
24pub enum HttpVersion {
25	Http1_0,
26	Http1_1,
27	Http2,
28	Http3,
29}
30
31#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
32pub enum TlsVersion {
33	Tls12,
34	Tls13,
35}
36
37#[derive(Clone, Debug)]
38pub struct TlsInfo {
39	pub sni: Option<String>,
40	pub alpn: Option<Vec<u8>>,
41	pub version: Option<TlsVersion>,
42	pub peer_cert: Option<CertificateDer<'static>>,
43}
44
45pub struct ConnContext {
46	pub id: ConnId,
47	pub remote: SocketAddr,
48	pub local: SocketAddr,
49	pub transport: Transport,
50	pub entered_at: Instant,
51
52	pub tls: Mutex<Option<TlsInfo>>,
53	pub http_version: OnceLock<HttpVersion>,
54
55	pub user: Mutex<http::Extensions>,
56}
57
58#[cfg(test)]
59mod tests {
60	use super::*;
61
62	#[test]
63	fn conn_id_display_pads_zero_to_sixteen_hex_digits() {
64		let rendered = format!("{}", ConnId(0));
65		assert_eq!(rendered, "0000000000000000");
66		assert_eq!(rendered.len(), 16);
67	}
68
69	#[test]
70	fn conn_id_display_is_lowercase_hex() {
71		let rendered = format!("{}", ConnId(0x0bad_f00d_dead_beef));
72		assert_eq!(rendered, "0badf00ddeadbeef");
73		assert!(rendered.chars().all(|c| c.is_ascii_digit() || ('a'..='f').contains(&c)));
74	}
75
76	#[test]
77	fn conn_id_display_zero_pads_small_values() {
78		// non-zero top nibble would mean no left padding; a small value exercises
79		// the {:016x} pad path explicitly.
80		let rendered = format!("{}", ConnId(1));
81		assert_eq!(rendered, "0000000000000001");
82	}
83
84	#[test]
85	fn conn_id_display_renders_u64_max() {
86		let rendered = format!("{}", ConnId(u64::MAX));
87		assert_eq!(rendered, "ffffffffffffffff");
88		assert_eq!(rendered.len(), 16);
89	}
90
91	#[test]
92	fn conn_id_serde_round_trip() {
93		let id = ConnId(0x1234_5678_9abc_def0);
94		let encoded = serde_json::to_string(&id).expect("serialize");
95		let decoded: ConnId = serde_json::from_str(&encoded).expect("deserialize");
96		assert_eq!(decoded, id);
97	}
98
99	#[test]
100	fn tls_version_variants_are_exhaustive_at_two() {
101		// Adding a TlsVersion variant without updating this arm would be a
102		// compile error — the spec (08-tls.md) constrains accepted versions
103		// to 1.2 and 1.3 only.
104		for v in [TlsVersion::Tls12, TlsVersion::Tls13] {
105			let matched = match v {
106				TlsVersion::Tls12 => "1.2",
107				TlsVersion::Tls13 => "1.3",
108			};
109			assert!(!matched.is_empty());
110		}
111	}
112
113	#[test]
114	fn tls_version_serde_round_trip_per_variant() {
115		for v in [TlsVersion::Tls12, TlsVersion::Tls13] {
116			let encoded = serde_json::to_string(&v).expect("serialize");
117			let decoded: TlsVersion = serde_json::from_str(&encoded).expect("deserialize");
118			assert_eq!(decoded, v);
119		}
120	}
121
122	#[test]
123	fn transport_serde_round_trip_per_variant() {
124		for t in [Transport::Tcp, Transport::Udp] {
125			let encoded = serde_json::to_string(&t).expect("serialize");
126			let decoded: Transport = serde_json::from_str(&encoded).expect("deserialize");
127			assert_eq!(decoded, t);
128		}
129	}
130
131	#[test]
132	fn http_version_serde_round_trip_per_variant() {
133		for v in [HttpVersion::Http1_0, HttpVersion::Http1_1, HttpVersion::Http2, HttpVersion::Http3] {
134			let encoded = serde_json::to_string(&v).expect("serialize");
135			let decoded: HttpVersion = serde_json::from_str(&encoded).expect("deserialize");
136			assert_eq!(decoded, v);
137		}
138	}
139}