iroh_quinn_proto/
frame.rs

1use std::{
2    fmt::{self, Write},
3    mem,
4    net::{IpAddr, SocketAddr},
5    ops::{Range, RangeInclusive},
6};
7
8use bytes::{Buf, BufMut, Bytes};
9use tinyvec::TinyVec;
10
11use crate::{
12    Dir, MAX_CID_SIZE, RESET_TOKEN_SIZE, ResetToken, StreamId, TransportError, TransportErrorCode,
13    VarInt,
14    coding::{self, BufExt, BufMutExt, Decodable, Encodable, UnexpectedEnd},
15    connection::PathId,
16    range_set::ArrayRangeSet,
17    shared::{ConnectionId, EcnCodepoint},
18};
19
20#[cfg(feature = "arbitrary")]
21use arbitrary::Arbitrary;
22
23/// Generates the [`FrameType`] enum, and its associated conversions from and to u64
24macro_rules! frame_types {
25    // Process the unit variants.
26    (enum_defs: [$($enum_defs: tt)*] try_from_arms: [$($try_from_arms: tt)*] to_u64_arms:[$($to_u64_arms: tt)*] // accumulators
27     $variant: ident = $value: literal, // VariantName = value,
28     $($token: tt)*) => {
29        frame_types!{
30            enum_defs: [$($enum_defs)* $variant,]
31            try_from_arms: [$($try_from_arms)* $value => Self::$variant,]
32            to_u64_arms: [$($to_u64_arms)* FrameType::$variant => $value,]
33            $($token)*
34        }
35    };
36
37    // Process the tuple variants.
38    (enum_defs: [$($enum_defs: tt)*] try_from_arms: [$($try_from_arms: tt)*] to_u64_arms:[$($to_u64_arms: tt)*] // accumulators
39     $variant: ident($inner: ident), // VariantName(InnerType),
40     $($token: tt)*) => {
41        frame_types!{
42            enum_defs: [$($enum_defs)* $variant($inner),]
43            try_from_arms: [$($try_from_arms)* value if <$inner>::VALUES.contains(&value) => Self::$variant($inner(value as u8)),]
44            to_u64_arms: [$($to_u64_arms)* FrameType::$variant($inner(value)) => value as u64,]
45            $($token)*
46        }
47    };
48
49    // Final generation step.
50    (enum_defs: [$($enum_defs: tt)+] try_from_arms: [$($try_from_arms: tt)+] to_u64_arms: [$($to_u64_arms: tt)+]) => {
51        /// A QUIC frame type
52        #[derive(Copy, Clone, Eq, PartialEq, derive_more::Debug, derive_more::Display)]
53        #[display(rename_all = "SCREAMING_SNAKE_CASE")]
54        #[allow(missing_docs)]
55        pub enum FrameType {
56            $($enum_defs)*
57        }
58
59        pub struct InvalidFrameId(u64);
60
61        impl TryFrom<u64> for FrameType {
62            type Error = InvalidFrameId;
63            fn try_from(value: u64) -> Result<Self, Self::Error> {
64                Ok(match value {
65                    $($try_from_arms)*
66                    other => return Err(InvalidFrameId(other))
67                })
68            }
69        }
70
71        impl FrameType {
72            pub(crate) const fn to_u64(self) -> u64 {
73                match self {
74                    $($to_u64_arms)*
75                }
76            }
77        }
78    };
79}
80
81frame_types! {
82    enum_defs: []
83    try_from_arms: []
84    to_u64_arms: []
85    Padding = 0x00,
86    Ping = 0x01,
87    Ack = 0x02,
88    AckEcn = 0x03,
89    ResetStream = 0x04,
90    StopSending = 0x05,
91    Crypto = 0x06,
92    NewToken = 0x07,
93    // STREAM
94    Stream(StreamInfo),
95    MaxData = 0x10,
96    MaxStreamData = 0x11,
97    MaxStreamsBidi = 0x12,
98    MaxStreamsUni = 0x13,
99    DataBlocked = 0x14,
100    StreamDataBlocked = 0x15,
101    StreamsBlockedBidi = 0x16,
102    StreamsBlockedUni = 0x17,
103    NewConnectionId = 0x18,
104    RetireConnectionId = 0x19,
105    PathChallenge = 0x1a,
106    PathResponse = 0x1b,
107    ConnectionClose = 0x1c,
108    ApplicationClose = 0x1d,
109    HandshakeDone = 0x1e,
110    // ACK Frequency
111    AckFrequency = 0xaf,
112    ImmediateAck = 0x1f,
113    // DATAGRAM
114    Datagram(DatagramInfo),
115    // ADDRESS DISCOVERY REPORT
116    ObservedIpv4Addr = 0x9f81a6,
117    ObservedIpv6Addr = 0x9f81a7,
118    // Multipath
119    PathAck = 0x15228c00,
120    PathAckEcn = 0x15228c01,
121    PathAbandon = 0x15228c05,
122    PathStatusBackup = 0x15228c07,
123    PathStatusAvailable = 0x15228c08,
124    PathNewConnectionId = 0x15228c09,
125    PathRetireConnectionId = 0x15228c0a,
126    MaxPathId = 0x15228c0c,
127    PathsBlocked = 0x15228c0d,
128    PathCidsBlocked = 0x15228c0e,
129    // IROH'S NAT TRAVERSAL
130    AddIpv4Address = 0x3d7f90,
131    AddIpv6Address = 0x3d7f91,
132    ReachOutAtIpv4 = 0x3d7f92,
133    ReachOutAtIpv6 = 0x3d7f93,
134    RemoveAddress = 0x3d7f94,
135}
136
137impl FrameType {
138    /// The encoded size of this [`FrameType`].
139    const fn size(&self) -> usize {
140        VarInt(self.to_u64()).size()
141    }
142}
143
144impl Decodable for FrameType {
145    fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
146        Self::try_from(buf.get_var()?).map_err(|_| coding::UnexpectedEnd)
147    }
148}
149
150impl Encodable for FrameType {
151    fn encode<B: BufMut>(&self, buf: &mut B) {
152        buf.write_var(self.to_u64());
153    }
154}
155
156pub(crate) trait FrameStruct {
157    /// Smallest number of bytes this type of frame is guaranteed to fit within.
158    const SIZE_BOUND: usize;
159}
160
161/// The type used to refer to [`FrameType`]s in closing and transport errors.
162#[derive(Copy, Clone, Eq, PartialEq, derive_more::Debug, derive_more::Display)]
163pub enum MaybeFrame {
164    /// Not attributed to any particular [`FrameType`].
165    None,
166    /// Attributed to some frame type this implementation does not recognize.
167    #[display("UNKNOWN{:02x}", _0)]
168    #[debug("Unknown{:02x}", _0)]
169    Unknown(u64),
170    /// Attributed to a specific [`FrameType`], never [`FrameType::Padding`].
171    Known(FrameType),
172}
173
174impl MaybeFrame {
175    /// Encoded size of this [`MaybeFrame`].
176    const fn size(&self) -> usize {
177        match self {
178            Self::None => VarInt(0).size(),
179            Self::Unknown(other) => VarInt(*other).size(),
180            Self::Known(frame_type) => frame_type.size(),
181        }
182    }
183}
184
185impl Decodable for MaybeFrame {
186    fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
187        match FrameType::try_from(buf.get_var()?) {
188            Ok(FrameType::Padding) => Ok(Self::None),
189            Ok(other_frame) => Ok(Self::Known(other_frame)),
190            Err(InvalidFrameId(other)) => Ok(Self::Unknown(other)),
191        }
192    }
193}
194
195impl Encodable for MaybeFrame {
196    fn encode<B: BufMut>(&self, buf: &mut B) {
197        match self {
198            Self::None => buf.write(0u64),
199            Self::Unknown(frame_id) => buf.write(*frame_id),
200            Self::Known(frame_type) => buf.write(*frame_type),
201        }
202    }
203}
204
205#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)]
206#[display("STREAM")]
207pub struct StreamInfo(u8);
208
209impl StreamInfo {
210    const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x08, 0x0f);
211    fn fin(self) -> bool {
212        self.0 & 0x01 != 0
213    }
214    fn len(self) -> bool {
215        self.0 & 0x02 != 0
216    }
217    fn off(self) -> bool {
218        self.0 & 0x04 != 0
219    }
220}
221
222#[derive(Debug, Copy, Clone, Eq, PartialEq, derive_more::Display)]
223#[display("DATAGRAM")]
224pub struct DatagramInfo(u8);
225
226impl DatagramInfo {
227    const VALUES: RangeInclusive<u64> = RangeInclusive::new(0x30, 0x31);
228
229    fn len(self) -> bool {
230        self.0 & 0x01 != 0
231    }
232}
233
234#[derive(Debug)]
235pub(crate) enum Frame {
236    Padding,
237    Ping,
238    Ack(Ack),
239    PathAck(PathAck),
240    ResetStream(ResetStream),
241    StopSending(StopSending),
242    Crypto(Crypto),
243    NewToken(NewToken),
244    Stream(Stream),
245    MaxData(VarInt),
246    MaxStreamData { id: StreamId, offset: u64 },
247    MaxStreams { dir: Dir, count: u64 },
248    DataBlocked { offset: u64 },
249    StreamDataBlocked { id: StreamId, offset: u64 },
250    StreamsBlocked { dir: Dir, limit: u64 },
251    NewConnectionId(NewConnectionId),
252    RetireConnectionId(RetireConnectionId),
253    PathChallenge(PathChallenge),
254    PathResponse(PathResponse),
255    Close(Close),
256    Datagram(Datagram),
257    AckFrequency(AckFrequency),
258    ImmediateAck,
259    HandshakeDone,
260    ObservedAddr(ObservedAddr),
261    PathAbandon(PathAbandon),
262    PathStatusAvailable(PathStatusAvailable),
263    PathStatusBackup(PathStatusBackup),
264    MaxPathId(MaxPathId),
265    PathsBlocked(PathsBlocked),
266    PathCidsBlocked(PathCidsBlocked),
267    AddAddress(AddAddress),
268    ReachOut(ReachOut),
269    RemoveAddress(RemoveAddress),
270}
271
272impl fmt::Display for Frame {
273    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
274        // Eventually all our frames will support fmt::Display and be able to be used to log
275        // consistently. For now we fall back to fmt::Debug.
276        match self {
277            Self::Padding => write!(f, "PADDING"),
278            Self::Ping => write!(f, "PING"),
279            Self::PathChallenge(frame) => write!(f, "{frame}"),
280            Self::PathResponse(frame) => write!(f, "{frame}"),
281            Self::ImmediateAck => write!(f, "IMMEDIATE_ACK"),
282            Self::HandshakeDone => write!(f, "HANDSHAKE_DONE"),
283            _ => write!(f, "{self:?}"),
284        }
285    }
286}
287
288impl Frame {
289    pub(crate) fn ty(&self) -> FrameType {
290        use Frame::*;
291        match *self {
292            Padding => FrameType::Padding,
293            ResetStream(_) => FrameType::ResetStream,
294            Close(self::Close::Connection(_)) => FrameType::ConnectionClose,
295            Close(self::Close::Application(_)) => FrameType::ConnectionClose,
296            MaxData(_) => FrameType::MaxData,
297            MaxStreamData { .. } => FrameType::MaxStreamData,
298            MaxStreams { dir: Dir::Bi, .. } => FrameType::MaxStreamsBidi,
299            MaxStreams { dir: Dir::Uni, .. } => FrameType::MaxStreamsUni,
300            Ping => FrameType::Ping,
301            DataBlocked { .. } => FrameType::DataBlocked,
302            StreamDataBlocked { .. } => FrameType::StreamDataBlocked,
303            StreamsBlocked { dir: Dir::Bi, .. } => FrameType::StreamsBlockedBidi,
304            StreamsBlocked { dir: Dir::Uni, .. } => FrameType::StreamsBlockedUni,
305            StopSending { .. } => FrameType::StopSending,
306            RetireConnectionId { .. } => FrameType::RetireConnectionId,
307            Ack(_) => FrameType::Ack,
308            PathAck(_) => FrameType::PathAck,
309            Stream(ref x) => {
310                let mut ty = *StreamInfo::VALUES.start() as u8;
311                if x.fin {
312                    ty |= 0x01;
313                }
314                if x.offset != 0 {
315                    ty |= 0x04;
316                }
317                // TODO(@divma): move all this to getframetype for Stream
318                FrameType::Stream(StreamInfo(ty))
319            }
320            PathChallenge(_) => FrameType::PathChallenge,
321            PathResponse(_) => FrameType::PathResponse,
322            NewConnectionId(cid) => cid.get_type(),
323            Crypto(_) => FrameType::Crypto,
324            NewToken(_) => FrameType::NewToken,
325            Datagram(_) => FrameType::Datagram(DatagramInfo(*DatagramInfo::VALUES.start() as u8)),
326            AckFrequency(_) => FrameType::AckFrequency,
327            ImmediateAck => FrameType::ImmediateAck,
328            HandshakeDone => FrameType::HandshakeDone,
329            ObservedAddr(ref observed) => observed.get_type(),
330            PathAbandon(_) => FrameType::PathAbandon,
331            PathStatusAvailable(_) => FrameType::PathStatusAvailable,
332            PathStatusBackup(_) => FrameType::PathStatusBackup,
333            MaxPathId(_) => FrameType::MaxPathId,
334            PathsBlocked(_) => FrameType::PathsBlocked,
335            PathCidsBlocked(_) => FrameType::PathCidsBlocked,
336            AddAddress(ref frame) => frame.get_type(),
337            ReachOut(ref frame) => frame.get_type(),
338            RemoveAddress(_) => self::RemoveAddress::TYPE,
339        }
340    }
341
342    pub(crate) fn is_ack_eliciting(&self) -> bool {
343        !matches!(
344            *self,
345            Self::Ack(_) | Self::PathAck(_) | Self::Padding | Self::Close(_)
346        )
347    }
348
349    /// Returns `true` if this frame MUST be sent in 1-RTT space
350    pub(crate) fn is_1rtt(&self) -> bool {
351        // See also https://www.ietf.org/archive/id/draft-ietf-quic-multipath-17.html#section-4-1:
352        // > All frames defined in this document MUST only be sent in 1-RTT packets.
353        // > If an endpoint receives a multipath-specific frame in a different packet type, it MUST close the
354        // > connection with an error of type PROTOCOL_VIOLATION.
355
356        self.is_multipath_frame() || self.is_qad_frame()
357    }
358
359    fn is_qad_frame(&self) -> bool {
360        matches!(*self, Self::ObservedAddr(_))
361    }
362
363    fn is_multipath_frame(&self) -> bool {
364        matches!(
365            *self,
366            Self::PathAck(_)
367                | Self::PathAbandon(_)
368                | Self::PathStatusBackup(_)
369                | Self::PathStatusAvailable(_)
370                | Self::MaxPathId(_)
371                | Self::PathsBlocked(_)
372                | Self::PathCidsBlocked(_)
373                | Self::NewConnectionId(NewConnectionId {
374                    path_id: Some(_),
375                    ..
376                })
377                | Self::RetireConnectionId(RetireConnectionId {
378                    path_id: Some(_),
379                    ..
380                })
381        )
382    }
383}
384
385#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display)]
386#[display("PATH_CHALLENGE({_0:08x})")]
387pub(crate) struct PathChallenge(pub(crate) u64);
388
389impl PathChallenge {
390    pub(crate) const SIZE_BOUND: usize = 9;
391}
392impl Decodable for PathChallenge {
393    fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
394        Ok(Self(buf.get()?))
395    }
396}
397impl Encodable for PathChallenge {
398    fn encode<B: BufMut>(&self, buf: &mut B) {
399        buf.write(FrameType::PathChallenge);
400        buf.write(self.0);
401    }
402}
403
404#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, derive_more::Display)]
405#[display("PATH_RESPONSE({_0:08x})")]
406pub(crate) struct PathResponse(pub(crate) u64);
407
408impl PathResponse {
409    pub(crate) const SIZE_BOUND: usize = 9;
410}
411
412impl Decodable for PathResponse {
413    fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
414        Ok(Self(buf.get()?))
415    }
416}
417impl Encodable for PathResponse {
418    fn encode<B: BufMut>(&self, buf: &mut B) {
419        buf.write(FrameType::PathResponse);
420        buf.write(self.0);
421    }
422}
423
424#[derive(Debug, PartialEq, Eq)]
425pub(crate) struct RetireConnectionId {
426    pub(crate) path_id: Option<PathId>,
427    pub(crate) sequence: u64,
428}
429
430impl RetireConnectionId {
431    /// Maximum size of this frame when the frame type is [`FrameType::RetireConnectionId`]
432    pub(crate) const SIZE_BOUND: usize = {
433        let type_len = FrameType::RetireConnectionId.size();
434        let seq_max_len = 8usize;
435        type_len + seq_max_len
436    };
437
438    /// Maximum size of this frame when the frame type is [`FrameType::PathRetireConnectionId`]
439    pub(crate) const SIZE_BOUND_MULTIPATH: usize = {
440        let type_len = FrameType::PathRetireConnectionId.size();
441        let path_id_len = VarInt::from_u32(u32::MAX).size();
442        let seq_max_len = 8usize;
443        type_len + path_id_len + seq_max_len
444    };
445
446    /// Decode [`Self`] from the buffer, provided that the frame type has been verified (either
447    /// [`FrameType::PathRetireConnectionId`], or [`FrameType::RetireConnectionId`])
448    pub(crate) fn decode<R: Buf>(bytes: &mut R, read_path: bool) -> coding::Result<Self> {
449        Ok(Self {
450            path_id: if read_path { Some(bytes.get()?) } else { None },
451            sequence: bytes.get_var()?,
452        })
453    }
454
455    /// Get the [`FrameType`] for this [`RetireConnectionId`]
456    pub(crate) fn get_type(&self) -> FrameType {
457        if self.path_id.is_some() {
458            FrameType::PathRetireConnectionId
459        } else {
460            FrameType::RetireConnectionId
461        }
462    }
463
464    /// Returns the maximum encoded size on the wire
465    ///
466    /// `path_retire_cid` determines whether this frame is a multipath frame. This is a rough upper
467    /// estimate, does not squeeze every last byte out.
468    pub(crate) const fn size_bound(path_retire_cid: bool) -> usize {
469        match path_retire_cid {
470            true => Self::SIZE_BOUND_MULTIPATH,
471            false => Self::SIZE_BOUND,
472        }
473    }
474}
475
476impl Encodable for RetireConnectionId {
477    fn encode<W: BufMut>(&self, buf: &mut W) {
478        buf.write(self.get_type());
479        if let Some(id) = self.path_id {
480            buf.write(id);
481        }
482        buf.write_var(self.sequence);
483    }
484}
485
486#[derive(Clone, Debug)]
487pub enum Close {
488    Connection(ConnectionClose),
489    Application(ApplicationClose),
490}
491
492impl Close {
493    pub(crate) fn encoder(&self, max_len: usize) -> CloseEncoder<'_> {
494        CloseEncoder {
495            close: self,
496            max_len,
497        }
498    }
499
500    pub(crate) fn is_transport_layer(&self) -> bool {
501        matches!(*self, Self::Connection(_))
502    }
503}
504
505pub(crate) struct CloseEncoder<'a> {
506    close: &'a Close,
507    max_len: usize,
508}
509
510impl<'a> Encodable for CloseEncoder<'a> {
511    fn encode<W: BufMut>(&self, out: &mut W) {
512        match self.close {
513            Close::Connection(x) => x.encode(out, self.max_len),
514            Close::Application(x) => x.encode(out, self.max_len),
515        }
516    }
517}
518
519impl From<TransportError> for Close {
520    fn from(x: TransportError) -> Self {
521        Self::Connection(x.into())
522    }
523}
524impl From<ConnectionClose> for Close {
525    fn from(x: ConnectionClose) -> Self {
526        Self::Connection(x)
527    }
528}
529impl From<ApplicationClose> for Close {
530    fn from(x: ApplicationClose) -> Self {
531        Self::Application(x)
532    }
533}
534
535/// Reason given by the transport for closing the connection
536#[derive(Debug, Clone, PartialEq, Eq)]
537pub struct ConnectionClose {
538    /// Class of error as encoded in the specification
539    pub error_code: TransportErrorCode,
540    /// Type of frame that caused the close
541    pub frame_type: MaybeFrame,
542    /// Human-readable reason for the close
543    pub reason: Bytes,
544}
545
546impl fmt::Display for ConnectionClose {
547    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
548        self.error_code.fmt(f)?;
549        if !self.reason.as_ref().is_empty() {
550            f.write_str(": ")?;
551            f.write_str(&String::from_utf8_lossy(&self.reason))?;
552        }
553        Ok(())
554    }
555}
556
557impl From<TransportError> for ConnectionClose {
558    fn from(x: TransportError) -> Self {
559        Self {
560            error_code: x.code,
561            frame_type: x.frame,
562            reason: x.reason.into(),
563        }
564    }
565}
566
567impl FrameStruct for ConnectionClose {
568    const SIZE_BOUND: usize = 1 + 8 + 8 + 8;
569}
570
571impl ConnectionClose {
572    pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) {
573        out.write(FrameType::ConnectionClose); // 1 byte
574        out.write(self.error_code); // <= 8 bytes
575        out.write(self.frame_type); // <= 8 bytes
576        let max_len = max_len
577            - 3
578            - self.frame_type.size()
579            - VarInt::from_u64(self.reason.len() as u64).unwrap().size();
580        let actual_len = self.reason.len().min(max_len);
581        out.write_var(actual_len as u64); // <= 8 bytes
582        out.put_slice(&self.reason[0..actual_len]); // whatever's left
583    }
584}
585
586/// Reason given by an application for closing the connection
587#[derive(Debug, Clone, PartialEq, Eq)]
588pub struct ApplicationClose {
589    /// Application-specific reason code
590    pub error_code: VarInt,
591    /// Human-readable reason for the close
592    pub reason: Bytes,
593}
594
595impl fmt::Display for ApplicationClose {
596    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
597        if !self.reason.as_ref().is_empty() {
598            f.write_str(&String::from_utf8_lossy(&self.reason))?;
599            f.write_str(" (code ")?;
600            self.error_code.fmt(f)?;
601            f.write_str(")")?;
602        } else {
603            self.error_code.fmt(f)?;
604        }
605        Ok(())
606    }
607}
608
609impl FrameStruct for ApplicationClose {
610    const SIZE_BOUND: usize = 1 + 8 + 8;
611}
612
613impl ApplicationClose {
614    pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) {
615        out.write(FrameType::ApplicationClose); // 1 byte
616        out.write(self.error_code); // <= 8 bytes
617        let max_len = max_len - 3 - VarInt::from_u64(self.reason.len() as u64).unwrap().size();
618        let actual_len = self.reason.len().min(max_len);
619        out.write_var(actual_len as u64); // <= 8 bytes
620        out.put_slice(&self.reason[0..actual_len]); // whatever's left
621    }
622}
623
624#[derive(Clone, Eq, PartialEq)]
625pub struct PathAck {
626    pub path_id: PathId,
627    pub largest: u64,
628    pub delay: u64,
629    pub additional: Bytes,
630    pub ecn: Option<EcnCounts>,
631}
632
633impl fmt::Debug for PathAck {
634    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
635        let mut ranges = "[".to_string();
636        let mut first = true;
637        for range in self.into_iter() {
638            if !first {
639                ranges.push(',');
640            }
641            write!(ranges, "{range:?}")?;
642            first = false;
643        }
644        ranges.push(']');
645
646        f.debug_struct("PathAck")
647            .field("path_id", &self.path_id)
648            .field("largest", &self.largest)
649            .field("delay", &self.delay)
650            .field("ecn", &self.ecn)
651            .field("ranges", &ranges)
652            .finish()
653    }
654}
655
656impl<'a> IntoIterator for &'a PathAck {
657    type Item = RangeInclusive<u64>;
658    type IntoIter = AckIter<'a>;
659
660    fn into_iter(self) -> AckIter<'a> {
661        AckIter::new(self.largest, &self.additional[..])
662    }
663}
664
665impl PathAck {
666    pub fn into_ack(self) -> (Ack, PathId) {
667        let ack = Ack {
668            largest: self.largest,
669            delay: self.delay,
670            additional: self.additional,
671            ecn: self.ecn,
672        };
673
674        (ack, self.path_id)
675    }
676
677    pub(crate) fn encoder<'a>(
678        path_id: PathId,
679        delay: u64,
680        ranges: &'a ArrayRangeSet,
681        ecn: Option<&'a EcnCounts>,
682    ) -> PathAckEncoder<'a> {
683        PathAckEncoder {
684            path_id,
685            delay,
686            ranges,
687            ecn,
688        }
689    }
690}
691
692pub(crate) struct PathAckEncoder<'a> {
693    path_id: PathId,
694    delay: u64,
695    ranges: &'a ArrayRangeSet,
696    ecn: Option<&'a EcnCounts>,
697}
698
699impl<'a> Encodable for PathAckEncoder<'a> {
700    /// Encode [`Self`] into the given buffer
701    ///
702    /// The [`FrameType`] will be either [`FrameType::PathAckEcn`] or [`FrameType::PathAck`]
703    /// depending on whether [`EcnCounts`] are provided.
704    ///
705    /// PANICS: if `ranges` is empty.
706    fn encode<W: BufMut>(&self, buf: &mut W) {
707        let PathAckEncoder {
708            path_id,
709            delay,
710            ranges,
711            ecn,
712        } = self;
713        let mut rest = ranges.iter().rev();
714        let first = rest
715            .next()
716            .expect("Caller has verified ranges is non empty");
717        let largest = first.end - 1;
718        let first_size = first.end - first.start;
719        let kind = match ecn.is_some() {
720            true => FrameType::PathAckEcn,
721            false => FrameType::PathAck,
722        };
723        buf.write(kind);
724        buf.write(*path_id);
725        buf.write_var(largest);
726        buf.write_var(*delay);
727        buf.write_var(ranges.len() as u64 - 1);
728        buf.write_var(first_size - 1);
729        let mut prev = first.start;
730        for block in rest {
731            let size = block.end - block.start;
732            buf.write_var(prev - block.end - 1);
733            buf.write_var(size - 1);
734            prev = block.start;
735        }
736        if let Some(x) = ecn {
737            x.encode(buf)
738        }
739    }
740}
741
742#[derive(Clone, Eq, PartialEq)]
743pub struct Ack {
744    pub largest: u64,
745    pub delay: u64,
746    pub additional: Bytes,
747    pub ecn: Option<EcnCounts>,
748}
749
750impl fmt::Debug for Ack {
751    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
752        let mut ranges = "[".to_string();
753        let mut first = true;
754        for range in self.iter() {
755            if !first {
756                ranges.push(',');
757            }
758            write!(ranges, "{range:?}").unwrap();
759            first = false;
760        }
761        ranges.push(']');
762
763        f.debug_struct("Ack")
764            .field("largest", &self.largest)
765            .field("delay", &self.delay)
766            .field("ecn", &self.ecn)
767            .field("ranges", &ranges)
768            .finish()
769    }
770}
771
772impl<'a> IntoIterator for &'a Ack {
773    type Item = RangeInclusive<u64>;
774    type IntoIter = AckIter<'a>;
775
776    fn into_iter(self) -> AckIter<'a> {
777        AckIter::new(self.largest, &self.additional[..])
778    }
779}
780
781impl Ack {
782    pub(crate) fn encoder<'a>(
783        delay: u64,
784        ranges: &'a ArrayRangeSet,
785        ecn: Option<&'a EcnCounts>,
786    ) -> AckEncoder<'a> {
787        AckEncoder { delay, ranges, ecn }
788    }
789
790    pub fn iter(&self) -> AckIter<'_> {
791        self.into_iter()
792    }
793}
794
795pub(crate) struct AckEncoder<'a> {
796    delay: u64,
797    ranges: &'a ArrayRangeSet,
798    ecn: Option<&'a EcnCounts>,
799}
800
801impl<'a> Encodable for AckEncoder<'a> {
802    fn encode<W: BufMut>(&self, buf: &mut W) {
803        let AckEncoder { delay, ranges, ecn } = self;
804        let mut rest = ranges.iter().rev();
805        let first = rest.next().unwrap();
806        let largest = first.end - 1;
807        let first_size = first.end - first.start;
808        let kind = match ecn.is_some() {
809            true => FrameType::AckEcn,
810            false => FrameType::Ack,
811        };
812        buf.write(kind);
813        buf.write_var(largest);
814        buf.write_var(*delay);
815        buf.write_var(ranges.len() as u64 - 1);
816        buf.write_var(first_size - 1);
817        let mut prev = first.start;
818        for block in rest {
819            let size = block.end - block.start;
820            buf.write_var(prev - block.end - 1);
821            buf.write_var(size - 1);
822            prev = block.start;
823        }
824        if let Some(x) = ecn {
825            x.encode(buf)
826        }
827    }
828}
829
830#[derive(Debug, Copy, Clone, Eq, PartialEq)]
831pub struct EcnCounts {
832    pub ect0: u64,
833    pub ect1: u64,
834    pub ce: u64,
835}
836
837impl std::ops::AddAssign<EcnCodepoint> for EcnCounts {
838    fn add_assign(&mut self, rhs: EcnCodepoint) {
839        match rhs {
840            EcnCodepoint::Ect0 => {
841                self.ect0 += 1;
842            }
843            EcnCodepoint::Ect1 => {
844                self.ect1 += 1;
845            }
846            EcnCodepoint::Ce => {
847                self.ce += 1;
848            }
849        }
850    }
851}
852
853impl EcnCounts {
854    pub const ZERO: Self = Self {
855        ect0: 0,
856        ect1: 0,
857        ce: 0,
858    };
859}
860
861impl Encodable for EcnCounts {
862    fn encode<W: BufMut>(&self, out: &mut W) {
863        out.write_var(self.ect0);
864        out.write_var(self.ect1);
865        out.write_var(self.ce);
866    }
867}
868
869#[derive(Debug, Clone)]
870pub(crate) struct Stream {
871    pub(crate) id: StreamId,
872    pub(crate) offset: u64,
873    pub(crate) fin: bool,
874    pub(crate) data: Bytes,
875}
876
877impl FrameStruct for Stream {
878    const SIZE_BOUND: usize = 1 + 8 + 8 + 8;
879}
880
881/// Metadata from a stream frame
882#[derive(Debug, Clone)]
883pub(crate) struct StreamMeta {
884    pub(crate) id: StreamId,
885    pub(crate) offsets: Range<u64>,
886    pub(crate) fin: bool,
887}
888
889// This manual implementation exists because `Default` is not implemented for `StreamId`
890impl Default for StreamMeta {
891    fn default() -> Self {
892        Self {
893            id: StreamId(0),
894            offsets: 0..0,
895            fin: false,
896        }
897    }
898}
899
900impl StreamMeta {
901    pub(crate) fn encoder(&self, encode_length: bool) -> StreamMetaEncoder<'_> {
902        StreamMetaEncoder {
903            meta: self,
904            encode_length,
905        }
906    }
907}
908
909pub(crate) struct StreamMetaEncoder<'a> {
910    meta: &'a StreamMeta,
911    encode_length: bool,
912}
913
914impl<'a> Encodable for StreamMetaEncoder<'a> {
915    fn encode<W: BufMut>(&self, out: &mut W) {
916        let StreamMetaEncoder {
917            meta,
918            encode_length: length,
919        } = self;
920        let mut ty = *StreamInfo::VALUES.start();
921        if meta.offsets.start != 0 {
922            ty |= 0x04;
923        }
924        if *length {
925            ty |= 0x02;
926        }
927        if meta.fin {
928            ty |= 0x01;
929        }
930        out.write_var(ty); // 1 byte
931        out.write(meta.id); // <=8 bytes
932        if meta.offsets.start != 0 {
933            out.write_var(meta.offsets.start); // <=8 bytes
934        }
935        if *length {
936            out.write_var(meta.offsets.end - meta.offsets.start); // <=8 bytes
937        }
938    }
939}
940
941/// A vector of [`StreamMeta`] with optimization for the single element case
942pub(crate) type StreamMetaVec = TinyVec<[StreamMeta; 1]>;
943
944#[derive(Debug, Clone)]
945pub(crate) struct Crypto {
946    pub(crate) offset: u64,
947    pub(crate) data: Bytes,
948}
949
950impl Crypto {
951    pub(crate) const SIZE_BOUND: usize = 17;
952}
953
954impl Encodable for Crypto {
955    fn encode<W: BufMut>(&self, out: &mut W) {
956        out.write(FrameType::Crypto);
957        out.write_var(self.offset);
958        out.write_var(self.data.len() as u64);
959        out.put_slice(&self.data);
960    }
961}
962
963#[derive(Debug, Clone)]
964pub(crate) struct NewToken {
965    pub(crate) token: Bytes,
966}
967
968impl Encodable for NewToken {
969    fn encode<W: BufMut>(&self, out: &mut W) {
970        out.write(FrameType::NewToken);
971        out.write_var(self.token.len() as u64);
972        out.put_slice(&self.token);
973    }
974}
975
976impl NewToken {
977    pub(crate) fn size(&self) -> usize {
978        1 + VarInt::from_u64(self.token.len() as u64).unwrap().size() + self.token.len()
979    }
980}
981
982#[derive(Debug, Clone)]
983pub(crate) struct MaxPathId(pub(crate) PathId);
984
985impl MaxPathId {
986    pub(crate) const SIZE_BOUND: usize =
987        FrameType::MaxPathId.size() + VarInt(u32::MAX as u64).size();
988}
989
990impl Decodable for MaxPathId {
991    fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
992        Ok(Self(buf.get()?))
993    }
994}
995
996impl Encodable for MaxPathId {
997    fn encode<B: BufMut>(&self, buf: &mut B) {
998        buf.write(FrameType::MaxPathId);
999        buf.write(self.0);
1000    }
1001}
1002
1003#[derive(Debug, Clone, PartialEq, Eq)]
1004pub(crate) struct PathsBlocked(pub(crate) PathId);
1005
1006impl PathsBlocked {
1007    pub(crate) const SIZE_BOUND: usize =
1008        FrameType::PathsBlocked.size() + VarInt(u32::MAX as u64).size();
1009}
1010
1011impl Encodable for PathsBlocked {
1012    fn encode<B: BufMut>(&self, buf: &mut B) {
1013        buf.write(FrameType::PathsBlocked);
1014        buf.write(self.0);
1015    }
1016}
1017
1018impl Decodable for PathsBlocked {
1019    /// Decode [`Self`] from the buffer, provided that the frame type has been verified
1020    fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
1021        Ok(Self(buf.get()?))
1022    }
1023}
1024
1025#[derive(Debug, Clone, PartialEq, Eq)]
1026pub(crate) struct PathCidsBlocked {
1027    pub(crate) path_id: PathId,
1028    pub(crate) next_seq: VarInt,
1029}
1030
1031impl PathCidsBlocked {
1032    pub(crate) const SIZE_BOUND: usize =
1033        FrameType::PathCidsBlocked.size() + VarInt(u32::MAX as u64).size() + VarInt::MAX.size();
1034}
1035
1036impl Decodable for PathCidsBlocked {
1037    fn decode<R: Buf>(buf: &mut R) -> coding::Result<Self> {
1038        Ok(Self {
1039            path_id: buf.get()?,
1040            next_seq: buf.get()?,
1041        })
1042    }
1043}
1044
1045impl Encodable for PathCidsBlocked {
1046    fn encode<W: BufMut>(&self, buf: &mut W) {
1047        buf.write(FrameType::PathCidsBlocked);
1048        buf.write(self.path_id);
1049        buf.write(self.next_seq);
1050    }
1051}
1052
1053pub(crate) struct Iter {
1054    bytes: Bytes,
1055    last_ty: MaybeFrame,
1056}
1057
1058impl Iter {
1059    pub(crate) fn new(payload: Bytes) -> Result<Self, TransportError> {
1060        if payload.is_empty() {
1061            // "An endpoint MUST treat receipt of a packet containing no frames as a
1062            // connection error of type PROTOCOL_VIOLATION."
1063            // https://www.rfc-editor.org/rfc/rfc9000.html#name-frames-and-frame-types
1064            return Err(TransportError::PROTOCOL_VIOLATION(
1065                "packet payload is empty",
1066            ));
1067        }
1068
1069        Ok(Self {
1070            bytes: payload,
1071            last_ty: MaybeFrame::None,
1072        })
1073    }
1074
1075    fn take_len(&mut self) -> Result<Bytes, UnexpectedEnd> {
1076        let len = self.bytes.get_var()?;
1077        if len > self.bytes.remaining() as u64 {
1078            return Err(UnexpectedEnd);
1079        }
1080        Ok(self.bytes.split_to(len as usize))
1081    }
1082
1083    #[track_caller]
1084    fn try_next(&mut self) -> Result<Frame, IterErr> {
1085        self.last_ty = self.bytes.get()?;
1086
1087        let ty = match self.last_ty {
1088            MaybeFrame::None => FrameType::Padding,
1089            MaybeFrame::Unknown(_other) => return Err(IterErr::InvalidFrameId),
1090            MaybeFrame::Known(frame_type) => frame_type,
1091        };
1092        Ok(match ty {
1093            FrameType::Padding => Frame::Padding,
1094            FrameType::ResetStream => Frame::ResetStream(ResetStream {
1095                id: self.bytes.get()?,
1096                error_code: self.bytes.get()?,
1097                final_offset: self.bytes.get()?,
1098            }),
1099            FrameType::ConnectionClose => Frame::Close(Close::Connection(ConnectionClose {
1100                error_code: self.bytes.get()?,
1101                frame_type: self.bytes.get()?,
1102                reason: self.take_len()?,
1103            })),
1104            FrameType::ApplicationClose => Frame::Close(Close::Application(ApplicationClose {
1105                error_code: self.bytes.get()?,
1106                reason: self.take_len()?,
1107            })),
1108            FrameType::MaxData => Frame::MaxData(self.bytes.get()?),
1109            FrameType::MaxStreamData => Frame::MaxStreamData {
1110                id: self.bytes.get()?,
1111                offset: self.bytes.get_var()?,
1112            },
1113            FrameType::MaxStreamsBidi => Frame::MaxStreams {
1114                dir: Dir::Bi,
1115                count: self.bytes.get_var()?,
1116            },
1117            FrameType::MaxStreamsUni => Frame::MaxStreams {
1118                dir: Dir::Uni,
1119                count: self.bytes.get_var()?,
1120            },
1121            FrameType::Ping => Frame::Ping,
1122            FrameType::DataBlocked => Frame::DataBlocked {
1123                offset: self.bytes.get_var()?,
1124            },
1125            FrameType::StreamDataBlocked => Frame::StreamDataBlocked {
1126                id: self.bytes.get()?,
1127                offset: self.bytes.get_var()?,
1128            },
1129            FrameType::StreamsBlockedBidi => Frame::StreamsBlocked {
1130                dir: Dir::Bi,
1131                limit: self.bytes.get_var()?,
1132            },
1133            FrameType::StreamsBlockedUni => Frame::StreamsBlocked {
1134                dir: Dir::Uni,
1135                limit: self.bytes.get_var()?,
1136            },
1137            FrameType::StopSending => Frame::StopSending(StopSending {
1138                id: self.bytes.get()?,
1139                error_code: self.bytes.get()?,
1140            }),
1141            FrameType::RetireConnectionId | FrameType::PathRetireConnectionId => {
1142                Frame::RetireConnectionId(RetireConnectionId::decode(
1143                    &mut self.bytes,
1144                    ty == FrameType::PathRetireConnectionId,
1145                )?)
1146            }
1147            FrameType::Ack | FrameType::AckEcn => {
1148                let largest = self.bytes.get_var()?;
1149                let delay = self.bytes.get_var()?;
1150                let extra_blocks = self.bytes.get_var()? as usize;
1151                let n = scan_ack_blocks(&self.bytes, largest, extra_blocks)?;
1152                Frame::Ack(Ack {
1153                    delay,
1154                    largest,
1155                    additional: self.bytes.split_to(n),
1156                    ecn: if ty != FrameType::AckEcn && ty != FrameType::PathAckEcn {
1157                        None
1158                    } else {
1159                        Some(EcnCounts {
1160                            ect0: self.bytes.get_var()?,
1161                            ect1: self.bytes.get_var()?,
1162                            ce: self.bytes.get_var()?,
1163                        })
1164                    },
1165                })
1166            }
1167            FrameType::PathAck | FrameType::PathAckEcn => {
1168                let path_id = self.bytes.get()?;
1169                let largest = self.bytes.get_var()?;
1170                let delay = self.bytes.get_var()?;
1171                let extra_blocks = self.bytes.get_var()? as usize;
1172                let n = scan_ack_blocks(&self.bytes, largest, extra_blocks)?;
1173                Frame::PathAck(PathAck {
1174                    path_id,
1175                    delay,
1176                    largest,
1177                    additional: self.bytes.split_to(n),
1178                    ecn: if ty != FrameType::AckEcn && ty != FrameType::PathAckEcn {
1179                        None
1180                    } else {
1181                        Some(EcnCounts {
1182                            ect0: self.bytes.get_var()?,
1183                            ect1: self.bytes.get_var()?,
1184                            ce: self.bytes.get_var()?,
1185                        })
1186                    },
1187                })
1188            }
1189            FrameType::PathChallenge => Frame::PathChallenge(self.bytes.get()?),
1190            FrameType::PathResponse => Frame::PathResponse(self.bytes.get()?),
1191            FrameType::NewConnectionId | FrameType::PathNewConnectionId => {
1192                let read_path = ty == FrameType::PathNewConnectionId;
1193                Frame::NewConnectionId(NewConnectionId::read(&mut self.bytes, read_path)?)
1194            }
1195            FrameType::Crypto => Frame::Crypto(Crypto {
1196                offset: self.bytes.get_var()?,
1197                data: self.take_len()?,
1198            }),
1199            FrameType::NewToken => Frame::NewToken(NewToken {
1200                token: self.take_len()?,
1201            }),
1202            FrameType::HandshakeDone => Frame::HandshakeDone,
1203            FrameType::AckFrequency => Frame::AckFrequency(AckFrequency {
1204                sequence: self.bytes.get()?,
1205                ack_eliciting_threshold: self.bytes.get()?,
1206                request_max_ack_delay: self.bytes.get()?,
1207                reordering_threshold: self.bytes.get()?,
1208            }),
1209            FrameType::ImmediateAck => Frame::ImmediateAck,
1210            FrameType::ObservedIpv4Addr | FrameType::ObservedIpv6Addr => {
1211                let is_ipv6 = ty == FrameType::ObservedIpv6Addr;
1212                let observed = ObservedAddr::read(&mut self.bytes, is_ipv6)?;
1213                Frame::ObservedAddr(observed)
1214            }
1215            FrameType::PathAbandon => Frame::PathAbandon(PathAbandon::decode(&mut self.bytes)?),
1216            FrameType::PathStatusAvailable => {
1217                Frame::PathStatusAvailable(PathStatusAvailable::decode(&mut self.bytes)?)
1218            }
1219            FrameType::PathStatusBackup => {
1220                Frame::PathStatusBackup(PathStatusBackup::decode(&mut self.bytes)?)
1221            }
1222            FrameType::MaxPathId => Frame::MaxPathId(MaxPathId::decode(&mut self.bytes)?),
1223            FrameType::PathsBlocked => Frame::PathsBlocked(PathsBlocked::decode(&mut self.bytes)?),
1224            FrameType::PathCidsBlocked => {
1225                Frame::PathCidsBlocked(PathCidsBlocked::decode(&mut self.bytes)?)
1226            }
1227            FrameType::AddIpv4Address | FrameType::AddIpv6Address => {
1228                let is_ipv6 = ty == FrameType::AddIpv6Address;
1229                let add_address = AddAddress::read(&mut self.bytes, is_ipv6)?;
1230                Frame::AddAddress(add_address)
1231            }
1232            FrameType::ReachOutAtIpv4 | FrameType::ReachOutAtIpv6 => {
1233                let is_ipv6 = ty == FrameType::ReachOutAtIpv6;
1234                let reach_out = ReachOut::read(&mut self.bytes, is_ipv6)?;
1235                Frame::ReachOut(reach_out)
1236            }
1237            FrameType::RemoveAddress => Frame::RemoveAddress(RemoveAddress::read(&mut self.bytes)?),
1238            FrameType::Stream(s) => Frame::Stream(Stream {
1239                id: self.bytes.get()?,
1240                offset: if s.off() { self.bytes.get_var()? } else { 0 },
1241                fin: s.fin(),
1242                data: if s.len() {
1243                    self.take_len()?
1244                } else {
1245                    self.take_remaining()
1246                },
1247            }),
1248            FrameType::Datagram(d) => Frame::Datagram(Datagram {
1249                data: if d.len() {
1250                    self.take_len()?
1251                } else {
1252                    self.take_remaining()
1253                },
1254            }),
1255        })
1256    }
1257
1258    fn take_remaining(&mut self) -> Bytes {
1259        mem::take(&mut self.bytes)
1260    }
1261}
1262
1263impl Iterator for Iter {
1264    type Item = Result<Frame, InvalidFrame>;
1265    fn next(&mut self) -> Option<Self::Item> {
1266        if !self.bytes.has_remaining() {
1267            return None;
1268        }
1269        match self.try_next() {
1270            Ok(x) => Some(Ok(x)),
1271            Err(e) => {
1272                // Corrupt frame, skip it and everything that follows
1273                self.bytes.clear();
1274                Some(Err(InvalidFrame {
1275                    ty: self.last_ty,
1276                    reason: e.reason(),
1277                }))
1278            }
1279        }
1280    }
1281}
1282
1283#[derive(Debug)]
1284pub(crate) struct InvalidFrame {
1285    pub(crate) ty: MaybeFrame,
1286    pub(crate) reason: &'static str,
1287}
1288
1289impl From<InvalidFrame> for TransportError {
1290    fn from(err: InvalidFrame) -> Self {
1291        let mut te = Self::FRAME_ENCODING_ERROR(err.reason);
1292        te.frame = err.ty;
1293        te
1294    }
1295}
1296
1297/// Validate exactly `n` ACK ranges in `buf` and return the number of bytes they cover
1298fn scan_ack_blocks(mut buf: &[u8], largest: u64, n: usize) -> Result<usize, IterErr> {
1299    let total_len = buf.remaining();
1300    let first_block = buf.get_var()?;
1301    let mut smallest = largest.checked_sub(first_block).ok_or(IterErr::Malformed)?;
1302    for _ in 0..n {
1303        let gap = buf.get_var()?;
1304        smallest = smallest.checked_sub(gap + 2).ok_or(IterErr::Malformed)?;
1305        let block = buf.get_var()?;
1306        smallest = smallest.checked_sub(block).ok_or(IterErr::Malformed)?;
1307    }
1308    Ok(total_len - buf.remaining())
1309}
1310
1311#[derive(Debug)]
1312enum IterErr {
1313    UnexpectedEnd,
1314    InvalidFrameId,
1315    Malformed,
1316}
1317
1318impl IterErr {
1319    fn reason(&self) -> &'static str {
1320        use IterErr::*;
1321        match *self {
1322            UnexpectedEnd => "unexpected end",
1323            InvalidFrameId => "invalid frame ID",
1324            Malformed => "malformed",
1325        }
1326    }
1327}
1328
1329impl From<UnexpectedEnd> for IterErr {
1330    fn from(_: UnexpectedEnd) -> Self {
1331        Self::UnexpectedEnd
1332    }
1333}
1334
1335#[derive(Debug, Clone)]
1336pub struct AckIter<'a> {
1337    largest: u64,
1338    data: &'a [u8],
1339}
1340
1341impl<'a> AckIter<'a> {
1342    fn new(largest: u64, data: &'a [u8]) -> Self {
1343        Self { largest, data }
1344    }
1345}
1346
1347impl Iterator for AckIter<'_> {
1348    type Item = RangeInclusive<u64>;
1349    fn next(&mut self) -> Option<RangeInclusive<u64>> {
1350        if !self.data.has_remaining() {
1351            return None;
1352        }
1353        let block = self.data.get_var().unwrap();
1354        let largest = self.largest;
1355        if let Ok(gap) = self.data.get_var() {
1356            self.largest -= block + gap + 2;
1357        }
1358        Some(largest - block..=largest)
1359    }
1360}
1361
1362#[allow(unreachable_pub)] // fuzzing only
1363#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1364#[derive(Debug, Copy, Clone)]
1365pub struct ResetStream {
1366    pub(crate) id: StreamId,
1367    pub(crate) error_code: VarInt,
1368    pub(crate) final_offset: VarInt,
1369}
1370
1371impl FrameStruct for ResetStream {
1372    const SIZE_BOUND: usize = 1 + 8 + 8 + 8;
1373}
1374
1375impl Encodable for ResetStream {
1376    fn encode<W: BufMut>(&self, out: &mut W) {
1377        out.write(FrameType::ResetStream); // 1 byte
1378        out.write(self.id); // <= 8 bytes
1379        out.write(self.error_code); // <= 8 bytes
1380        out.write(self.final_offset); // <= 8 bytes
1381    }
1382}
1383
1384#[derive(Debug, Copy, Clone)]
1385pub(crate) struct StopSending {
1386    pub(crate) id: StreamId,
1387    pub(crate) error_code: VarInt,
1388}
1389
1390impl FrameStruct for StopSending {
1391    const SIZE_BOUND: usize = 1 + 8 + 8;
1392}
1393
1394impl Encodable for StopSending {
1395    fn encode<W: BufMut>(&self, out: &mut W) {
1396        out.write(FrameType::StopSending); // 1 byte
1397        out.write(self.id); // <= 8 bytes
1398        out.write(self.error_code) // <= 8 bytes
1399    }
1400}
1401
1402#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1403pub(crate) struct NewConnectionId {
1404    pub(crate) path_id: Option<PathId>,
1405    pub(crate) sequence: u64,
1406    pub(crate) retire_prior_to: u64,
1407    pub(crate) id: ConnectionId,
1408    pub(crate) reset_token: ResetToken,
1409}
1410
1411impl NewConnectionId {
1412    /// Maximum size of this frame when the frame type is [`FrameType::NewConnectionId`],
1413    pub(crate) const SIZE_BOUND: usize = {
1414        let type_len = FrameType::NewConnectionId.size();
1415        let seq_max_len = 8usize;
1416        let retire_prior_to_max_len = 8usize;
1417        let cid_len_len = 1;
1418        let cid_len = 160;
1419        let reset_token_len = 16;
1420        type_len + seq_max_len + retire_prior_to_max_len + cid_len_len + cid_len + reset_token_len
1421    };
1422
1423    /// Maximum size of this frame when the frame type is [`FrameType::PathNewConnectionId`],
1424    pub(crate) const SIZE_BOUND_MULTIPATH: usize = {
1425        let type_len = FrameType::PathNewConnectionId.size();
1426        let path_id_len = VarInt::from_u32(u32::MAX).size();
1427        let seq_max_len = 8usize;
1428        let retire_prior_to_max_len = 8usize;
1429        let cid_len_len = 1;
1430        let cid_len = 160;
1431        let reset_token_len = 16;
1432        type_len
1433            + path_id_len
1434            + seq_max_len
1435            + retire_prior_to_max_len
1436            + cid_len_len
1437            + cid_len
1438            + reset_token_len
1439    };
1440
1441    pub(crate) fn get_type(&self) -> FrameType {
1442        if self.path_id.is_some() {
1443            FrameType::PathNewConnectionId
1444        } else {
1445            FrameType::NewConnectionId
1446        }
1447    }
1448
1449    /// Returns the maximum encoded size on the wire.
1450    ///
1451    /// This is a rough upper estimate, does not squeeze every last byte out.
1452    pub(crate) const fn size_bound(path_new_cid: bool, cid_len: usize) -> usize {
1453        let upper_bound = match path_new_cid {
1454            true => Self::SIZE_BOUND_MULTIPATH,
1455            false => Self::SIZE_BOUND,
1456        };
1457        // instead of using the maximum cid len, use the provided one
1458        upper_bound - 160 + cid_len
1459    }
1460
1461    fn read<R: Buf>(bytes: &mut R, read_path: bool) -> Result<Self, IterErr> {
1462        let path_id = if read_path { Some(bytes.get()?) } else { None };
1463        let sequence = bytes.get_var()?;
1464        let retire_prior_to = bytes.get_var()?;
1465        if retire_prior_to > sequence {
1466            return Err(IterErr::Malformed);
1467        }
1468        let length = bytes.get::<u8>()? as usize;
1469        if length > MAX_CID_SIZE || length == 0 {
1470            return Err(IterErr::Malformed);
1471        }
1472        if length > bytes.remaining() {
1473            return Err(IterErr::UnexpectedEnd);
1474        }
1475        let mut stage = [0; MAX_CID_SIZE];
1476        bytes.copy_to_slice(&mut stage[0..length]);
1477        let id = ConnectionId::new(&stage[..length]);
1478        if bytes.remaining() < 16 {
1479            return Err(IterErr::UnexpectedEnd);
1480        }
1481        let mut reset_token = [0; RESET_TOKEN_SIZE];
1482        bytes.copy_to_slice(&mut reset_token);
1483        Ok(Self {
1484            path_id,
1485            sequence,
1486            retire_prior_to,
1487            id,
1488            reset_token: reset_token.into(),
1489        })
1490    }
1491}
1492
1493impl Encodable for NewConnectionId {
1494    fn encode<W: BufMut>(&self, out: &mut W) {
1495        out.write(self.get_type());
1496        if let Some(id) = self.path_id {
1497            out.write(id);
1498        }
1499        out.write_var(self.sequence);
1500        out.write_var(self.retire_prior_to);
1501        out.write(self.id.len() as u8);
1502        out.put_slice(&self.id);
1503        out.put_slice(&self.reset_token);
1504    }
1505}
1506
1507impl FrameStruct for NewConnectionId {
1508    const SIZE_BOUND: usize = 1 + 8 + 8 + 1 + MAX_CID_SIZE + RESET_TOKEN_SIZE;
1509}
1510
1511/// An unreliable datagram
1512#[derive(Debug, Clone)]
1513pub struct Datagram {
1514    /// Payload
1515    pub data: Bytes,
1516}
1517
1518impl FrameStruct for Datagram {
1519    const SIZE_BOUND: usize = 1 + 8;
1520}
1521
1522impl Datagram {
1523    pub(crate) fn size(&self, length: bool) -> usize {
1524        1 + if length {
1525            VarInt::from_u64(self.data.len() as u64).unwrap().size()
1526        } else {
1527            0
1528        } + self.data.len()
1529    }
1530}
1531
1532impl Encodable for Datagram {
1533    fn encode<B: BufMut>(&self, out: &mut B) {
1534        // A datagram is encoded only after this is verified.
1535        const ENCODE_LEN: bool = true;
1536        out.write(FrameType::Datagram(DatagramInfo(
1537            *DatagramInfo::VALUES.start() as u8 | u8::from(ENCODE_LEN),
1538        ))); // 1 byte
1539        // Safe to unwrap because we check length sanity before queueing datagrams
1540        out.write(VarInt::from_u64(self.data.len() as u64).unwrap()); // <= 8 bytes
1541        out.put_slice(&self.data);
1542    }
1543}
1544
1545#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1546pub(crate) struct AckFrequency {
1547    pub(crate) sequence: VarInt,
1548    pub(crate) ack_eliciting_threshold: VarInt,
1549    pub(crate) request_max_ack_delay: VarInt,
1550    pub(crate) reordering_threshold: VarInt,
1551}
1552
1553impl Encodable for AckFrequency {
1554    fn encode<W: BufMut>(&self, buf: &mut W) {
1555        buf.write(FrameType::AckFrequency);
1556        buf.write(self.sequence);
1557        buf.write(self.ack_eliciting_threshold);
1558        buf.write(self.request_max_ack_delay);
1559        buf.write(self.reordering_threshold);
1560    }
1561}
1562
1563/* Address Discovery https://datatracker.ietf.org/doc/draft-seemann-quic-address-discovery/ */
1564
1565/// Conjunction of the information contained in the address discovery frames
1566/// ([`FrameType::ObservedIpv4Addr`], [`FrameType::ObservedIpv6Addr`]).
1567#[derive(Debug, PartialEq, Eq, Clone)]
1568pub(crate) struct ObservedAddr {
1569    /// Monotonically increasing integer within the same connection.
1570    pub(crate) seq_no: VarInt,
1571    /// Reported observed address.
1572    pub(crate) ip: IpAddr,
1573    /// Reported observed port.
1574    pub(crate) port: u16,
1575}
1576
1577impl ObservedAddr {
1578    pub(crate) fn new<N: Into<VarInt>>(remote: std::net::SocketAddr, seq_no: N) -> Self {
1579        Self {
1580            ip: remote.ip(),
1581            port: remote.port(),
1582            seq_no: seq_no.into(),
1583        }
1584    }
1585
1586    /// Get the [`FrameType`] for this frame.
1587    pub(crate) fn get_type(&self) -> FrameType {
1588        if self.ip.is_ipv6() {
1589            FrameType::ObservedIpv6Addr
1590        } else {
1591            FrameType::ObservedIpv4Addr
1592        }
1593    }
1594
1595    /// Compute the number of bytes needed to encode the frame.
1596    pub(crate) fn size(&self) -> usize {
1597        let type_size = self.get_type().size();
1598        let req_id_bytes = self.seq_no.size();
1599        let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 };
1600        let port_bytes = 2;
1601        type_size + req_id_bytes + ip_bytes + port_bytes
1602    }
1603
1604    /// Reads the frame contents from the buffer.
1605    ///
1606    /// Should only be called when the frame type has been identified as
1607    /// [`FrameType::ObservedIpv4Addr`] or [`FrameType::ObservedIpv6Addr`].
1608    pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> {
1609        let seq_no = bytes.get()?;
1610        let ip = if is_ipv6 {
1611            IpAddr::V6(bytes.get()?)
1612        } else {
1613            IpAddr::V4(bytes.get()?)
1614        };
1615        let port = bytes.get()?;
1616        Ok(Self { seq_no, ip, port })
1617    }
1618
1619    /// Gives the [`SocketAddr`] reported in the frame.
1620    pub(crate) fn socket_addr(&self) -> SocketAddr {
1621        (self.ip, self.port).into()
1622    }
1623}
1624
1625impl Encodable for ObservedAddr {
1626    fn encode<W: BufMut>(&self, buf: &mut W) {
1627        buf.write(self.get_type());
1628        buf.write(self.seq_no);
1629        match self.ip {
1630            IpAddr::V4(ipv4_addr) => {
1631                buf.write(ipv4_addr);
1632            }
1633            IpAddr::V6(ipv6_addr) => {
1634                buf.write(ipv6_addr);
1635            }
1636        }
1637        buf.write::<u16>(self.port);
1638    }
1639}
1640
1641/* Multipath <https://datatracker.ietf.org/doc/draft-ietf-quic-multipath/> */
1642
1643#[derive(Debug, PartialEq, Eq)]
1644pub(crate) struct PathAbandon {
1645    pub(crate) path_id: PathId,
1646    pub(crate) error_code: TransportErrorCode,
1647}
1648
1649impl PathAbandon {
1650    pub(crate) const SIZE_BOUND: usize = FrameType::PathAbandon.size() + 8 + 8;
1651}
1652
1653impl Encodable for PathAbandon {
1654    fn encode<W: BufMut>(&self, buf: &mut W) {
1655        buf.write(FrameType::PathAbandon);
1656        buf.write(self.path_id);
1657        buf.write(self.error_code);
1658    }
1659}
1660
1661impl Decodable for PathAbandon {
1662    fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> {
1663        Ok(Self {
1664            path_id: bytes.get()?,
1665            error_code: bytes.get()?,
1666        })
1667    }
1668}
1669
1670#[derive(Debug, PartialEq, Eq)]
1671pub(crate) struct PathStatusAvailable {
1672    pub(crate) path_id: PathId,
1673    pub(crate) status_seq_no: VarInt,
1674}
1675
1676impl PathStatusAvailable {
1677    const TYPE: FrameType = FrameType::PathStatusAvailable;
1678    pub(crate) const SIZE_BOUND: usize = FrameType::PathStatusAvailable.size() + 8 + 8;
1679}
1680
1681impl Encodable for PathStatusAvailable {
1682    fn encode<W: BufMut>(&self, buf: &mut W) {
1683        buf.write(Self::TYPE);
1684        buf.write(self.path_id);
1685        buf.write(self.status_seq_no);
1686    }
1687}
1688
1689impl Decodable for PathStatusAvailable {
1690    fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> {
1691        Ok(Self {
1692            path_id: bytes.get()?,
1693            status_seq_no: bytes.get()?,
1694        })
1695    }
1696}
1697
1698#[derive(Debug, PartialEq, Eq)]
1699pub(crate) struct PathStatusBackup {
1700    pub(crate) path_id: PathId,
1701    pub(crate) status_seq_no: VarInt,
1702}
1703
1704impl PathStatusBackup {
1705    const TYPE: FrameType = FrameType::PathStatusBackup;
1706}
1707
1708impl Encodable for PathStatusBackup {
1709    fn encode<W: BufMut>(&self, buf: &mut W) {
1710        buf.write(Self::TYPE);
1711        buf.write(self.path_id);
1712        buf.write(self.status_seq_no);
1713    }
1714}
1715
1716impl Decodable for PathStatusBackup {
1717    fn decode<R: Buf>(bytes: &mut R) -> coding::Result<Self> {
1718        Ok(Self {
1719            path_id: bytes.get()?,
1720            status_seq_no: bytes.get()?,
1721        })
1722    }
1723}
1724
1725/* Nat traversal frames */
1726
1727/// Conjunction of the information contained in the add address frames
1728/// ([`FrameType::AddIpv4Address`], [`FrameType::AddIpv6Address`]).
1729#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)]
1730// TODO(@divma): remove
1731#[allow(dead_code)]
1732pub(crate) struct AddAddress {
1733    /// Monotonically increasing integer within the same connection
1734    // TODO(@divma): both assumed, the draft has no mention of this but it's standard
1735    pub(crate) seq_no: VarInt,
1736    /// Address to include in the known set
1737    pub(crate) ip: IpAddr,
1738    /// Port to use with this address
1739    pub(crate) port: u16,
1740}
1741
1742// TODO(@divma): remove
1743#[allow(dead_code)]
1744impl AddAddress {
1745    /// Smallest number of bytes this type of frame is guaranteed to fit within.
1746    pub(crate) const SIZE_BOUND: usize = Self {
1747        ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST),
1748        port: u16::MAX,
1749        seq_no: VarInt::MAX,
1750    }
1751    .size();
1752
1753    pub(crate) const fn new((ip, port): (IpAddr, u16), seq_no: VarInt) -> Self {
1754        Self { ip, port, seq_no }
1755    }
1756
1757    /// Get the [`FrameType`] for this frame.
1758    pub(crate) const fn get_type(&self) -> FrameType {
1759        if self.ip.is_ipv6() {
1760            FrameType::AddIpv6Address
1761        } else {
1762            FrameType::AddIpv4Address
1763        }
1764    }
1765
1766    /// Compute the number of bytes needed to encode the frame
1767    pub(crate) const fn size(&self) -> usize {
1768        let type_size = self.get_type().size();
1769        let seq_no_bytes = self.seq_no.size();
1770        let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 };
1771        let port_bytes = 2;
1772        type_size + seq_no_bytes + ip_bytes + port_bytes
1773    }
1774
1775    /// Read the frame contents from the buffer
1776    ///
1777    /// Should only be called when the frame type has been identified as
1778    /// [`FrameType::AddIpv4Address`] or [`FrameType::AddIpv6Address`].
1779    pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> {
1780        let seq_no = bytes.get()?;
1781        let ip = if is_ipv6 {
1782            IpAddr::V6(bytes.get()?)
1783        } else {
1784            IpAddr::V4(bytes.get()?)
1785        };
1786        let port = bytes.get()?;
1787        Ok(Self { seq_no, ip, port })
1788    }
1789
1790    /// Give the [`SocketAddr`] encoded in the frame
1791    pub(crate) fn socket_addr(&self) -> SocketAddr {
1792        self.ip_port().into()
1793    }
1794
1795    pub(crate) fn ip_port(&self) -> (IpAddr, u16) {
1796        (self.ip, self.port)
1797    }
1798}
1799
1800impl Encodable for AddAddress {
1801    fn encode<W: BufMut>(&self, buf: &mut W) {
1802        buf.write(self.get_type());
1803        buf.write(self.seq_no);
1804        match self.ip {
1805            IpAddr::V4(ipv4_addr) => {
1806                buf.write(ipv4_addr);
1807            }
1808            IpAddr::V6(ipv6_addr) => {
1809                buf.write(ipv6_addr);
1810            }
1811        }
1812        buf.write::<u16>(self.port);
1813    }
1814}
1815
1816/// Conjunction of the information contained in the reach out frames
1817/// ([`FrameType::ReachOutAtIpv4`], [`FrameType::ReachOutAtIpv6`])
1818#[derive(Debug, PartialEq, Eq, Clone)]
1819// TODO(@divma): remove
1820#[allow(dead_code)]
1821pub(crate) struct ReachOut {
1822    /// The sequence number of the NAT Traversal attempts
1823    pub(crate) round: VarInt,
1824    /// Address to use
1825    pub(crate) ip: IpAddr,
1826    /// Port to use with this address
1827    pub(crate) port: u16,
1828}
1829
1830// TODO(@divma): remove
1831#[allow(dead_code)]
1832impl ReachOut {
1833    /// Smallest number of bytes this type of frame is guaranteed to fit within
1834    pub(crate) const SIZE_BOUND: usize = Self {
1835        round: VarInt::MAX,
1836        ip: IpAddr::V6(std::net::Ipv6Addr::LOCALHOST),
1837        port: u16::MAX,
1838    }
1839    .size();
1840
1841    pub(crate) const fn new(round: VarInt, (ip, port): (IpAddr, u16)) -> Self {
1842        Self { round, ip, port }
1843    }
1844
1845    /// Get the [`FrameType`] for this frame
1846    pub(crate) const fn get_type(&self) -> FrameType {
1847        if self.ip.is_ipv6() {
1848            FrameType::ReachOutAtIpv6
1849        } else {
1850            FrameType::ReachOutAtIpv4
1851        }
1852    }
1853
1854    /// Compute the number of bytes needed to encode the frame
1855    pub(crate) const fn size(&self) -> usize {
1856        let type_size = self.get_type().size();
1857        let round_bytes = self.round.size();
1858        let ip_bytes = if self.ip.is_ipv6() { 16 } else { 4 };
1859        let port_bytes = 2;
1860        type_size + round_bytes + ip_bytes + port_bytes
1861    }
1862
1863    /// Read the frame contents from the buffer
1864    ///
1865    /// Should only be called when the frame type has been identified as
1866    /// [`FrameType::ReachOutAtIpv4`] or [`FrameType::ReachOutAtIpv6`].
1867    pub(crate) fn read<R: Buf>(bytes: &mut R, is_ipv6: bool) -> coding::Result<Self> {
1868        let round = bytes.get()?;
1869        let ip = if is_ipv6 {
1870            IpAddr::V6(bytes.get()?)
1871        } else {
1872            IpAddr::V4(bytes.get()?)
1873        };
1874        let port = bytes.get()?;
1875        Ok(Self { round, ip, port })
1876    }
1877
1878    /// Give the [`SocketAddr`] encoded in the frame
1879    pub(crate) fn socket_addr(&self) -> SocketAddr {
1880        (self.ip, self.port).into()
1881    }
1882}
1883
1884impl Encodable for ReachOut {
1885    fn encode<W: BufMut>(&self, buf: &mut W) {
1886        buf.write(self.get_type());
1887        buf.write(self.round);
1888        match self.ip {
1889            IpAddr::V4(ipv4_addr) => {
1890                buf.write(ipv4_addr);
1891            }
1892            IpAddr::V6(ipv6_addr) => {
1893                buf.write(ipv6_addr);
1894            }
1895        }
1896        buf.write::<u16>(self.port);
1897    }
1898}
1899
1900/// Frame signaling an address is no longer being advertised
1901#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)]
1902// TODO(@divma): remove
1903#[allow(dead_code)]
1904pub(crate) struct RemoveAddress {
1905    /// The sequence number of the address advertisement to be removed
1906    pub(crate) seq_no: VarInt,
1907}
1908
1909// TODO(@divma): remove
1910#[allow(dead_code)]
1911impl RemoveAddress {
1912    /// [`FrameType`] of this frame
1913    pub(crate) const TYPE: FrameType = FrameType::RemoveAddress;
1914
1915    /// Smallest number of bytes this type of frame is guaranteed to fit within
1916    pub(crate) const SIZE_BOUND: usize = Self::new(VarInt::MAX).size();
1917
1918    pub(crate) const fn new(seq_no: VarInt) -> Self {
1919        Self { seq_no }
1920    }
1921
1922    /// Compute the number of bytes needed to encode the frame
1923    pub(crate) const fn size(&self) -> usize {
1924        let type_size = Self::TYPE.size();
1925        let seq_no_bytes = self.seq_no.size();
1926        type_size + seq_no_bytes
1927    }
1928
1929    /// Read the frame contents from the buffer
1930    ///
1931    /// Should only be called when the frame type has been identified as
1932    /// [`FrameType::RemoveAddress`].
1933    pub(crate) fn read<R: Buf>(bytes: &mut R) -> coding::Result<Self> {
1934        Ok(Self {
1935            seq_no: bytes.get()?,
1936        })
1937    }
1938}
1939
1940impl Encodable for RemoveAddress {
1941    fn encode<W: BufMut>(&self, buf: &mut W) {
1942        buf.write(Self::TYPE);
1943        buf.write(self.seq_no);
1944    }
1945}
1946
1947#[cfg(test)]
1948mod test {
1949    use super::*;
1950    use crate::coding::Encodable;
1951    use assert_matches::assert_matches;
1952
1953    #[track_caller]
1954    fn frames(buf: Vec<u8>) -> Vec<Frame> {
1955        Iter::new(Bytes::from(buf))
1956            .unwrap()
1957            .collect::<Result<Vec<_>, _>>()
1958            .unwrap()
1959    }
1960
1961    #[test]
1962    fn ack_coding() {
1963        const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14];
1964        let mut ranges = ArrayRangeSet::new();
1965        for &packet in PACKETS {
1966            ranges.insert(packet..packet + 1);
1967        }
1968        let mut buf = Vec::new();
1969        const ECN: EcnCounts = EcnCounts {
1970            ect0: 42,
1971            ect1: 24,
1972            ce: 12,
1973        };
1974        Ack::encoder(42, &ranges, Some(&ECN)).encode(&mut buf);
1975        let frames = frames(buf);
1976        assert_eq!(frames.len(), 1);
1977        match frames[0] {
1978            Frame::Ack(ref ack) => {
1979                let mut packets = ack.iter().flatten().collect::<Vec<_>>();
1980                packets.sort_unstable();
1981                assert_eq!(&packets[..], PACKETS);
1982                assert_eq!(ack.ecn, Some(ECN));
1983            }
1984            ref x => panic!("incorrect frame {x:?}"),
1985        }
1986    }
1987
1988    #[test]
1989    #[allow(clippy::range_plus_one)]
1990    fn path_ack_coding() {
1991        const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14];
1992        let mut ranges = ArrayRangeSet::new();
1993        for &packet in PACKETS {
1994            ranges.insert(packet..packet + 1);
1995        }
1996        let mut buf = Vec::new();
1997        const ECN: EcnCounts = EcnCounts {
1998            ect0: 42,
1999            ect1: 24,
2000            ce: 12,
2001        };
2002        const PATH_ID: PathId = PathId::MAX;
2003        PathAck::encoder(PATH_ID, 42, &ranges, Some(&ECN)).encode(&mut buf);
2004        let frames = frames(buf);
2005        assert_eq!(frames.len(), 1);
2006        match frames[0] {
2007            Frame::PathAck(ref ack) => {
2008                assert_eq!(ack.path_id, PATH_ID);
2009                let mut packets = ack.into_iter().flatten().collect::<Vec<_>>();
2010                packets.sort_unstable();
2011                assert_eq!(&packets[..], PACKETS);
2012                assert_eq!(ack.ecn, Some(ECN));
2013            }
2014            ref x => panic!("incorrect frame {x:?}"),
2015        }
2016    }
2017
2018    #[test]
2019    fn ack_frequency_coding() {
2020        let mut buf = Vec::new();
2021        let original = AckFrequency {
2022            sequence: VarInt(42),
2023            ack_eliciting_threshold: VarInt(20),
2024            request_max_ack_delay: VarInt(50_000),
2025            reordering_threshold: VarInt(1),
2026        };
2027        original.encode(&mut buf);
2028        let frames = frames(buf);
2029        assert_eq!(frames.len(), 1);
2030        match &frames[0] {
2031            Frame::AckFrequency(decoded) => assert_eq!(decoded, &original),
2032            x => panic!("incorrect frame {x:?}"),
2033        }
2034    }
2035
2036    #[test]
2037    fn immediate_ack_coding() {
2038        let mut buf = Vec::new();
2039        FrameType::ImmediateAck.encode(&mut buf);
2040        let frames = frames(buf);
2041        assert_eq!(frames.len(), 1);
2042        assert_matches!(&frames[0], Frame::ImmediateAck);
2043    }
2044
2045    /// Test that encoding and decoding [`ObservedAddr`] produces the same result.
2046    #[test]
2047    fn test_observed_addr_roundrip() {
2048        let observed_addr = ObservedAddr {
2049            seq_no: VarInt(42),
2050            ip: std::net::Ipv4Addr::LOCALHOST.into(),
2051            port: 4242,
2052        };
2053        let mut buf = Vec::with_capacity(observed_addr.size());
2054        observed_addr.encode(&mut buf);
2055
2056        assert_eq!(
2057            observed_addr.size(),
2058            buf.len(),
2059            "expected written bytes and actual size differ"
2060        );
2061
2062        let mut decoded = frames(buf);
2063        assert_eq!(decoded.len(), 1);
2064        match decoded.pop().expect("non empty") {
2065            Frame::ObservedAddr(decoded) => assert_eq!(decoded, observed_addr),
2066            x => panic!("incorrect frame {x:?}"),
2067        }
2068    }
2069
2070    #[test]
2071    fn test_path_abandon_roundtrip() {
2072        let abandon = PathAbandon {
2073            path_id: PathId(42),
2074            error_code: TransportErrorCode::NO_ERROR,
2075        };
2076        let mut buf = Vec::new();
2077        abandon.encode(&mut buf);
2078
2079        let mut decoded = frames(buf);
2080        assert_eq!(decoded.len(), 1);
2081        match decoded.pop().expect("non empty") {
2082            Frame::PathAbandon(decoded) => assert_eq!(decoded, abandon),
2083            x => panic!("incorrect frame {x:?}"),
2084        }
2085    }
2086
2087    #[test]
2088    fn test_path_status_available_roundtrip() {
2089        let path_status_available = PathStatusAvailable {
2090            path_id: PathId(42),
2091            status_seq_no: VarInt(73),
2092        };
2093        let mut buf = Vec::new();
2094        path_status_available.encode(&mut buf);
2095
2096        let mut decoded = frames(buf);
2097        assert_eq!(decoded.len(), 1);
2098        match decoded.pop().expect("non empty") {
2099            Frame::PathStatusAvailable(decoded) => assert_eq!(decoded, path_status_available),
2100            x => panic!("incorrect frame {x:?}"),
2101        }
2102    }
2103
2104    #[test]
2105    fn test_path_status_backup_roundtrip() {
2106        let path_status_backup = PathStatusBackup {
2107            path_id: PathId(42),
2108            status_seq_no: VarInt(73),
2109        };
2110        let mut buf = Vec::new();
2111        path_status_backup.encode(&mut buf);
2112
2113        let mut decoded = frames(buf);
2114        assert_eq!(decoded.len(), 1);
2115        match decoded.pop().expect("non empty") {
2116            Frame::PathStatusBackup(decoded) => assert_eq!(decoded, path_status_backup),
2117            x => panic!("incorrect frame {x:?}"),
2118        }
2119    }
2120
2121    #[test]
2122    fn test_path_new_connection_id_roundtrip() {
2123        let cid = NewConnectionId {
2124            path_id: Some(PathId(22)),
2125            sequence: 31,
2126            retire_prior_to: 13,
2127            id: ConnectionId::new(&[0xAB; 8]),
2128            reset_token: ResetToken::from([0xCD; crate::RESET_TOKEN_SIZE]),
2129        };
2130        let mut buf = Vec::new();
2131        cid.encode(&mut buf);
2132
2133        let mut decoded = frames(buf);
2134        assert_eq!(decoded.len(), 1);
2135        match decoded.pop().expect("non empty") {
2136            Frame::NewConnectionId(decoded) => assert_eq!(decoded, cid),
2137            x => panic!("incorrect frame {x:?}"),
2138        }
2139    }
2140
2141    #[test]
2142    fn test_path_retire_connection_id_roundtrip() {
2143        let retire_cid = RetireConnectionId {
2144            path_id: Some(PathId(22)),
2145            sequence: 31,
2146        };
2147        let mut buf = Vec::new();
2148        retire_cid.encode(&mut buf);
2149
2150        let mut decoded = frames(buf);
2151        assert_eq!(decoded.len(), 1);
2152        match decoded.pop().expect("non empty") {
2153            Frame::RetireConnectionId(decoded) => assert_eq!(decoded, retire_cid),
2154            x => panic!("incorrect frame {x:?}"),
2155        }
2156    }
2157
2158    #[test]
2159    fn test_paths_blocked_path_cids_blocked_roundtrip() {
2160        let mut buf = Vec::new();
2161
2162        let frame0 = PathsBlocked(PathId(22));
2163        frame0.encode(&mut buf);
2164        let frame1 = PathCidsBlocked {
2165            path_id: PathId(23),
2166            next_seq: VarInt(32),
2167        };
2168        frame1.encode(&mut buf);
2169
2170        let mut decoded = frames(buf);
2171        assert_eq!(decoded.len(), 2);
2172        match decoded.pop().expect("non empty") {
2173            Frame::PathCidsBlocked(decoded) => assert_eq!(decoded, frame1),
2174            x => panic!("incorrect frame {x:?}"),
2175        }
2176        match decoded.pop().expect("non empty") {
2177            Frame::PathsBlocked(decoded) => assert_eq!(decoded, frame0),
2178            x => panic!("incorrect frame {x:?}"),
2179        }
2180    }
2181
2182    /// Test that encoding and decoding [`AddAddress`] produces the same result
2183    #[test]
2184    fn test_add_address_roundrip() {
2185        let add_address = AddAddress {
2186            seq_no: VarInt(42),
2187            ip: std::net::Ipv4Addr::LOCALHOST.into(),
2188            port: 4242,
2189        };
2190        let mut buf = Vec::with_capacity(add_address.size());
2191        add_address.encode(&mut buf);
2192
2193        assert_eq!(
2194            add_address.size(),
2195            buf.len(),
2196            "expected written bytes and actual size differ"
2197        );
2198
2199        let mut decoded = frames(buf);
2200        assert_eq!(decoded.len(), 1);
2201        match decoded.pop().expect("non empty") {
2202            Frame::AddAddress(decoded) => assert_eq!(decoded, add_address),
2203            x => panic!("incorrect frame {x:?}"),
2204        }
2205    }
2206
2207    /// Test that encoding and decoding [`AddAddress`] produces the same result
2208    #[test]
2209    fn test_reach_out_roundrip() {
2210        let reach_out = ReachOut {
2211            round: VarInt(42),
2212            ip: std::net::Ipv6Addr::LOCALHOST.into(),
2213            port: 4242,
2214        };
2215        let mut buf = Vec::with_capacity(reach_out.size());
2216        reach_out.encode(&mut buf);
2217
2218        assert_eq!(
2219            reach_out.size(),
2220            buf.len(),
2221            "expected written bytes and actual size differ"
2222        );
2223
2224        let mut decoded = frames(buf);
2225        assert_eq!(decoded.len(), 1);
2226        match decoded.pop().expect("non empty") {
2227            Frame::ReachOut(decoded) => assert_eq!(decoded, reach_out),
2228            x => panic!("incorrect frame {x:?}"),
2229        }
2230    }
2231
2232    /// Test that encoding and decoding [`RemoveAddress`] produces the same result
2233    #[test]
2234    fn test_remove_address_roundrip() {
2235        let remove_addr = RemoveAddress::new(VarInt(10));
2236        let mut buf = Vec::with_capacity(remove_addr.size());
2237        remove_addr.encode(&mut buf);
2238
2239        assert_eq!(
2240            remove_addr.size(),
2241            buf.len(),
2242            "expected written bytes and actual size differ"
2243        );
2244
2245        let mut decoded = frames(buf);
2246        assert_eq!(decoded.len(), 1);
2247        match decoded.pop().expect("non empty") {
2248            Frame::RemoveAddress(decoded) => assert_eq!(decoded, remove_addr),
2249            x => panic!("incorrect frame {x:?}"),
2250        }
2251    }
2252}