iroh_quinn_proto/
frame.rs

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