stackforge_core/layer/quic/
builder.rs1use super::headers::QuicPacketType;
8use super::varint;
9
10#[derive(Debug, Clone)]
27pub struct QuicBuilder {
28 is_long_header: bool,
30 packet_type: QuicPacketType,
32 version: u32,
34 dst_conn_id: Vec<u8>,
36 src_conn_id: Vec<u8>,
38 token: Vec<u8>,
40 payload: Vec<u8>,
42 packet_number: u32,
44}
45
46impl Default for QuicBuilder {
47 fn default() -> Self {
48 Self::new()
49 }
50}
51
52impl QuicBuilder {
53 #[must_use]
56 pub fn new() -> Self {
57 Self {
58 is_long_header: true,
59 packet_type: QuicPacketType::Initial,
60 version: 1,
61 dst_conn_id: Vec::new(),
62 src_conn_id: Vec::new(),
63 token: Vec::new(),
64 payload: Vec::new(),
65 packet_number: 0,
66 }
67 }
68
69 #[must_use]
71 pub fn initial() -> Self {
72 Self {
73 is_long_header: true,
74 packet_type: QuicPacketType::Initial,
75 version: 1,
76 ..Self::new()
77 }
78 }
79
80 #[must_use]
82 pub fn handshake() -> Self {
83 Self {
84 is_long_header: true,
85 packet_type: QuicPacketType::Handshake,
86 version: 1,
87 ..Self::new()
88 }
89 }
90
91 #[must_use]
94 pub fn one_rtt() -> Self {
95 Self {
96 is_long_header: false,
97 packet_type: QuicPacketType::OneRtt,
98 version: 1,
99 ..Self::new()
100 }
101 }
102
103 #[must_use]
105 pub fn dst_conn_id(mut self, id: Vec<u8>) -> Self {
106 self.dst_conn_id = id;
107 self
108 }
109
110 #[must_use]
112 pub fn src_conn_id(mut self, id: Vec<u8>) -> Self {
113 self.src_conn_id = id;
114 self
115 }
116
117 #[must_use]
119 pub fn version(mut self, v: u32) -> Self {
120 self.version = v;
121 self
122 }
123
124 #[must_use]
126 pub fn token(mut self, t: Vec<u8>) -> Self {
127 self.token = t;
128 self
129 }
130
131 #[must_use]
133 pub fn payload(mut self, p: Vec<u8>) -> Self {
134 self.payload = p;
135 self
136 }
137
138 #[must_use]
140 pub fn packet_number(mut self, n: u32) -> Self {
141 self.packet_number = n;
142 self
143 }
144
145 #[must_use]
150 pub fn build(&self) -> Vec<u8> {
151 if self.is_long_header {
152 self.build_long()
153 } else {
154 self.build_short()
155 }
156 }
157
158 fn pn_len(&self) -> usize {
164 if self.packet_number < 0x100 {
165 1
166 } else if self.packet_number < 0x1_0000 {
167 2
168 } else if self.packet_number < 0x100_0000 {
169 3
170 } else {
171 4
172 }
173 }
174
175 fn encode_pn(&self) -> Vec<u8> {
177 let n = self.pn_len();
178 let pn = self.packet_number;
179 match n {
180 1 => vec![pn as u8],
181 2 => (pn as u16).to_be_bytes().to_vec(),
182 3 => {
183 let b = pn.to_be_bytes();
184 vec![b[1], b[2], b[3]]
185 },
186 _ => pn.to_be_bytes().to_vec(),
187 }
188 }
189
190 fn long_type_bits(&self) -> u8 {
192 match self.packet_type {
193 QuicPacketType::Initial => 0x00,
194 QuicPacketType::ZeroRtt => 0x01,
195 QuicPacketType::Handshake => 0x02,
196 QuicPacketType::Retry => 0x03,
197 _ => 0x00,
199 }
200 }
201
202 fn build_long(&self) -> Vec<u8> {
204 let pn_len = self.pn_len();
205 let pn_bytes = self.encode_pn();
206
207 let length_val = (pn_len + self.payload.len()) as u64;
209 let length_varint = varint::encode(length_val);
210
211 let first_byte: u8 = 0x80 | 0x40 | (self.long_type_bits() << 4)
220 | ((pn_len as u8) - 1); let mut out = Vec::new();
223
224 out.push(first_byte);
226
227 out.extend_from_slice(&self.version.to_be_bytes());
229
230 out.push(self.dst_conn_id.len() as u8);
232 out.extend_from_slice(&self.dst_conn_id);
233
234 out.push(self.src_conn_id.len() as u8);
236 out.extend_from_slice(&self.src_conn_id);
237
238 if self.packet_type == QuicPacketType::Initial {
240 out.extend_from_slice(&varint::encode(self.token.len() as u64));
241 out.extend_from_slice(&self.token);
242 }
243
244 out.extend_from_slice(&length_varint);
246
247 out.extend_from_slice(&pn_bytes);
249
250 out.extend_from_slice(&self.payload);
252
253 out
254 }
255
256 fn build_short(&self) -> Vec<u8> {
258 let pn_len = self.pn_len();
259 let pn_bytes = self.encode_pn();
260
261 let first_byte: u8 = 0x40 | ((pn_len as u8) - 1);
269
270 let mut out = Vec::new();
271 out.push(first_byte);
272
273 out.extend_from_slice(&self.dst_conn_id);
275
276 out.extend_from_slice(&pn_bytes);
278
279 out.extend_from_slice(&self.payload);
281
282 out
283 }
284}
285
286pub type QuicInitialBuilder = QuicBuilder;
288
289#[cfg(test)]
290mod tests {
291 use super::*;
292 use crate::layer::quic::headers::{QuicLongHeader, QuicShortHeader};
293
294 #[test]
295 fn test_build_initial_basic() {
296 let bytes = QuicBuilder::initial()
297 .dst_conn_id(vec![0x01, 0x02, 0x03, 0x04])
298 .src_conn_id(vec![])
299 .payload(vec![0xAA, 0xBB])
300 .build();
301
302 assert_eq!(bytes[0] & 0x80, 0x80, "Header Form must be 1 (long)");
304 assert_eq!(bytes[0] & 0x40, 0x40, "Fixed Bit must be 1");
305 assert_eq!((bytes[0] & 0x30) >> 4, 0x00);
307
308 assert_eq!(&bytes[1..5], &[0x00, 0x00, 0x00, 0x01]);
310
311 assert_eq!(bytes[5], 4);
313 assert_eq!(&bytes[6..10], &[0x01, 0x02, 0x03, 0x04]);
314
315 assert_eq!(bytes[10], 0);
317 }
318
319 #[test]
320 fn test_build_initial_parse_back() {
321 let bytes = QuicBuilder::initial()
322 .dst_conn_id(vec![0xDE, 0xAD, 0xBE, 0xEF])
323 .src_conn_id(vec![0x11, 0x22])
324 .build();
325
326 let hdr = QuicLongHeader::parse(&bytes).unwrap();
327 assert_eq!(hdr.packet_type, QuicPacketType::Initial);
328 assert_eq!(hdr.dst_conn_id, vec![0xDE, 0xAD, 0xBE, 0xEF]);
329 assert_eq!(hdr.src_conn_id, vec![0x11, 0x22]);
330 assert_eq!(hdr.version, 1);
331 }
332
333 #[test]
334 fn test_build_handshake() {
335 let bytes = QuicBuilder::handshake()
336 .dst_conn_id(vec![0x01])
337 .payload(vec![0x06, 0x00, 0x01, 0xFF]) .build();
339
340 assert_eq!(bytes[0] & 0x80, 0x80, "long header");
341 assert_eq!((bytes[0] & 0x30) >> 4, 0x02, "Handshake type bits");
342
343 let hdr = QuicLongHeader::parse(&bytes).unwrap();
344 assert_eq!(hdr.packet_type, QuicPacketType::Handshake);
345 }
346
347 #[test]
348 fn test_build_one_rtt() {
349 let bytes = QuicBuilder::one_rtt()
350 .payload(vec![0x01]) .build();
352
353 assert_eq!(bytes[0] & 0x80, 0x00, "short header");
355 assert_eq!(bytes[0] & 0x40, 0x40, "Fixed Bit must be 1");
356
357 let hdr = QuicShortHeader::parse(&bytes).unwrap();
358 assert_eq!(hdr.header_len, 1);
359 }
360
361 #[test]
362 fn test_build_with_token() {
363 let bytes = QuicBuilder::initial()
364 .token(vec![0xCA, 0xFE])
365 .payload(vec![])
366 .build();
367
368 assert!(bytes.len() >= 12);
374 }
375
376 #[test]
377 fn test_packet_number_encoding() {
378 let bytes = QuicBuilder::initial().packet_number(0).build();
380 assert_eq!(bytes[0] & 0x03, 0, "pn_len-1 = 0 for 1-byte PN");
381
382 let bytes = QuicBuilder::initial().packet_number(0x1234_5678).build();
384 assert_eq!(bytes[0] & 0x03, 3, "pn_len-1 = 3 for 4-byte PN");
385 }
386}