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 pub fn new() -> Self {
56 Self {
57 is_long_header: true,
58 packet_type: QuicPacketType::Initial,
59 version: 1,
60 dst_conn_id: Vec::new(),
61 src_conn_id: Vec::new(),
62 token: Vec::new(),
63 payload: Vec::new(),
64 packet_number: 0,
65 }
66 }
67
68 pub fn initial() -> Self {
70 Self {
71 is_long_header: true,
72 packet_type: QuicPacketType::Initial,
73 version: 1,
74 ..Self::new()
75 }
76 }
77
78 pub fn handshake() -> Self {
80 Self {
81 is_long_header: true,
82 packet_type: QuicPacketType::Handshake,
83 version: 1,
84 ..Self::new()
85 }
86 }
87
88 pub fn one_rtt() -> Self {
91 Self {
92 is_long_header: false,
93 packet_type: QuicPacketType::OneRtt,
94 version: 1,
95 ..Self::new()
96 }
97 }
98
99 pub fn dst_conn_id(mut self, id: Vec<u8>) -> Self {
101 self.dst_conn_id = id;
102 self
103 }
104
105 pub fn src_conn_id(mut self, id: Vec<u8>) -> Self {
107 self.src_conn_id = id;
108 self
109 }
110
111 pub fn version(mut self, v: u32) -> Self {
113 self.version = v;
114 self
115 }
116
117 pub fn token(mut self, t: Vec<u8>) -> Self {
119 self.token = t;
120 self
121 }
122
123 pub fn payload(mut self, p: Vec<u8>) -> Self {
125 self.payload = p;
126 self
127 }
128
129 pub fn packet_number(mut self, n: u32) -> Self {
131 self.packet_number = n;
132 self
133 }
134
135 pub fn build(&self) -> Vec<u8> {
140 if self.is_long_header {
141 self.build_long()
142 } else {
143 self.build_short()
144 }
145 }
146
147 fn pn_len(&self) -> usize {
153 if self.packet_number < 0x100 {
154 1
155 } else if self.packet_number < 0x1_0000 {
156 2
157 } else if self.packet_number < 0x100_0000 {
158 3
159 } else {
160 4
161 }
162 }
163
164 fn encode_pn(&self) -> Vec<u8> {
166 let n = self.pn_len();
167 let pn = self.packet_number;
168 match n {
169 1 => vec![pn as u8],
170 2 => (pn as u16).to_be_bytes().to_vec(),
171 3 => {
172 let b = pn.to_be_bytes();
173 vec![b[1], b[2], b[3]]
174 }
175 _ => pn.to_be_bytes().to_vec(),
176 }
177 }
178
179 fn long_type_bits(&self) -> u8 {
181 match self.packet_type {
182 QuicPacketType::Initial => 0x00,
183 QuicPacketType::ZeroRtt => 0x01,
184 QuicPacketType::Handshake => 0x02,
185 QuicPacketType::Retry => 0x03,
186 _ => 0x00,
188 }
189 }
190
191 fn build_long(&self) -> Vec<u8> {
193 let pn_len = self.pn_len();
194 let pn_bytes = self.encode_pn();
195
196 let length_val = (pn_len + self.payload.len()) as u64;
198 let length_varint = varint::encode(length_val);
199
200 let first_byte: u8 = 0x80 | 0x40 | (self.long_type_bits() << 4)
209 | ((pn_len as u8) - 1); let mut out = Vec::new();
212
213 out.push(first_byte);
215
216 out.extend_from_slice(&self.version.to_be_bytes());
218
219 out.push(self.dst_conn_id.len() as u8);
221 out.extend_from_slice(&self.dst_conn_id);
222
223 out.push(self.src_conn_id.len() as u8);
225 out.extend_from_slice(&self.src_conn_id);
226
227 if self.packet_type == QuicPacketType::Initial {
229 out.extend_from_slice(&varint::encode(self.token.len() as u64));
230 out.extend_from_slice(&self.token);
231 }
232
233 out.extend_from_slice(&length_varint);
235
236 out.extend_from_slice(&pn_bytes);
238
239 out.extend_from_slice(&self.payload);
241
242 out
243 }
244
245 fn build_short(&self) -> Vec<u8> {
247 let pn_len = self.pn_len();
248 let pn_bytes = self.encode_pn();
249
250 let first_byte: u8 = 0x40 | ((pn_len as u8) - 1);
258
259 let mut out = Vec::new();
260 out.push(first_byte);
261
262 out.extend_from_slice(&self.dst_conn_id);
264
265 out.extend_from_slice(&pn_bytes);
267
268 out.extend_from_slice(&self.payload);
270
271 out
272 }
273}
274
275pub type QuicInitialBuilder = QuicBuilder;
277
278#[cfg(test)]
279mod tests {
280 use super::*;
281 use crate::layer::quic::headers::{QuicLongHeader, QuicShortHeader};
282
283 #[test]
284 fn test_build_initial_basic() {
285 let bytes = QuicBuilder::initial()
286 .dst_conn_id(vec![0x01, 0x02, 0x03, 0x04])
287 .src_conn_id(vec![])
288 .payload(vec![0xAA, 0xBB])
289 .build();
290
291 assert_eq!(bytes[0] & 0x80, 0x80, "Header Form must be 1 (long)");
293 assert_eq!(bytes[0] & 0x40, 0x40, "Fixed Bit must be 1");
294 assert_eq!((bytes[0] & 0x30) >> 4, 0x00);
296
297 assert_eq!(&bytes[1..5], &[0x00, 0x00, 0x00, 0x01]);
299
300 assert_eq!(bytes[5], 4);
302 assert_eq!(&bytes[6..10], &[0x01, 0x02, 0x03, 0x04]);
303
304 assert_eq!(bytes[10], 0);
306 }
307
308 #[test]
309 fn test_build_initial_parse_back() {
310 let bytes = QuicBuilder::initial()
311 .dst_conn_id(vec![0xDE, 0xAD, 0xBE, 0xEF])
312 .src_conn_id(vec![0x11, 0x22])
313 .build();
314
315 let hdr = QuicLongHeader::parse(&bytes).unwrap();
316 assert_eq!(hdr.packet_type, QuicPacketType::Initial);
317 assert_eq!(hdr.dst_conn_id, vec![0xDE, 0xAD, 0xBE, 0xEF]);
318 assert_eq!(hdr.src_conn_id, vec![0x11, 0x22]);
319 assert_eq!(hdr.version, 1);
320 }
321
322 #[test]
323 fn test_build_handshake() {
324 let bytes = QuicBuilder::handshake()
325 .dst_conn_id(vec![0x01])
326 .payload(vec![0x06, 0x00, 0x01, 0xFF]) .build();
328
329 assert_eq!(bytes[0] & 0x80, 0x80, "long header");
330 assert_eq!((bytes[0] & 0x30) >> 4, 0x02, "Handshake type bits");
331
332 let hdr = QuicLongHeader::parse(&bytes).unwrap();
333 assert_eq!(hdr.packet_type, QuicPacketType::Handshake);
334 }
335
336 #[test]
337 fn test_build_one_rtt() {
338 let bytes = QuicBuilder::one_rtt()
339 .payload(vec![0x01]) .build();
341
342 assert_eq!(bytes[0] & 0x80, 0x00, "short header");
344 assert_eq!(bytes[0] & 0x40, 0x40, "Fixed Bit must be 1");
345
346 let hdr = QuicShortHeader::parse(&bytes).unwrap();
347 assert_eq!(hdr.header_len, 1);
348 }
349
350 #[test]
351 fn test_build_with_token() {
352 let bytes = QuicBuilder::initial()
353 .token(vec![0xCA, 0xFE])
354 .payload(vec![])
355 .build();
356
357 assert!(bytes.len() >= 12);
363 }
364
365 #[test]
366 fn test_packet_number_encoding() {
367 let bytes = QuicBuilder::initial().packet_number(0).build();
369 assert_eq!(bytes[0] & 0x03, 0, "pn_len-1 = 0 for 1-byte PN");
370
371 let bytes = QuicBuilder::initial().packet_number(0x1234_5678).build();
373 assert_eq!(bytes[0] & 0x03, 3, "pn_len-1 = 3 for 4-byte PN");
374 }
375}