noq_proto/
frame.rs

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