1use super::super::packet::header::{
4 QuicConnectionId, QuicConnectionIdField, QuicLongHeader, QuicLongPacketType, QuicVersion,
5};
6use super::super::packet::long::QuicProtectedLongPacket;
7use super::super::varint::{QuicVarInt, QuicVarIntBuildError, QuicVarIntLen};
8use super::{QuicPacketBuildError, QuicPacketBuildField};
9
10pub struct QuicInitialPacketBuilder<'buffer, 'input> {
12 destination: &'buffer mut [u8],
13 version: QuicVersion,
14 protected_low_bits: u8,
15 destination_connection_id: QuicConnectionId<'input>,
16 source_connection_id: QuicConnectionId<'input>,
17 token: &'input [u8],
18 protected_remainder: &'input [u8],
19 token_length_len: Option<QuicVarIntLen>,
20 length_len: Option<QuicVarIntLen>,
21}
22
23impl<'buffer, 'input> QuicInitialPacketBuilder<'buffer, 'input> {
24 pub fn new(
26 destination: &'buffer mut [u8],
27 version: QuicVersion,
28 protected_low_bits: u8,
29 destination_connection_id: QuicConnectionId<'input>,
30 source_connection_id: QuicConnectionId<'input>,
31 token: &'input [u8],
32 protected_remainder: &'input [u8],
33 ) -> Self {
34 Self {
35 destination,
36 version,
37 protected_low_bits,
38 destination_connection_id,
39 source_connection_id,
40 token,
41 protected_remainder,
42 token_length_len: None,
43 length_len: None,
44 }
45 }
46
47 pub fn with_token_length_len(mut self, length: QuicVarIntLen) -> Self {
49 self.token_length_len = Some(length);
50 self
51 }
52
53 pub fn with_length_len(mut self, length: QuicVarIntLen) -> Self {
55 self.length_len = Some(length);
56 self
57 }
58
59 pub fn build(self) -> Result<QuicProtectedLongPacket<'buffer>, QuicPacketBuildError> {
61 build_long(BuildInput {
62 destination: self.destination,
63 version: self.version,
64 protected_low_bits: self.protected_low_bits,
65 destination_connection_id: self.destination_connection_id,
66 source_connection_id: self.source_connection_id,
67 packet_type: QuicLongPacketType::Initial,
68 token: Some(self.token),
69 token_length_len: self.token_length_len,
70 length_len: self.length_len,
71 protected_remainder: self.protected_remainder,
72 })
73 }
74}
75
76pub struct QuicZeroRttPacketBuilder<'buffer, 'input> {
78 destination: &'buffer mut [u8],
79 version: QuicVersion,
80 protected_low_bits: u8,
81 destination_connection_id: QuicConnectionId<'input>,
82 source_connection_id: QuicConnectionId<'input>,
83 protected_remainder: &'input [u8],
84 length_len: Option<QuicVarIntLen>,
85}
86
87impl<'buffer, 'input> QuicZeroRttPacketBuilder<'buffer, 'input> {
88 pub fn new(
90 destination: &'buffer mut [u8],
91 version: QuicVersion,
92 protected_low_bits: u8,
93 destination_connection_id: QuicConnectionId<'input>,
94 source_connection_id: QuicConnectionId<'input>,
95 protected_remainder: &'input [u8],
96 ) -> Self {
97 Self {
98 destination,
99 version,
100 protected_low_bits,
101 destination_connection_id,
102 source_connection_id,
103 protected_remainder,
104 length_len: None,
105 }
106 }
107
108 pub fn with_length_len(mut self, length: QuicVarIntLen) -> Self {
110 self.length_len = Some(length);
111 self
112 }
113
114 pub fn build(self) -> Result<QuicProtectedLongPacket<'buffer>, QuicPacketBuildError> {
116 build_long(BuildInput {
117 destination: self.destination,
118 version: self.version,
119 protected_low_bits: self.protected_low_bits,
120 destination_connection_id: self.destination_connection_id,
121 source_connection_id: self.source_connection_id,
122 packet_type: QuicLongPacketType::ZeroRtt,
123 token: None,
124 token_length_len: None,
125 length_len: self.length_len,
126 protected_remainder: self.protected_remainder,
127 })
128 }
129}
130
131pub struct QuicHandshakePacketBuilder<'buffer, 'input> {
133 destination: &'buffer mut [u8],
134 version: QuicVersion,
135 protected_low_bits: u8,
136 destination_connection_id: QuicConnectionId<'input>,
137 source_connection_id: QuicConnectionId<'input>,
138 protected_remainder: &'input [u8],
139 length_len: Option<QuicVarIntLen>,
140}
141
142impl<'buffer, 'input> QuicHandshakePacketBuilder<'buffer, 'input> {
143 pub fn new(
145 destination: &'buffer mut [u8],
146 version: QuicVersion,
147 protected_low_bits: u8,
148 destination_connection_id: QuicConnectionId<'input>,
149 source_connection_id: QuicConnectionId<'input>,
150 protected_remainder: &'input [u8],
151 ) -> Self {
152 Self {
153 destination,
154 version,
155 protected_low_bits,
156 destination_connection_id,
157 source_connection_id,
158 protected_remainder,
159 length_len: None,
160 }
161 }
162
163 pub fn with_length_len(mut self, length: QuicVarIntLen) -> Self {
165 self.length_len = Some(length);
166 self
167 }
168
169 pub fn build(self) -> Result<QuicProtectedLongPacket<'buffer>, QuicPacketBuildError> {
171 build_long(BuildInput {
172 destination: self.destination,
173 version: self.version,
174 protected_low_bits: self.protected_low_bits,
175 destination_connection_id: self.destination_connection_id,
176 source_connection_id: self.source_connection_id,
177 packet_type: QuicLongPacketType::Handshake,
178 token: None,
179 token_length_len: None,
180 length_len: self.length_len,
181 protected_remainder: self.protected_remainder,
182 })
183 }
184}
185
186struct BuildInput<'buffer, 'input> {
187 destination: &'buffer mut [u8],
188 version: QuicVersion,
189 protected_low_bits: u8,
190 destination_connection_id: QuicConnectionId<'input>,
191 source_connection_id: QuicConnectionId<'input>,
192 packet_type: QuicLongPacketType,
193 token: Option<&'input [u8]>,
194 token_length_len: Option<QuicVarIntLen>,
195 length_len: Option<QuicVarIntLen>,
196 protected_remainder: &'input [u8],
197}
198
199fn build_long<'buffer>(
200 input: BuildInput<'buffer, '_>,
201) -> Result<QuicProtectedLongPacket<'buffer>, QuicPacketBuildError> {
202 let raw_type = input.packet_type.raw_type(input.version).ok_or(
203 QuicPacketBuildError::UnsupportedVersion {
204 version: input.version,
205 },
206 )?;
207 if input.protected_low_bits > 0x0f {
208 return Err(QuicPacketBuildError::ProtectedLowBitsOutOfRange {
209 maximum: 0x0f,
210 actual: input.protected_low_bits,
211 });
212 }
213 validate_connection_id(
214 QuicConnectionIdField::Destination,
215 input.destination_connection_id.len(),
216 )?;
217 validate_connection_id(
218 QuicConnectionIdField::Source,
219 input.source_connection_id.len(),
220 )?;
221 if input.protected_remainder.len() < 2 {
222 return Err(QuicPacketBuildError::ProtectedRemainderTooShort {
223 minimum: 2,
224 actual: input.protected_remainder.len(),
225 });
226 }
227
228 let protected_length = u64::try_from(input.protected_remainder.len()).map_err(|_| {
229 QuicPacketBuildError::VarInt {
230 field: QuicPacketBuildField::ProtectedLength,
231 error: QuicVarIntBuildError::ValueTooLarge { value: u64::MAX },
232 }
233 })?;
234 let length_len = validate_varint(
235 QuicPacketBuildField::ProtectedLength,
236 protected_length,
237 input.length_len,
238 )?;
239 let token_length = input.token.map(|token| token.len());
240 let token_length_value = match token_length {
241 Some(length) => u64::try_from(length).map_err(|_| QuicPacketBuildError::VarInt {
242 field: QuicPacketBuildField::TokenLength,
243 error: QuicVarIntBuildError::ValueTooLarge { value: u64::MAX },
244 })?,
245 None => 0,
246 };
247 let token_length_len = match token_length {
248 Some(_) => Some(validate_varint(
249 QuicPacketBuildField::TokenLength,
250 token_length_value,
251 input.token_length_len,
252 )?),
253 None => None,
254 };
255
256 let destination_start = 6;
257 let destination_end = checked_add(
258 destination_start,
259 input.destination_connection_id.len(),
260 "destination connection ID",
261 )?;
262 let source_length_offset = destination_end;
263 let source_start = checked_add(source_length_offset, 1, "source connection ID length")?;
264 let source_end = checked_add(
265 source_start,
266 input.source_connection_id.len(),
267 "source connection ID",
268 )?;
269 let token_length_offset = source_end;
270 let token_start = match (input.token, token_length_len) {
271 (Some(_), Some(length)) => {
272 checked_add(token_length_offset, length.byte_len(), "token length")?
273 }
274 (None, None) => source_end,
275 _ => {
276 return Err(QuicPacketBuildError::LengthOverflow {
277 component: "token fields",
278 offset: source_end,
279 length: 0,
280 });
281 }
282 };
283 let token_end = match input.token {
284 Some(token) => checked_add(token_start, token.len(), "Initial token")?,
285 None => token_start,
286 };
287 let length_offset = token_end;
288 let packet_number_offset =
289 checked_add(length_offset, length_len.byte_len(), "protected length")?;
290 let required = checked_add(
291 packet_number_offset,
292 input.protected_remainder.len(),
293 "protected remainder",
294 )?;
295 if input.destination.len() < required {
296 return Err(QuicPacketBuildError::BufferTooShort {
297 required,
298 available: input.destination.len(),
299 });
300 }
301
302 let destination = input.destination;
303 destination[0] = 0xc0 | (raw_type << 4) | input.protected_low_bits;
304 destination[1..5].copy_from_slice(&input.version.raw().to_be_bytes());
305 destination[5] = input.destination_connection_id.len() as u8;
306 destination[destination_start..destination_end]
307 .copy_from_slice(input.destination_connection_id.as_bytes());
308 destination[source_length_offset] = input.source_connection_id.len() as u8;
309 destination[source_start..source_end].copy_from_slice(input.source_connection_id.as_bytes());
310 if let (Some(token), Some(token_length_len)) = (input.token, token_length_len) {
311 write_varint(
312 &mut destination[token_length_offset..token_start],
313 token_length_value,
314 token_length_len,
315 );
316 destination[token_start..token_end].copy_from_slice(token);
317 }
318 write_varint(
319 &mut destination[length_offset..packet_number_offset],
320 protected_length,
321 length_len,
322 );
323 destination[packet_number_offset..required].copy_from_slice(input.protected_remainder);
324
325 let bytes = &destination[..required];
326 let header = QuicLongHeader::from_validated(
327 &bytes[..source_end],
328 bytes[0],
329 input.version,
330 QuicConnectionId::new(&bytes[destination_start..destination_end]),
331 QuicConnectionId::new(&bytes[source_start..source_end]),
332 &bytes[source_end..],
333 );
334 let token_length = token_length_len.map(|length| {
335 QuicVarInt::from_validated(
336 &bytes[token_length_offset..token_start],
337 token_length_value,
338 length,
339 )
340 });
341 let token_fields =
342 token_length.map(|token_length| (token_length, &bytes[token_start..token_end]));
343 let length = QuicVarInt::from_validated(
344 &bytes[length_offset..packet_number_offset],
345 protected_length,
346 length_len,
347 );
348 Ok(QuicProtectedLongPacket::from_validated(
349 bytes,
350 header,
351 input.packet_type,
352 token_fields,
353 length,
354 packet_number_offset,
355 &bytes[packet_number_offset..required],
356 ))
357}
358
359fn validate_connection_id(
360 field: QuicConnectionIdField,
361 actual: usize,
362) -> Result<(), QuicPacketBuildError> {
363 if actual > 20 {
364 return Err(QuicPacketBuildError::ConnectionIdTooLong {
365 field,
366 maximum: 20,
367 actual,
368 });
369 }
370 Ok(())
371}
372
373fn validate_varint(
374 field: QuicPacketBuildField,
375 value: u64,
376 requested: Option<QuicVarIntLen>,
377) -> Result<QuicVarIntLen, QuicPacketBuildError> {
378 if value > QuicVarIntLen::Eight.max_value() {
379 return Err(QuicPacketBuildError::VarInt {
380 field,
381 error: QuicVarIntBuildError::ValueTooLarge { value },
382 });
383 }
384 let length = requested.unwrap_or_else(|| canonical_len(value));
385 if value > length.max_value() {
386 return Err(QuicPacketBuildError::VarInt {
387 field,
388 error: QuicVarIntBuildError::WidthTooSmall { length, value },
389 });
390 }
391 Ok(length)
392}
393
394const fn canonical_len(value: u64) -> QuicVarIntLen {
395 if value <= QuicVarIntLen::One.max_value() {
396 QuicVarIntLen::One
397 } else if value <= QuicVarIntLen::Two.max_value() {
398 QuicVarIntLen::Two
399 } else if value <= QuicVarIntLen::Four.max_value() {
400 QuicVarIntLen::Four
401 } else {
402 QuicVarIntLen::Eight
403 }
404}
405
406fn checked_add(
407 offset: usize,
408 length: usize,
409 component: &'static str,
410) -> Result<usize, QuicPacketBuildError> {
411 offset
412 .checked_add(length)
413 .ok_or(QuicPacketBuildError::LengthOverflow {
414 component,
415 offset,
416 length,
417 })
418}
419
420fn write_varint(destination: &mut [u8], value: u64, length: QuicVarIntLen) {
421 let value_bytes = value.to_be_bytes();
422 let length_bytes = length.byte_len();
423 destination.copy_from_slice(&value_bytes[value_bytes.len() - length_bytes..]);
424 destination[0] |= match length {
425 QuicVarIntLen::One => 0,
426 QuicVarIntLen::Two => 0x40,
427 QuicVarIntLen::Four => 0x80,
428 QuicVarIntLen::Eight => 0xc0,
429 };
430}