net_wire/quic/builder/
short.rs1use super::super::packet::header::{QuicConnectionId, QuicConnectionIdField, QuicShortHeader};
4use super::QuicPacketBuildError;
5
6pub struct QuicShortPacketBuilder<'buffer, 'input> {
11 destination: &'buffer mut [u8],
12 spin: bool,
13 protected_low_bits: u8,
14 destination_connection_id: QuicConnectionId<'input>,
15 protected_remainder: &'input [u8],
16}
17
18impl<'buffer, 'input> QuicShortPacketBuilder<'buffer, 'input> {
19 pub fn new(
21 destination: &'buffer mut [u8],
22 spin: bool,
23 protected_low_bits: u8,
24 destination_connection_id: QuicConnectionId<'input>,
25 protected_remainder: &'input [u8],
26 ) -> Self {
27 Self {
28 destination,
29 spin,
30 protected_low_bits,
31 destination_connection_id,
32 protected_remainder,
33 }
34 }
35
36 pub fn build(self) -> Result<QuicShortHeader<'buffer>, QuicPacketBuildError> {
38 if self.protected_low_bits > 0x1f {
39 return Err(QuicPacketBuildError::ProtectedLowBitsOutOfRange {
40 maximum: 0x1f,
41 actual: self.protected_low_bits,
42 });
43 }
44 if self.destination_connection_id.len() > 20 {
45 return Err(QuicPacketBuildError::ConnectionIdTooLong {
46 field: QuicConnectionIdField::Destination,
47 maximum: 20,
48 actual: self.destination_connection_id.len(),
49 });
50 }
51 if self.protected_remainder.len() < 2 {
52 return Err(QuicPacketBuildError::ProtectedRemainderTooShort {
53 minimum: 2,
54 actual: self.protected_remainder.len(),
55 });
56 }
57
58 let destination_end = checked_add(
59 1,
60 self.destination_connection_id.len(),
61 "destination connection ID",
62 )?;
63 let required = checked_add(
64 destination_end,
65 self.protected_remainder.len(),
66 "protected remainder",
67 )?;
68 if self.destination.len() < required {
69 return Err(QuicPacketBuildError::BufferTooShort {
70 required,
71 available: self.destination.len(),
72 });
73 }
74
75 let destination = self.destination;
76 destination[0] = 0x40 | (u8::from(self.spin) << 5) | self.protected_low_bits;
77 destination[1..destination_end].copy_from_slice(self.destination_connection_id.as_bytes());
78 destination[destination_end..required].copy_from_slice(self.protected_remainder);
79
80 let bytes = &destination[..required];
81 Ok(QuicShortHeader::from_validated(
82 bytes,
83 bytes[0],
84 QuicConnectionId::new(&bytes[1..destination_end]),
85 &bytes[destination_end..],
86 ))
87 }
88}
89
90fn checked_add(
91 offset: usize,
92 length: usize,
93 component: &'static str,
94) -> Result<usize, QuicPacketBuildError> {
95 offset
96 .checked_add(length)
97 .ok_or(QuicPacketBuildError::LengthOverflow {
98 component,
99 offset,
100 length,
101 })
102}