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