Skip to main content

internet/ietf/quicv1/encoding/
packet_headers.rs

1//! Packet headers encoding following [Section 17].
2//!
3//! > description
4//!
5//! This module provides the following primitives:
6//!
7//! - [`FixedBit`]
8//! - [`LongHeaderPacketType`]
9//! - [`ConnectionId`]
10//! - [`PacketNumberLength`]
11//! - [`PacketNumber`]
12//! - [`Length`]
13//! - [`RetryToken`]
14//! - [`RetryIntegrityTag`]
15//! - [`SpinBit`]
16//! - [`KeyPhase`]
17//!
18//! And the following packet headers:
19//!
20//! - [`InitialPacket`]
21//! - [`ZeroRttPacket`]
22//! - [`HandshakePacket`]
23//! - [`RetryPacket`]
24//! - [`OneRttPacket`]
25//!
26//! [Section 17]: https://datatracker.ietf.org/doc/html/rfc9000#section-17
27
28use crate::{
29    Buf,
30    BufError::{self},
31    BufMut, BufResult, Codec, Cursor,
32    ietf::quic::{HeaderForm, Version},
33    ietf::quicv1::VariableLengthInteger,
34};
35
36/// A Fixed Bit of the Long Header Packet following [Section 17.2].
37///
38/// The bit is set to 1, unless the packet is a [Version Negotiation packet].
39///
40/// [Section 17.2]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.2
41/// [Version Negotiation packet]: crate::ietf::quic::VersionNegotiationPacket
42#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
43#[repr(u8)]
44pub enum FixedBit {
45    /// Indicating any packet.
46    One = 1,
47    /// Indicating Version Negotiation Packet.
48    VersionNegotiationPacket = 0,
49}
50
51impl Codec for FixedBit {
52    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
53        let current_byte = writer.peek_u8().unwrap_or(0x00);
54        let bit_mask = (*self as u8) << 6;
55        let updated_byte = (current_byte & !0x40) | bit_mask;
56        writer.poke_u8(updated_byte)
57    }
58
59    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
60        let byte = reader.peek_u8()?;
61        match (byte & 0x40) >> 6 {
62            0 => Ok(Self::VersionNegotiationPacket),
63            _ => Ok(Self::One),
64        }
65    }
66}
67
68/// A Long Header Type following [Section 17.2, Table 5].
69///
70/// Indicating type of the Long Header Packet.
71///
72/// [Section 17.2, Table 5]: https://datatracker.ietf.org/doc/html/rfc9000#table-5
73#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
74#[repr(u8)]
75pub enum LongHeaderPacketType {
76    /// [Initial Packet](InitialPacket) type.
77    Initial = 0x00,
78
79    /// [0-RTT Packet](ZeroRttPacket) type.
80    ZeroRtt = 0x01,
81
82    /// [Handshake Packet](HandshakePacket) type.
83    Handshake = 0x02,
84
85    /// [Retry Packet](RetryPacket) type.
86    Retry = 0x03,
87}
88
89impl Codec for LongHeaderPacketType {
90    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
91        let current_byte = writer.peek_u8().unwrap_or(0x00);
92        let bit_mask = (*self as u8) << 4;
93        let updated_byte = (current_byte & !0x30) | bit_mask;
94        writer.poke_u8(updated_byte)
95    }
96
97    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
98        let value = (reader.peek_u8()? & 0x30) >> 4;
99        match value {
100            0 => Ok(Self::Initial),
101            1 => Ok(Self::ZeroRtt),
102            2 => Ok(Self::Handshake),
103            _ => Ok(Self::Retry),
104        }
105    }
106}
107
108/// A connection ID, specified for QUIC version 1.
109///
110/// Helper structure to contain the `Connection ID Length` and `Connection ID` fields.
111#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
112pub struct ConnectionId {
113    /// The length of the connection ID, must not exceed 20 in QUIC version 1.
114    length: u8,
115    /// The connection ID bytes.
116    bytes: [u8; Self::MAXIMAL_LENGTH],
117}
118
119impl ConnectionId {
120    ///
121    pub const MAXIMAL_LENGTH: usize = 20;
122
123    ///
124    pub fn new(connection_id: &[u8]) -> Option<Self> {
125        let length = connection_id.length();
126        if length > Self::MAXIMAL_LENGTH as usize {
127            return None;
128        }
129        let mut cid = [0u8; Self::MAXIMAL_LENGTH];
130        cid[..length].copy_from_slice(connection_id);
131        let length = length as u8;
132        Some(Self { length, bytes: cid })
133    }
134
135    ///
136    pub fn into_inner(self) -> (u8, [u8; Self::MAXIMAL_LENGTH]) {
137        (self.length, self.bytes)
138    }
139
140    ///
141    pub fn length(self) -> u8 {
142        self.length
143    }
144
145    ///
146    pub fn bytes(self) -> [u8; Self::MAXIMAL_LENGTH] {
147        self.bytes
148    }
149}
150
151impl Codec for ConnectionId {
152    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
153        let (cil, ci) = self.into_inner();
154        cil.encode(writer, ())?;
155        writer.write_slice(&ci[..cil as usize])
156    }
157
158    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
159        let ci = &mut [0u8; Self::MAXIMAL_LENGTH];
160        let cil = u8::decode(reader, ())?;
161        reader.read_into(&mut ci[..cil as usize])?;
162        Ok(Self::new(&ci[..cil as usize]).ok_or(BufError::UnexpectedValue)?)
163    }
164}
165
166impl Codec<u8> for ConnectionId {
167    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: u8) -> BufResult<()> {
168        let (cil, ci) = self.into_inner();
169        writer.write_slice(&ci[..cil as usize])
170    }
171
172    fn decode<R: Buf>(reader: &mut Cursor<R>, cil: u8) -> BufResult<Self> {
173        let ci = &mut [0u8; Self::MAXIMAL_LENGTH];
174        reader.read_into(&mut ci[..cil as usize])?;
175        Ok(Self::new(&ci[..cil as usize]).ok_or(BufError::UnexpectedValue)?)
176    }
177}
178
179/// A Packet Number Length.
180///
181/// > description
182///
183/// Defined in [IETF RFC 9000, Section 17.2](https://datatracker.ietf.org/doc/html/rfc9000#section-17.2).
184#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
185pub struct PacketNumberLength(pub u8);
186
187impl PacketNumberLength {
188    /// Выбирает минимальную длину, достаточную для кодирования данного номера пакета.
189    pub fn from_packet_number(packet_number: PacketNumber) -> BufResult<Self> {
190        // Предполагается, что VariableLengthInteger имеет поле .0 типа u64
191        let pn = packet_number.0.0;
192
193        if pn <= u8::MAX as u64 {
194            Ok(Self(0)) // 1 byte
195        } else if pn <= u16::MAX as u64 {
196            Ok(Self(1)) // 2 bytes
197        } else if pn <= 0xFFFFFF {
198            Ok(Self(2)) // 3 bytes
199        } else {
200            Ok(Self(3)) // 4 bytes
201        }
202    }
203
204    /// Возвращает фактическое количество байт, занимаемое номером пакета (1..=4).
205    pub fn byte_length(&self) -> u8 {
206        self.0 + 1
207    }
208}
209
210impl Codec for PacketNumberLength {
211    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
212        let current_byte = writer.peek_u8().unwrap_or(0x00);
213        let bit_mask = self.0 & 0x03;
214        let updated_byte = (current_byte & !0x03) | bit_mask;
215
216        writer.write_u8(updated_byte)
217    }
218
219    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
220        Ok(Self(reader.read_u8()? & 0x03))
221    }
222}
223
224/// A Packet Number.
225///
226/// > description
227///
228/// Defined in [IETF RFC 9000, Section 17.2](https://datatracker.ietf.org/doc/html/rfc9000#section-17.2).
229#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
230pub struct PacketNumber(pub VariableLengthInteger);
231impl PacketNumber {
232    ///
233    pub fn new(last_sent: PacketNumber) -> Self {
234        let mut last_sent = last_sent;
235        last_sent.0.0 += 1;
236        Self(last_sent.0)
237    }
238
239    ///
240    pub fn length(&self) -> BufResult<PacketNumberLength> {
241        PacketNumberLength::from_packet_number(*self)
242    }
243}
244impl Codec<PacketNumberLength> for PacketNumber {
245    fn encode<W: BufMut>(
246        &self,
247        writer: &mut Cursor<W>,
248        length: PacketNumberLength,
249    ) -> BufResult<()> {
250        let pn = self.0.0;
251
252        match length.0 {
253            0 => writer.write_u8(pn as u8),
254            1 => writer.write_u16_be(pn as u16), // Big-endian согласно RFC
255            2 => {
256                // 3 bytes: записываем по одному байту в big-endian порядке
257                writer.write_u8((pn >> 16) as u8)?;
258                writer.write_u8((pn >> 8) as u8)?;
259                writer.write_u8(pn as u8)
260            }
261            3 => writer.write_u32_be(pn as u32),
262            _ => Err(BufError::UnexpectedValue),
263        }
264    }
265
266    fn decode<R: Buf>(reader: &mut Cursor<R>, length: PacketNumberLength) -> BufResult<Self> {
267        let pn = match length.0 {
268            0 => reader.read_u8()? as u64,
269            1 => reader.read_u16_be()? as u64,
270            2 => {
271                // Читаем 3 байта и собираем в u64 в big-endian порядке
272                let b1 = reader.read_u8()? as u64;
273                let b2 = reader.read_u8()? as u64;
274                let b3 = reader.read_u8()? as u64;
275                (b1 << 16) | (b2 << 8) | b3
276            }
277            3 => reader.read_u32_be()? as u64,
278            _ => return Err(BufError::UnexpectedValue),
279        };
280
281        Ok(Self(VariableLengthInteger(pn)))
282    }
283}
284
285/// A length of the [PacketNumber] and Payload fields in bytes following [Section 17.2].
286///
287/// > description
288///
289/// Defined in [Section 17.2](https://datatracker.ietf.org/doc/html/rfc9000#section-17.2).
290#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
291pub struct Length(pub VariableLengthInteger);
292impl Length {
293    ///
294    pub fn calculate(
295        packet_payload_length: usize,
296        packet_number_length: PacketNumberLength,
297    ) -> BufResult<Self> {
298        Ok(Self(VariableLengthInteger::new(
299            packet_payload_length as u64 + packet_number_length.0 as u64,
300        )?))
301    }
302}
303
304impl Codec for Length {
305    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
306        self.0.encode(writer, ())
307    }
308
309    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
310        Ok(Self(VariableLengthInteger::decode(reader, ())?))
311    }
312}
313
314/// A Token.
315///
316/// > description
317#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
318pub struct RetryToken(pub Vec<u8>);
319
320impl Codec for RetryToken {
321    ///
322    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
323        self.0.encode(writer, ())
324    }
325
326    ///
327    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
328        let remaining = reader.remaining();
329        if remaining < 16 {
330            return Err(BufError::OutOfBounds);
331        }
332        let length = remaining - 16;
333        Ok(Self(Vec::decode(reader, length)?))
334    }
335}
336
337impl Codec<VariableLengthInteger> for RetryToken {
338    ///
339    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: VariableLengthInteger) -> BufResult<()> {
340        self.0.encode(writer, ())
341    }
342
343    ///
344    fn decode<R: Buf>(reader: &mut Cursor<R>, length: VariableLengthInteger) -> BufResult<Self> {
345        Ok(Self(Vec::decode(reader, length.0 as usize)?))
346    }
347}
348
349/// A Retry Integrity Tag.
350#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
351pub struct RetryIntegrityTag(pub [u8; 16]);
352
353impl Codec for RetryIntegrityTag {
354    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
355        writer.write_array(&self.0)
356    }
357
358    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
359        Ok(Self(reader.read_array::<16>()?))
360    }
361}
362
363/// A Spin Bit of the [1-RTT packet].
364///
365/// > description
366///
367/// [1-RTT packet]: OneRttPacket
368#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
369#[repr(u8)]
370pub enum SpinBit {
371    ///
372    Zero = 0,
373    ///
374    One = 1,
375}
376
377impl SpinBit {
378    ///
379    pub fn spin(&mut self) {
380        *self = match self {
381            SpinBit::Zero => SpinBit::One,
382            SpinBit::One => SpinBit::Zero,
383        }
384    }
385}
386
387impl Codec for SpinBit {
388    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
389        let current_byte = writer.peek_u8().unwrap_or(0x00);
390        let bit_mask = (*self as u8) << 5;
391        let updated_byte = (current_byte & !0b100000) | bit_mask;
392        writer.poke_u8(updated_byte)
393    }
394
395    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
396        let value = reader.peek_u8()? & 0b100000;
397        match value {
398            0 => Ok(Self::Zero),
399            _ => Ok(Self::One),
400        }
401    }
402}
403
404/// A Key Phase of the [1-RTT packet].
405///
406/// > description
407///
408/// [1-RTT packet]: OneRttPacket
409#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
410#[repr(u8)]
411pub enum KeyPhase {
412    /// .
413    Zero = 0,
414    /// .
415    One = 1,
416}
417
418impl Codec for KeyPhase {
419    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
420        let current_byte = writer.peek_u8().unwrap_or(0x00);
421        let bit_mask = (*self as u8) << 2;
422        let updated_byte = (current_byte & !0b100) | bit_mask;
423        writer.poke_u8(updated_byte)
424    }
425
426    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
427        let value = reader.peek_u8()? & 0b100;
428        match value {
429            0 => Ok(Self::Zero),
430            _ => Ok(Self::One),
431        }
432    }
433}
434
435/// An Initial Packet following [Section 17.2.2].
436///
437/// Carries the first [CRYPTO frames] from client and [ACK frames] in either direction.
438///
439/// [CRYPTO frames]: crate::ietf::quicv1::CryptoFrame
440/// [ACK frames]: crate::ietf::quicv1::AckFrame
441/// [Section 17.2.2]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.2.2
442#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
443pub struct InitialPacket {
444    /// The version.
445    pub version: Version,
446    /// The destination connection ID.
447    pub destination_connection_id: ConnectionId,
448    /// The source connection ID.
449    pub source_connection_id: ConnectionId,
450    /// The token received from the the server [Retry packet](RetryPacket).
451    pub token: RetryToken,
452    /// The Packet Number.
453    pub packet_number: PacketNumber,
454    /// The Packet Payload.
455    pub packet_payload: Vec<u8>,
456}
457
458impl InitialPacket {
459    /// The header form.
460    pub const HEADER_FORM: HeaderForm = HeaderForm::LongHeader;
461    /// The fixed bit.
462    pub const FIXED_BIT: FixedBit = FixedBit::One;
463    /// The long packet type.
464    pub const LONG_PACKET_TYPE: LongHeaderPacketType = LongHeaderPacketType::Initial;
465}
466
467impl Codec for InitialPacket {
468    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
469        Self::HEADER_FORM.encode(writer, ())?;
470        Self::FIXED_BIT.encode(writer, ())?;
471        Self::LONG_PACKET_TYPE.encode(writer, ())?;
472        let packet_number_length = self.packet_number.length()?;
473        packet_number_length.encode(writer, ())?;
474        self.version.encode(writer, ())?;
475        self.destination_connection_id.encode(writer, ())?;
476        self.source_connection_id.encode(writer, ())?;
477        VariableLengthInteger::new(self.token.0.len() as u64)?.encode(writer, ())?;
478        self.token.0.encode(writer, ())?;
479        Length::calculate(self.packet_payload.len(), packet_number_length)?.encode(writer, ())?;
480        self.packet_number.encode(writer, packet_number_length)?;
481        self.packet_payload.encode(writer, ())
482    }
483
484    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
485        if HeaderForm::decode(reader, ())? != Self::HEADER_FORM {
486            return Err(BufError::UnexpectedValue);
487        }
488        if FixedBit::decode(reader, ())? != Self::FIXED_BIT {
489            return Err(BufError::UnexpectedValue);
490        }
491        if LongHeaderPacketType::decode(reader, ())? != Self::LONG_PACKET_TYPE {
492            return Err(BufError::UnexpectedValue);
493        }
494        let packet_number_length = PacketNumberLength::decode(reader, ())?;
495        let version = Version::decode(reader, ())?;
496        let destination_connection_id = ConnectionId::decode(reader, ())?;
497        let source_connection_id = ConnectionId::decode(reader, ())?;
498        let token_length = VariableLengthInteger::decode(reader, ())?;
499        let token_bytes = &mut [0u8; 16];
500        reader.read_into(&mut token_bytes[..token_length.0 as usize])?;
501        let token = RetryToken((&token_bytes[..token_length.0 as usize]).to_vec());
502        let _length = VariableLengthInteger::decode(reader, ())?;
503        let packet_number = PacketNumber::decode(reader, packet_number_length)?;
504        let packet_payload = Vec::decode(reader, ())?;
505
506        Ok(Self {
507            version,
508            destination_connection_id,
509            source_connection_id,
510            token,
511            packet_number,
512            packet_payload,
513        })
514    }
515}
516
517/// A 0-RTT Packet following [Section 17.2.3].
518///
519/// Carries early data from the client to the server prior to handshake completion.
520///
521/// [Section 17.2.3]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.2.3
522#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
523pub struct ZeroRttPacket {
524    /// The version.
525    pub version: Version,
526    /// The destination connection ID.
527    pub destination_connection_id: ConnectionId,
528    /// The source connection ID.
529    pub source_connection_id: ConnectionId,
530    /// The packet number.
531    pub packet_number: PacketNumber,
532    /// The packet payload.
533    pub packet_payload: Vec<u8>,
534}
535
536impl ZeroRttPacket {
537    /// The header form.
538    pub const HEADER_FORM: HeaderForm = HeaderForm::LongHeader;
539    /// The fixed bit.
540    pub const FIXED_BIT: FixedBit = FixedBit::One;
541    /// The long packet type.
542    pub const LONG_PACKET_TYPE: LongHeaderPacketType = LongHeaderPacketType::ZeroRtt;
543}
544
545impl Codec for ZeroRttPacket {
546    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
547        Self::HEADER_FORM.encode(writer, ())?;
548        Self::FIXED_BIT.encode(writer, ())?;
549        Self::LONG_PACKET_TYPE.encode(writer, ())?;
550        let packet_number_length = self.packet_number.length()?;
551        packet_number_length.encode(writer, ())?;
552        self.version.encode(writer, ())?;
553        self.destination_connection_id.encode(writer, ())?;
554        self.source_connection_id.encode(writer, ())?;
555        Length::calculate(self.packet_payload.len(), packet_number_length)?.encode(writer, ())?;
556        self.packet_number.encode(writer, packet_number_length)?;
557        self.packet_payload.encode(writer, ())
558    }
559
560    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
561        if HeaderForm::decode(reader, ())? != Self::HEADER_FORM {
562            return Err(BufError::UnexpectedValue);
563        }
564        if FixedBit::decode(reader, ())? != Self::FIXED_BIT {
565            return Err(BufError::UnexpectedValue);
566        }
567        if LongHeaderPacketType::decode(reader, ())? != Self::LONG_PACKET_TYPE {
568            return Err(BufError::UnexpectedValue);
569        }
570        let packet_number_length = PacketNumberLength::decode(reader, ())?;
571        let version = Version::decode(reader, ())?;
572        let destination_connection_id = ConnectionId::decode(reader, ())?;
573        let source_connection_id = ConnectionId::decode(reader, ())?;
574        let _length = VariableLengthInteger::decode(reader, ())?;
575        let packet_number = PacketNumber::decode(reader, packet_number_length)?;
576        let packet_payload = Vec::decode(reader, ())?;
577
578        Ok(Self {
579            version,
580            destination_connection_id,
581            source_connection_id,
582            packet_number,
583            packet_payload,
584        })
585    }
586}
587
588/// A Handshake Packet following [Section 17.2.4].
589///
590/// Carries cryptographic handshake messages and acknowledgments from the server and client.
591///
592/// [Section 17.2.4]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.2.4
593#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
594pub struct HandshakePacket {
595    /// The version.
596    pub version: Version,
597    /// The destination connection ID.
598    pub destination_connection_id: ConnectionId,
599    /// The source connection ID.
600    pub source_connection_id: ConnectionId,
601    /// The packet number.
602    pub packet_number: PacketNumber,
603    /// The packet payload.
604    pub packet_payload: Vec<u8>,
605}
606
607impl HandshakePacket {
608    /// The header form.
609    pub const HEADER_FORM: HeaderForm = HeaderForm::LongHeader;
610    /// The fixed bit.
611    pub const FIXED_BIT: FixedBit = FixedBit::One;
612    /// The long packet type.
613    pub const LONG_PACKET_TYPE: LongHeaderPacketType = LongHeaderPacketType::Handshake;
614}
615
616impl Codec for HandshakePacket {
617    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
618        Self::HEADER_FORM.encode(writer, ())?;
619        Self::FIXED_BIT.encode(writer, ())?;
620        Self::LONG_PACKET_TYPE.encode(writer, ())?;
621        let packet_number_length = self.packet_number.length()?;
622        packet_number_length.encode(writer, ())?;
623        self.version.encode(writer, ())?;
624        self.destination_connection_id.encode(writer, ())?;
625        self.source_connection_id.encode(writer, ())?;
626        Length::calculate(self.packet_payload.len(), packet_number_length)?.encode(writer, ())?;
627        self.packet_number.encode(writer, packet_number_length)?;
628        self.packet_payload.encode(writer, ())
629    }
630
631    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
632        if HeaderForm::decode(reader, ())? != Self::HEADER_FORM {
633            return Err(BufError::UnexpectedValue);
634        }
635        if FixedBit::decode(reader, ())? != Self::FIXED_BIT {
636            return Err(BufError::UnexpectedValue);
637        }
638        if LongHeaderPacketType::decode(reader, ())? != Self::LONG_PACKET_TYPE {
639            return Err(BufError::UnexpectedValue);
640        }
641        let packet_number_length = PacketNumberLength::decode(reader, ())?;
642        let version = Version::decode(reader, ())?;
643        let destination_connection_id = ConnectionId::decode(reader, ())?;
644        let source_connection_id = ConnectionId::decode(reader, ())?;
645        let _length = VariableLengthInteger::decode(reader, ())?;
646        let packet_number = PacketNumber::decode(reader, packet_number_length)?;
647        let packet_payload = Vec::decode(reader, ())?;
648
649        Ok(Self {
650            version,
651            destination_connection_id,
652            source_connection_id,
653            packet_number,
654            packet_payload,
655        })
656    }
657}
658
659/// A Retry Packet following [Section 17.2.5].
660///
661/// Carries an [address validation token] created by the server to the client.
662///
663/// [Section 17.2.5]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.2.5
664/// [address validation token]: RetryToken
665#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
666pub struct RetryPacket {
667    /// The version.
668    pub version: Version,
669    /// The destination connection ID.
670    pub destination_connection_id: ConnectionId,
671    /// The source connection ID.
672    pub source_connection_id: ConnectionId,
673    /// The retry token.
674    pub retry_token: RetryToken,
675    /// The retry integrity tag.
676    pub retry_integrity_tag: RetryIntegrityTag,
677}
678
679impl RetryPacket {
680    /// The header form.
681    pub const HEADER_FORM: HeaderForm = HeaderForm::LongHeader;
682    /// The fixed bit.
683    pub const FIXED_BIT: FixedBit = FixedBit::One;
684    /// The long packet type.
685    pub const LONG_PACKET_TYPE: LongHeaderPacketType = LongHeaderPacketType::Retry;
686}
687
688impl Codec for RetryPacket {
689    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, _: ()) -> BufResult<()> {
690        Self::HEADER_FORM.encode(writer, ())?;
691        Self::FIXED_BIT.encode(writer, ())?;
692        Self::LONG_PACKET_TYPE.encode(writer, ())?;
693        writer.advance(1)?;
694        self.version.encode(writer, ())?;
695        self.destination_connection_id.encode(writer, ())?;
696        self.source_connection_id.encode(writer, ())?;
697        self.retry_token.encode(writer, ())?;
698        self.retry_integrity_tag.encode(writer, ())
699    }
700
701    fn decode<R: Buf>(reader: &mut Cursor<R>, _: ()) -> BufResult<Self> {
702        if HeaderForm::decode(reader, ())? != Self::HEADER_FORM {
703            return Err(BufError::UnexpectedValue);
704        }
705        if FixedBit::decode(reader, ())? != Self::FIXED_BIT {
706            return Err(BufError::UnexpectedValue);
707        }
708        if LongHeaderPacketType::decode(reader, ())? != Self::LONG_PACKET_TYPE {
709            return Err(BufError::UnexpectedValue);
710        }
711        reader.advance(1)?;
712        let version = Version::decode(reader, ())?;
713        let destination_connection_id = ConnectionId::decode(reader, ())?;
714        let source_connection_id = ConnectionId::decode(reader, ())?;
715        let mut left = Vec::decode(reader, ())?;
716        let length = left.len();
717        let (retry_token, _retry_integrity_tag) = left.split_at_mut_checked(length - 16).unwrap();
718        let retry_token = RetryToken(retry_token.to_vec());
719        let retry_integrity_tag = match _retry_integrity_tag.try_into() {
720            Ok(x) => x,
721            Err(_) => return Err(BufError::UnexpectedValue),
722        };
723        let retry_integrity_tag = RetryIntegrityTag(retry_integrity_tag);
724        Ok(Self {
725            version,
726            destination_connection_id,
727            source_connection_id,
728            retry_token,
729            retry_integrity_tag,
730        })
731    }
732}
733
734/// A 1-RTT Packet by [Section 17.3.1].
735///
736/// Used after the version and 1-RTT keys are negotiated.
737///
738/// [Section 17.3.1]: https://datatracker.ietf.org/doc/html/rfc9000#section-17.3.1
739#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
740pub struct OneRttPacket {
741    /// The Spin Bit.
742    pub spin_bit: SpinBit,
743    /// The Key Phase.
744    pub key_phase: KeyPhase,
745    /// The negotiated destination connection ID.
746    pub destination_connection_id: ConnectionId,
747    /// The number of this packet.
748    pub packet_number: PacketNumber,
749    /// The Packet Payload.
750    pub packet_payload: Vec<u8>,
751}
752
753impl OneRttPacket {
754    /// The header form.
755    pub const HEADER_FORM: HeaderForm = HeaderForm::ShortHeader;
756    /// The fixed bit.
757    pub const FIXED_BIT: FixedBit = FixedBit::One;
758}
759
760impl Codec<u8> for OneRttPacket {
761    fn encode<W: BufMut>(&self, writer: &mut Cursor<W>, dcid_length: u8) -> BufResult<()> {
762        Self::HEADER_FORM.encode(writer, ())?;
763        Self::FIXED_BIT.encode(writer, ())?;
764        self.spin_bit.encode(writer, ())?;
765        self.key_phase.encode(writer, ())?;
766        let packet_number_length = self.packet_number.length()?;
767        packet_number_length.encode(writer, ())?;
768        self.destination_connection_id.encode(writer, dcid_length)?;
769        self.packet_number.encode(writer, packet_number_length)?;
770        self.packet_payload.encode(writer, ())
771    }
772
773    fn decode<R: Buf>(reader: &mut Cursor<R>, dcid_length: u8) -> BufResult<Self> {
774        if HeaderForm::decode(reader, ())? != Self::HEADER_FORM {
775            return Err(BufError::UnexpectedValue);
776        }
777        if FixedBit::decode(reader, ())? != Self::FIXED_BIT {
778            return Err(BufError::UnexpectedValue);
779        }
780        let spin_bit = SpinBit::decode(reader, ())?;
781        let key_phase = KeyPhase::decode(reader, ())?;
782        let packet_number_length = PacketNumberLength::decode(reader, ())?;
783        let destination_connection_id = ConnectionId::decode(reader, dcid_length)?;
784        let packet_number = PacketNumber::decode(reader, packet_number_length)?;
785        let packet_payload = Vec::decode(reader, ())?;
786
787        Ok(Self {
788            spin_bit,
789            key_phase,
790            destination_connection_id,
791            packet_number,
792            packet_payload,
793        })
794    }
795}
796
797#[cfg(test)]
798mod tests {
799    use core::fmt::Debug;
800
801    use crate::{
802        Codec, Cursor,
803        ietf::quic::Version,
804        ietf::quicv1::{
805            ConnectionId, FixedBit, HandshakePacket, InitialPacket, KeyPhase, LongHeaderPacketType,
806            OneRttPacket, PacketNumber, PacketNumberLength, RetryIntegrityTag, RetryPacket,
807            RetryToken, SpinBit, VariableLengthInteger, ZeroRttPacket,
808        },
809    };
810
811    fn codec_roundtrip<T: Codec<C> + Debug + Eq, C: Copy>(
812        etalon_struct: T,
813        etalon_bytes: &[u8],
814        context: C,
815    ) {
816        let mut encoded_bytes = vec![];
817        {
818            let writer = &mut Cursor::new(&mut encoded_bytes);
819            etalon_struct.encode(writer, context).unwrap();
820        }
821        assert_eq!(etalon_bytes, &encoded_bytes);
822
823        let decoded_struct = {
824            let reader = &mut Cursor::new(&mut encoded_bytes);
825            T::decode(reader, context).unwrap()
826        };
827        assert_eq!(etalon_struct, decoded_struct);
828
829        encoded_bytes.fill(0x00);
830        {
831            let writer = &mut Cursor::new(&mut encoded_bytes);
832            decoded_struct.encode(writer, context).unwrap();
833        }
834        assert_eq!(etalon_bytes, &encoded_bytes);
835    }
836
837    #[test]
838    fn fixed_bit() {
839        let etalon_bytes = &[0b01000000];
840        let etalon_struct = FixedBit::One;
841        codec_roundtrip(etalon_struct, etalon_bytes, ());
842
843        let etalon_bytes = &[0b00000000];
844        let etalon_struct = FixedBit::VersionNegotiationPacket;
845        codec_roundtrip(etalon_struct, etalon_bytes, ());
846    }
847
848    #[test]
849    fn long_header_packet_type() {
850        let etalon_bytes = &[0b00000000];
851        let etalon_struct = LongHeaderPacketType::Initial;
852        codec_roundtrip(etalon_struct, etalon_bytes, ());
853
854        let etalon_bytes = &[0b00010000];
855        let etalon_struct = LongHeaderPacketType::ZeroRtt;
856        codec_roundtrip(etalon_struct, etalon_bytes, ());
857
858        let etalon_bytes = &[0b00100000];
859        let etalon_struct = LongHeaderPacketType::Handshake;
860        codec_roundtrip(etalon_struct, etalon_bytes, ());
861
862        let etalon_bytes = &[0b00110000];
863        let etalon_struct = LongHeaderPacketType::Retry;
864        codec_roundtrip(etalon_struct, etalon_bytes, ());
865    }
866
867    #[test]
868    fn connection_id() {
869        assert_eq!(ConnectionId::new(&[0x08; 21]), None);
870
871        let etalon_bytes = &[0x08; 9];
872        let etalon_struct = ConnectionId::new(&[0x08; 8]).unwrap();
873        codec_roundtrip(etalon_struct, etalon_bytes, ());
874
875        let etalon_bytes = &[0x010; 17];
876        let etalon_struct = ConnectionId::new(&[0x010; 16]).unwrap();
877        codec_roundtrip(etalon_struct, etalon_bytes, ());
878
879        let etalon_bytes = &[0x014; 21];
880        let etalon_struct = ConnectionId::new(&[0x014; 20]).unwrap();
881        codec_roundtrip(etalon_struct, etalon_bytes, ());
882    }
883
884    #[test]
885    fn packet_number_length() {
886        let etalon_bytes = &[0x00];
887        let etalon_struct = PacketNumberLength::from_packet_number(PacketNumber(
888            VariableLengthInteger::new(0).unwrap(),
889        ))
890        .unwrap();
891        codec_roundtrip(etalon_struct, etalon_bytes, ());
892    }
893
894    #[test]
895    fn packet_number() {
896        let etalon_bytes = &[0x00];
897        let etalon_struct = PacketNumber(VariableLengthInteger::new(0).unwrap());
898        codec_roundtrip(etalon_struct, etalon_bytes, etalon_struct.length().unwrap());
899    }
900
901    #[test]
902    fn token() {
903        let etalon_bytes = &[
904            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
905            0x00, 0x00, // token
906            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
907            0x00, 0x00, // retry integrity tag
908        ];
909        let etalon_struct = RetryToken(vec![0x00; 16]);
910        {
911            let context = ();
912            let mut encoded_bytes = vec![];
913            {
914                let writer = &mut Cursor::new(&mut encoded_bytes);
915                etalon_struct.encode(writer, context).unwrap();
916            }
917            encoded_bytes.extend_from_slice(&[0x00; 16]);
918            assert_eq!(&etalon_bytes.to_vec(), &encoded_bytes);
919
920            let decoded_struct = {
921                let reader = &mut Cursor::new(&mut encoded_bytes);
922                RetryToken::decode(reader, context).unwrap()
923            };
924            assert_eq!(etalon_struct, decoded_struct);
925
926            encoded_bytes.fill(0x00);
927            {
928                let writer = &mut Cursor::new(&mut encoded_bytes);
929                decoded_struct.encode(writer, context).unwrap();
930            }
931            assert_eq!(&etalon_bytes.to_vec(), &encoded_bytes);
932        };
933
934        let etalon_bytes = &[
935            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
936            0x00, 0x00,
937        ];
938        let etalon_struct = RetryToken(vec![0x00; 16]);
939        codec_roundtrip(
940            etalon_struct,
941            etalon_bytes,
942            VariableLengthInteger::new_const(16),
943        );
944    }
945
946    #[test]
947    fn retry_integrity_tag() {
948        let etalon_bytes = &[0; 16];
949        let etalon_struct = RetryIntegrityTag([0; 16]);
950
951        codec_roundtrip(etalon_struct, etalon_bytes, ());
952    }
953
954    #[test]
955    fn spin_bit() {
956        let etalon_bytes = &[0b00000000];
957        let etalon_struct = SpinBit::Zero;
958        codec_roundtrip(etalon_struct, etalon_bytes, ());
959
960        let etalon_bytes = &[0b00100000];
961        let etalon_struct = SpinBit::One;
962        codec_roundtrip(etalon_struct, etalon_bytes, ());
963    }
964
965    #[test]
966    fn key_phase() {
967        let etalon_bytes = &[0b00000000];
968        let etalon_struct = KeyPhase::Zero;
969        codec_roundtrip(etalon_struct, etalon_bytes, ());
970
971        let etalon_bytes = &[0b100];
972        let etalon_struct = KeyPhase::One;
973        codec_roundtrip(etalon_struct, etalon_bytes, ());
974    }
975
976    #[test]
977    fn initial_packet() {
978        let etalon_struct = InitialPacket {
979            version: Version(1),
980            destination_connection_id: ConnectionId::new(&[0x82; 8]).unwrap(),
981            source_connection_id: ConnectionId::new(&[0x41; 8]).unwrap(),
982            token: RetryToken(vec![0]),
983            packet_number: PacketNumber(VariableLengthInteger::new(0).unwrap()),
984            packet_payload: vec![],
985        };
986
987        // 0xC0 = Long Header, Initial packet type, packet number length = 1 byte.
988        // Length = 0x01, так как payload пустой и packet number занимает 1 байт.
989        let etalon_bytes: &[u8] = &[
990            0xC0, // Version = 1
991            0x00, 0x00, 0x00, 0x01, // Destination Connection ID Length + Value
992            0x08, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
993            // Source Connection ID Length + Value
994            0x08, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, // Token Length = 1
995            0x01, // Token
996            0x00, // Length = Packet Number length + Payload length = 1 + 0
997            0x00, // Packet Number
998            0x00,
999        ];
1000
1001        codec_roundtrip(etalon_struct, etalon_bytes, ());
1002    }
1003
1004    #[test]
1005    fn zero_rtt_packet() {
1006        let etalon_struct = ZeroRttPacket {
1007            version: Version(1),
1008            destination_connection_id: ConnectionId::new(&[0x82; 8]).unwrap(),
1009            source_connection_id: ConnectionId::new(&[0x41; 8]).unwrap(),
1010            packet_number: PacketNumber(VariableLengthInteger::new(0).unwrap()),
1011            packet_payload: vec![],
1012        };
1013
1014        // 0xD0 = Long Header, 0-RTT packet type, packet number length = 1 byte.
1015        let etalon_bytes: &[u8] = &[
1016            // First byte
1017            0xD0, // Version = 1
1018            0x00, 0x00, 0x00, 0x01, // Destination Connection ID Length + Value
1019            0x08, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
1020            // Source Connection ID Length + Value
1021            0x08, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
1022            // Length = Packet Number length + Payload length = 1 + 0
1023            0x00, // Packet Number
1024            0x00,
1025        ];
1026
1027        codec_roundtrip(etalon_struct, etalon_bytes, ());
1028    }
1029
1030    #[test]
1031    fn handshake_packet() {
1032        let etalon_struct = HandshakePacket {
1033            version: Version(1),
1034            destination_connection_id: ConnectionId::new(&[0x82; 8]).unwrap(),
1035            source_connection_id: ConnectionId::new(&[0x41; 8]).unwrap(),
1036            packet_number: PacketNumber(VariableLengthInteger::new(0).unwrap()),
1037            packet_payload: vec![],
1038        };
1039
1040        // 0xE0 = Long Header, Handshake packet type, packet number length = 1 byte.
1041        let etalon_bytes: &[u8] = &[
1042            // First byte
1043            0xE0, // Version = 1
1044            0x00, 0x00, 0x00, 0x01, // Destination Connection ID Length + Value
1045            0x08, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
1046            // Source Connection ID Length + Value
1047            0x08, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
1048            // Length = Packet Number length + Payload length = 1 + 0
1049            0x00, 0x00, // Packet Number
1050        ];
1051
1052        codec_roundtrip(etalon_struct, etalon_bytes, ());
1053    }
1054
1055    #[test]
1056    fn retry_packet() {
1057        let etalon_struct = RetryPacket {
1058            version: Version(1),
1059            destination_connection_id: ConnectionId::new(&[0x82; 8]).unwrap(),
1060            source_connection_id: ConnectionId::new(&[0x41; 8]).unwrap(),
1061            retry_token: RetryToken(vec![0]),
1062            retry_integrity_tag: RetryIntegrityTag([0x55; 16]),
1063        };
1064
1065        let etalon_bytes: &[u8] = &[
1066            // First byte
1067            0xF0, // Version = 1
1068            0x00, 0x00, 0x00, 0x01, // Destination Connection ID Length + Value
1069            0x08, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
1070            // Source Connection ID Length + Value
1071            0x08, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, // Retry Token
1072            0x00, // Retry Integrity Tag, 16 bytes
1073            0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1074            0x55, 0x55,
1075        ];
1076
1077        codec_roundtrip(etalon_struct, etalon_bytes, ());
1078    }
1079
1080    #[test]
1081    fn one_rtt_packet() {
1082        let etalon_struct = OneRttPacket {
1083            spin_bit: SpinBit::Zero,
1084            key_phase: KeyPhase::Zero,
1085            destination_connection_id: ConnectionId::new(&[0x82; 8]).unwrap(),
1086            packet_number: PacketNumber(VariableLengthInteger::new(0).unwrap()),
1087            packet_payload: vec![],
1088        };
1089
1090        let etalon_bytes: &[u8] = &[
1091            0b01000000, // First byte
1092            0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, // Destination Connection ID
1093            0x00, // Packet Number
1094        ];
1095
1096        codec_roundtrip(etalon_struct, etalon_bytes, 8);
1097    }
1098}