vane_core/
conn_context.rs1use 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, Default)]
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 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 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}