noq_proto/
frame.rs

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