1use super::parse::QuicPacketParseError;
4
5#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
11pub struct QuicConnectionId<'a>(&'a [u8]);
12
13impl<'a> QuicConnectionId<'a> {
14 pub const fn new(bytes: &'a [u8]) -> Self {
16 Self(bytes)
17 }
18
19 pub const fn as_bytes(self) -> &'a [u8] {
21 self.0
22 }
23
24 pub const fn len(self) -> usize {
26 self.0.len()
27 }
28
29 pub const fn is_empty(self) -> bool {
31 self.0.is_empty()
32 }
33}
34
35#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
37pub enum QuicConnectionIdField {
38 Destination,
40 Source,
42}
43
44#[repr(transparent)]
46#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
47pub struct QuicVersion(u32);
48
49impl QuicVersion {
50 pub const NEGOTIATION: Self = Self(0);
52 pub const V1: Self = Self(1);
54 pub const V2: Self = Self(0x6b33_43cf);
56
57 pub const fn new(raw: u32) -> Self {
59 Self(raw)
60 }
61
62 pub const fn raw(self) -> u32 {
64 self.0
65 }
66
67 pub const fn is_reserved(self) -> bool {
69 self.0 & 0x0f0f_0f0f == 0x0a0a_0a0a
70 }
71}
72
73#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
75pub enum QuicLongPacketType {
76 Initial,
78 ZeroRtt,
80 Handshake,
82 Retry,
84}
85
86impl QuicLongPacketType {
87 pub const fn from_raw(version: QuicVersion, raw_type: u8) -> Option<Self> {
89 if raw_type > 3 {
90 return None;
91 }
92 match version {
93 QuicVersion::V1 => match raw_type {
94 0 => Some(Self::Initial),
95 1 => Some(Self::ZeroRtt),
96 2 => Some(Self::Handshake),
97 _ => Some(Self::Retry),
98 },
99 QuicVersion::V2 => match raw_type {
100 0 => Some(Self::Retry),
101 1 => Some(Self::Initial),
102 2 => Some(Self::ZeroRtt),
103 _ => Some(Self::Handshake),
104 },
105 _ => None,
106 }
107 }
108
109 pub const fn raw_type(self, version: QuicVersion) -> Option<u8> {
111 match version {
112 QuicVersion::V1 => match self {
113 Self::Initial => Some(0),
114 Self::ZeroRtt => Some(1),
115 Self::Handshake => Some(2),
116 Self::Retry => Some(3),
117 },
118 QuicVersion::V2 => match self {
119 Self::Initial => Some(1),
120 Self::ZeroRtt => Some(2),
121 Self::Handshake => Some(3),
122 Self::Retry => Some(0),
123 },
124 _ => None,
125 }
126 }
127}
128
129const HEADER_FORM_BIT: u8 = 0x80;
130const FIXED_BIT: u8 = 0x40;
131const LONG_TYPE_SHIFT: u8 = 4;
132const LONG_TYPE_MASK: u8 = 0x03;
133
134#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
140pub struct QuicShortHeaderContext {
141 destination_connection_id_len: usize,
142}
143
144impl QuicShortHeaderContext {
145 pub const fn new(destination_connection_id_len: usize) -> Self {
147 Self {
148 destination_connection_id_len,
149 }
150 }
151
152 pub const fn destination_connection_id_len(self) -> usize {
154 self.destination_connection_id_len
155 }
156}
157
158#[derive(Clone, Copy, Debug, Eq, PartialEq)]
164pub struct QuicLongHeader<'a> {
165 bytes: &'a [u8],
166 first_byte: u8,
167 version: QuicVersion,
168 destination_connection_id: QuicConnectionId<'a>,
169 source_connection_id: QuicConnectionId<'a>,
170 version_specific: &'a [u8],
171}
172
173impl<'a> QuicLongHeader<'a> {
174 pub(crate) const fn from_validated(
176 bytes: &'a [u8],
177 first_byte: u8,
178 version: QuicVersion,
179 destination_connection_id: QuicConnectionId<'a>,
180 source_connection_id: QuicConnectionId<'a>,
181 version_specific: &'a [u8],
182 ) -> Self {
183 Self {
184 bytes,
185 first_byte,
186 version,
187 destination_connection_id,
188 source_connection_id,
189 version_specific,
190 }
191 }
192
193 pub fn parse(bytes: &'a [u8]) -> Result<Self, QuicPacketParseError> {
195 let first_byte = first_byte(bytes)?;
196 if first_byte & HEADER_FORM_BIT == 0 {
197 return Err(QuicPacketParseError::WrongHeaderForm {
198 expected_long: true,
199 first_byte,
200 });
201 }
202
203 require(bytes, 5)?;
204 let version =
205 QuicVersion::new(u32::from_be_bytes([bytes[1], bytes[2], bytes[3], bytes[4]]));
206 require(bytes, 6)?;
207 let destination_len = usize::from(bytes[5]);
208 let destination_end = field_end(6, destination_len)?;
209 require(bytes, destination_end)?;
210 let destination_connection_id = QuicConnectionId::new(&bytes[6..destination_end]);
211
212 let source_len_offset = destination_end;
213 let source_start = field_end(source_len_offset, 1)?;
214 require(bytes, source_start)?;
215 let source_len = usize::from(bytes[source_len_offset]);
216 let source_end = field_end(source_start, source_len)?;
217 require(bytes, source_end)?;
218
219 Ok(Self {
220 bytes: &bytes[..source_end],
221 first_byte,
222 version,
223 destination_connection_id,
224 source_connection_id: QuicConnectionId::new(&bytes[source_start..source_end]),
225 version_specific: &bytes[source_end..],
226 })
227 }
228
229 pub const fn first_byte(self) -> u8 {
231 self.first_byte
232 }
233
234 pub const fn has_fixed_bit(self) -> bool {
236 self.first_byte & FIXED_BIT != 0
237 }
238
239 pub const fn raw_type_bits(self) -> u8 {
241 (self.first_byte >> LONG_TYPE_SHIFT) & LONG_TYPE_MASK
242 }
243
244 pub const fn version(self) -> QuicVersion {
246 self.version
247 }
248
249 pub const fn destination_connection_id(self) -> QuicConnectionId<'a> {
251 self.destination_connection_id
252 }
253
254 pub const fn source_connection_id(self) -> QuicConnectionId<'a> {
256 self.source_connection_id
257 }
258
259 pub const fn as_bytes(self) -> &'a [u8] {
261 self.bytes
262 }
263
264 pub const fn version_specific(self) -> &'a [u8] {
266 self.version_specific
267 }
268
269 pub const fn long_packet_type(self) -> Option<QuicLongPacketType> {
271 QuicLongPacketType::from_raw(self.version, self.raw_type_bits())
272 }
273}
274
275#[derive(Clone, Copy, Debug, Eq, PartialEq)]
281pub struct QuicShortHeader<'a> {
282 bytes: &'a [u8],
283 first_byte: u8,
284 destination_connection_id: QuicConnectionId<'a>,
285 protected_remainder: &'a [u8],
286}
287
288impl<'a> QuicShortHeader<'a> {
289 pub(crate) const fn from_validated(
291 bytes: &'a [u8],
292 first_byte: u8,
293 destination_connection_id: QuicConnectionId<'a>,
294 protected_remainder: &'a [u8],
295 ) -> Self {
296 Self {
297 bytes,
298 first_byte,
299 destination_connection_id,
300 protected_remainder,
301 }
302 }
303
304 pub fn parse(
306 bytes: &'a [u8],
307 context: QuicShortHeaderContext,
308 ) -> Result<Self, QuicPacketParseError> {
309 let first_byte = first_byte(bytes)?;
310 if first_byte & HEADER_FORM_BIT != 0 {
311 return Err(QuicPacketParseError::WrongHeaderForm {
312 expected_long: false,
313 first_byte,
314 });
315 }
316
317 let destination_end = field_end(1, context.destination_connection_id_len())?;
318 require(bytes, destination_end)?;
319 Ok(Self {
320 bytes,
321 first_byte,
322 destination_connection_id: QuicConnectionId::new(&bytes[1..destination_end]),
323 protected_remainder: &bytes[destination_end..],
324 })
325 }
326
327 pub const fn first_byte(self) -> u8 {
329 self.first_byte
330 }
331
332 pub const fn has_fixed_bit(self) -> bool {
334 self.first_byte & FIXED_BIT != 0
335 }
336
337 pub const fn destination_connection_id(self) -> QuicConnectionId<'a> {
339 self.destination_connection_id
340 }
341
342 pub const fn protected_remainder(self) -> &'a [u8] {
344 self.protected_remainder
345 }
346
347 pub const fn as_bytes(self) -> &'a [u8] {
349 self.bytes
350 }
351}
352
353fn first_byte(bytes: &[u8]) -> Result<u8, QuicPacketParseError> {
354 bytes
355 .first()
356 .copied()
357 .ok_or(QuicPacketParseError::Incomplete {
358 required: 1,
359 available: 0,
360 })
361}
362
363fn field_end(offset: usize, length: usize) -> Result<usize, QuicPacketParseError> {
364 offset
365 .checked_add(length)
366 .ok_or(QuicPacketParseError::LengthOverflow { offset, length })
367}
368
369fn require(bytes: &[u8], required: usize) -> Result<(), QuicPacketParseError> {
370 if bytes.len() < required {
371 return Err(QuicPacketParseError::Incomplete {
372 required,
373 available: bytes.len(),
374 });
375 }
376 Ok(())
377}