1use rkyv::{Archive, Deserialize, Serialize};
4
5#[derive(Archive, Serialize, Deserialize, Debug, Clone, PartialEq)]
11#[rkyv(compare(PartialEq), derive(Debug))]
12pub struct ProxyFrame {
13 pub conn_id: u64,
15
16 pub rip: [u8; 16],
18
19 pub rport: u16,
21
22 pub payload: Vec<u8>,
24
25 pub uuid: [u8; 16],
27
28 pub timestamp: u64,
30
31 pub checksum: u32,
33
34 pub flags: FrameFlags,
36}
37
38#[derive(Archive, Serialize, Deserialize, Debug, Clone, Copy, Default, PartialEq)]
40#[rkyv(compare(PartialEq), derive(Debug))]
41pub struct FrameFlags {
42 pub is_control: bool,
44
45 pub is_compressed: bool,
47
48 pub is_final: bool,
50
51 pub needs_ack: bool,
53
54 pub is_ack: bool,
56}
57
58impl ProxyFrame {
59 pub fn new_data(conn_id: u64, rip: [u8; 16], rport: u16, payload: Vec<u8>) -> Self {
61 let checksum = crc32fast::hash(&payload);
62 let uuid = uuid::Uuid::new_v4().into_bytes();
63 let timestamp = std::time::SystemTime::now()
64 .duration_since(std::time::UNIX_EPOCH)
65 .unwrap()
66 .as_millis() as u64;
67
68 Self {
69 conn_id,
70 rip,
71 rport,
72 payload,
73 uuid,
74 timestamp,
75 checksum,
76 flags: FrameFlags::default(),
77 }
78 }
79
80 pub fn new_control(payload: Vec<u8>) -> Self {
82 let mut frame = Self::new_data(0, [0; 16], 0, payload);
83 frame.flags.is_control = true;
84 frame
85 }
86
87 pub fn new_close(conn_id: u64) -> Self {
89 let mut frame = Self::new_data(conn_id, [0; 16], 0, vec![]);
90 frame.flags.is_final = true;
91 frame
92 }
93
94 pub fn verify_checksum(&self) -> bool {
96 crc32fast::hash(&self.payload) == self.checksum
97 }
98
99 pub fn ipv4_to_mapped(ipv4: [u8; 4]) -> [u8; 16] {
101 let mut mapped = [0u8; 16];
102 mapped[10] = 0xff;
103 mapped[11] = 0xff;
104 mapped[12..16].copy_from_slice(&ipv4);
105 mapped
106 }
107
108 pub fn mapped_to_ipv4(mapped: &[u8; 16]) -> Option<[u8; 4]> {
110 if mapped[..10] == [0; 10] && mapped[10] == 0xff && mapped[11] == 0xff {
111 let mut ipv4 = [0u8; 4];
112 ipv4.copy_from_slice(&mapped[12..16]);
113 Some(ipv4)
114 } else {
115 None
116 }
117 }
118}
119
120#[derive(Archive, Serialize, Deserialize, Debug, Clone, PartialEq)]
122#[rkyv(compare(PartialEq), derive(Debug))]
123pub struct GroupInfo {
124 pub group_id: i32,
126 pub name: String,
128 pub node_count: u32,
130 pub load: u8,
132}
133
134#[derive(Archive, Serialize, Deserialize, Debug, Clone, PartialEq)]
136#[rkyv(compare(PartialEq), derive(Debug))]
137pub enum ControlMessage {
138 DohQuery { query: Vec<u8> },
140
141 DohResponse { response: Vec<u8> },
143
144 Ping { nonce: u64 },
146
147 Pong { nonce: u64 },
149
150 KeyRotation {
152 new_pk: [u8; 32],
153 valid_from: u64,
154 valid_until: u64,
155 },
156
157 Emergency {
159 level: EmergencyLevel,
160 trigger_after: u64,
161 },
162
163 GroupList { groups: Vec<GroupInfo> },
165
166 GroupSelect { group_id: i32 },
168}
169
170#[derive(Archive, Serialize, Deserialize, Debug, Clone, Copy, PartialEq)]
172#[rkyv(compare(PartialEq), derive(Debug))]
173pub enum EmergencyLevel {
174 Warning,
176 Stop,
178 Shutdown,
180}
181
182#[derive(Archive, Serialize, Deserialize, Debug, Clone, PartialEq)]
186#[rkyv(compare(PartialEq), derive(Debug))]
187pub struct PlainPacket {
188 pub magic: u32,
190
191 pub conn_id: u64,
193
194 pub handler_id: u64,
196
197 pub rip: [u8; 16],
199
200 pub rport: u16,
202
203 pub payload: Vec<u8>,
205
206 pub checksum: u32,
208
209 pub is_response: bool,
211}
212
213impl PlainPacket {
214 pub const MAGIC: u32 = 0xDEADBEEF;
216
217 pub fn from_frame(frame: &ProxyFrame, handler_id: u64) -> Self {
219 Self {
220 magic: Self::MAGIC,
221 conn_id: frame.conn_id,
222 handler_id,
223 rip: frame.rip,
224 rport: frame.rport,
225 payload: frame.payload.clone(),
226 checksum: frame.checksum,
227 is_response: false,
228 }
229 }
230
231 pub fn response(conn_id: u64, handler_id: u64, payload: Vec<u8>) -> Self {
233 let checksum = crc32fast::hash(&payload);
234 Self {
235 magic: Self::MAGIC,
236 conn_id,
237 handler_id,
238 rip: [0; 16],
239 rport: 0,
240 payload,
241 checksum,
242 is_response: true,
243 }
244 }
245
246 pub fn is_valid(&self) -> bool {
248 self.magic == Self::MAGIC && crc32fast::hash(&self.payload) == self.checksum
249 }
250}
251
252#[derive(Archive, Serialize, Deserialize, Debug, Clone, PartialEq)]
254#[rkyv(compare(PartialEq), derive(Debug))]
255pub enum RaftCommand {
256 Upsert {
258 conn_id: u64,
259 txid: u64,
260 client_addr: [u8; 16],
261 nat_entry: (u16, u16),
262 assigned_pod: u32,
263 },
264
265 Delete { conn_id: u64 },
267
268 Cleanup { before_timestamp: u64 },
270
271 Noop,
273}
274
275#[cfg(test)]
276mod tests {
277 use super::*;
278
279 #[test]
280 fn test_frame_creation() {
281 let payload = vec![1, 2, 3, 4, 5];
282 let frame = ProxyFrame::new_data(
283 42,
284 ProxyFrame::ipv4_to_mapped([192, 168, 1, 1]),
285 8080,
286 payload.clone(),
287 );
288
289 assert_eq!(frame.conn_id, 42);
290 assert_eq!(frame.rport, 8080);
291 assert_eq!(frame.payload, payload);
292 assert!(frame.verify_checksum());
293 }
294
295 #[test]
296 fn test_ipv4_mapping() {
297 let ipv4 = [192, 168, 1, 1];
298 let mapped = ProxyFrame::ipv4_to_mapped(ipv4);
299 let extracted = ProxyFrame::mapped_to_ipv4(&mapped);
300
301 assert_eq!(extracted, Some(ipv4));
302 }
303
304 #[test]
305 fn test_serialization() {
306 let frame = ProxyFrame::new_data(1, [0; 16], 443, vec![0xDE, 0xAD, 0xBE, 0xEF]);
307
308 let bytes = rkyv::to_bytes::<rkyv::rancor::Error>(&frame).unwrap();
309 let archived = rkyv::access::<ArchivedProxyFrame, rkyv::rancor::Error>(&bytes).unwrap();
310
311 assert_eq!(archived.conn_id, 1);
312 assert_eq!(archived.rport, 443);
313 }
314}