1use rkyv::{Archive, Deserialize, Serialize};
5
6#[derive(Archive, Serialize, Deserialize, Debug, Clone, PartialEq)]
12#[rkyv(compare(PartialEq), derive(Debug))]
13pub struct ProxyFrame {
14 pub conn_id: u64,
16
17 pub rip: [u8; 16],
19
20 pub rport: u16,
22
23 pub payload: Vec<u8>,
25
26 pub uuid: [u8; 16],
28
29 pub timestamp: u64,
31
32 pub checksum: u32,
34
35 pub flags: FrameFlags,
37}
38
39#[derive(Archive, Serialize, Deserialize, Debug, Clone, Copy, Default, PartialEq)]
41#[rkyv(compare(PartialEq), derive(Debug))]
42pub struct FrameFlags {
43 pub is_control: bool,
45
46 pub is_compressed: bool,
48
49 pub is_final: bool,
51
52 pub needs_ack: bool,
54
55 pub is_ack: bool,
57}
58
59impl ProxyFrame {
60 pub fn new_data(conn_id: u64, rip: [u8; 16], rport: u16, payload: Vec<u8>) -> Self {
62 let checksum = crc32fast::hash(&payload);
63 let uuid = uuid::Uuid::new_v4().into_bytes();
64 let timestamp = std::time::SystemTime::now()
65 .duration_since(std::time::UNIX_EPOCH)
66 .unwrap()
67 .as_millis() as u64;
68
69 Self {
70 conn_id,
71 rip,
72 rport,
73 payload,
74 uuid,
75 timestamp,
76 checksum,
77 flags: FrameFlags::default(),
78 }
79 }
80
81 pub fn new_control(payload: Vec<u8>) -> Self {
83 let mut frame = Self::new_data(0, [0; 16], 0, payload);
84 frame.flags.is_control = true;
85 frame
86 }
87
88 pub fn new_close(conn_id: u64) -> Self {
90 let mut frame = Self::new_data(conn_id, [0; 16], 0, vec![]);
91 frame.flags.is_final = true;
92 frame
93 }
94
95 pub fn verify_checksum(&self) -> bool {
97 crc32fast::hash(&self.payload) == self.checksum
98 }
99
100 pub fn ipv4_to_mapped(ipv4: [u8; 4]) -> [u8; 16] {
102 let mut mapped = [0u8; 16];
103 mapped[10] = 0xff;
104 mapped[11] = 0xff;
105 mapped[12..16].copy_from_slice(&ipv4);
106 mapped
107 }
108
109 pub fn mapped_to_ipv4(mapped: &[u8; 16]) -> Option<[u8; 4]> {
111 if mapped[..10] == [0; 10] && mapped[10] == 0xff && mapped[11] == 0xff {
112 let mut ipv4 = [0u8; 4];
113 ipv4.copy_from_slice(&mapped[12..16]);
114 Some(ipv4)
115 } else {
116 None
117 }
118 }
119}
120
121#[derive(Archive, Serialize, Deserialize, Debug, Clone, PartialEq)]
123#[rkyv(compare(PartialEq), derive(Debug))]
124pub struct GroupInfo {
125 pub group_id: i32,
127 pub name: String,
129 pub node_count: u32,
131 pub load: u8,
133}
134
135#[derive(Archive, Serialize, Deserialize, Debug, Clone, PartialEq)]
137#[rkyv(compare(PartialEq), derive(Debug))]
138pub enum ControlMessage {
139 DohQuery { query: Vec<u8> },
141
142 DohResponse { response: Vec<u8> },
144
145 Ping { nonce: u64 },
147
148 Pong { nonce: u64 },
150
151 KeyRotation {
153 new_pk: [u8; 32],
154 valid_from: u64,
155 valid_until: u64,
156 },
157
158 Emergency {
160 level: EmergencyLevel,
161 trigger_after: u64,
162 },
163
164 GroupList { groups: Vec<GroupInfo> },
166
167 GroupSelect { group_id: i32 },
169}
170
171#[derive(Archive, Serialize, Deserialize, Debug, Clone, Copy, PartialEq)]
173#[rkyv(compare(PartialEq), derive(Debug))]
174pub enum EmergencyLevel {
175 Warning,
177 Stop,
179 Shutdown,
181}
182
183#[derive(Archive, Serialize, Deserialize, Debug, Clone, PartialEq)]
187#[rkyv(compare(PartialEq), derive(Debug))]
188pub struct PlainPacket {
189 pub magic: u32,
191
192 pub conn_id: u64,
194
195 pub handler_id: u64,
197
198 pub rip: [u8; 16],
200
201 pub rport: u16,
203
204 pub payload: Vec<u8>,
206
207 pub checksum: u32,
209
210 pub is_response: bool,
212}
213
214impl PlainPacket {
215 pub const MAGIC: u32 = 0xDEADBEEF;
217
218 pub fn from_frame(frame: &ProxyFrame, handler_id: u64) -> Self {
220 Self {
221 magic: Self::MAGIC,
222 conn_id: frame.conn_id,
223 handler_id,
224 rip: frame.rip,
225 rport: frame.rport,
226 payload: frame.payload.clone(),
227 checksum: frame.checksum,
228 is_response: false,
229 }
230 }
231
232 pub fn response(conn_id: u64, handler_id: u64, payload: Vec<u8>) -> Self {
234 let checksum = crc32fast::hash(&payload);
235 Self {
236 magic: Self::MAGIC,
237 conn_id,
238 handler_id,
239 rip: [0; 16],
240 rport: 0,
241 payload,
242 checksum,
243 is_response: true,
244 }
245 }
246
247 pub fn is_valid(&self) -> bool {
249 self.magic == Self::MAGIC && crc32fast::hash(&self.payload) == self.checksum
250 }
251}
252
253#[derive(Archive, Serialize, Deserialize, Debug, Clone, PartialEq)]
255#[rkyv(compare(PartialEq), derive(Debug))]
256pub enum RaftCommand {
257 Upsert {
259 conn_id: u64,
260 txid: u64,
261 client_addr: [u8; 16],
262 nat_entry: (u16, u16),
263 assigned_pod: u32,
264 },
265
266 Delete { conn_id: u64 },
268
269 Cleanup { before_timestamp: u64 },
271
272 Noop,
274}
275
276#[cfg(test)]
277mod tests {
278 use super::*;
279
280 #[test]
281 fn test_frame_creation() {
282 let payload = vec![1, 2, 3, 4, 5];
283 let frame = ProxyFrame::new_data(
284 42,
285 ProxyFrame::ipv4_to_mapped([192, 168, 1, 1]),
286 8080,
287 payload.clone(),
288 );
289
290 assert_eq!(frame.conn_id, 42);
291 assert_eq!(frame.rport, 8080);
292 assert_eq!(frame.payload, payload);
293 assert!(frame.verify_checksum());
294 }
295
296 #[test]
297 fn test_ipv4_mapping() {
298 let ipv4 = [192, 168, 1, 1];
299 let mapped = ProxyFrame::ipv4_to_mapped(ipv4);
300 let extracted = ProxyFrame::mapped_to_ipv4(&mapped);
301
302 assert_eq!(extracted, Some(ipv4));
303 }
304
305 #[test]
306 fn test_serialization() {
307 let frame = ProxyFrame::new_data(1, [0; 16], 443, vec![0xDE, 0xAD, 0xBE, 0xEF]);
308
309 let bytes = rkyv::to_bytes::<rkyv::rancor::Error>(&frame).unwrap();
310 let archived = rkyv::access::<ArchivedProxyFrame, rkyv::rancor::Error>(&bytes).unwrap();
311
312 assert_eq!(archived.conn_id, 1);
313 assert_eq!(archived.rport, 443);
314 }
315}