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