Skip to main content

ant_quic/
frame.rs

1// Copyright 2024 Saorsa Labs Ltd.
2//
3// This Saorsa Network Software is licensed under the General Public License (GPL), version 3.
4// Please see the file LICENSE-GPL, or visit <http://www.gnu.org/licenses/> for the full text.
5//
6// Full details available at https://saorsalabs.com/licenses
7#![allow(missing_docs)]
8
9use std::{
10    fmt::{self, Write},
11    mem,
12    net::SocketAddr,
13    ops::{Range, RangeInclusive},
14};
15
16use bytes::{Buf, BufMut, Bytes};
17use tinyvec::TinyVec;
18
19use crate::{
20    Dir, MAX_CID_SIZE, RESET_TOKEN_SIZE, ResetToken, StreamId, TransportError, TransportErrorCode,
21    VarInt, VarIntBoundsExceeded,
22    coding::{self, BufExt, BufMutExt, UnexpectedEnd},
23    range_set::ArrayRangeSet,
24    shared::{ConnectionId, EcnCodepoint},
25};
26
27fn log_encode_overflow(context: &'static str) {
28    tracing::error!("VarInt overflow while encoding {context}");
29    debug_assert!(false, "VarInt overflow while encoding {context}");
30}
31
32#[cfg(feature = "arbitrary")]
33use arbitrary::Arbitrary;
34
35/// A QUIC frame type
36#[derive(Copy, Clone, Eq, PartialEq)]
37pub struct FrameType(pub(crate) u64);
38
39impl FrameType {
40    pub(crate) fn stream(self) -> Option<StreamInfo> {
41        if STREAM_TYS.contains(&self.0) {
42            Some(StreamInfo(self.0 as u8))
43        } else {
44            None
45        }
46    }
47
48    /// Check if this is a STREAM frame type
49    #[allow(dead_code)]
50    pub(crate) fn is_stream(self) -> bool {
51        STREAM_TYS.contains(&self.0)
52    }
53    fn datagram(self) -> Option<DatagramInfo> {
54        if DATAGRAM_TYS.contains(&self.0) {
55            Some(DatagramInfo(self.0 as u8))
56        } else {
57            None
58        }
59    }
60
61    pub(crate) fn try_encode<B: BufMut>(&self, buf: &mut B) -> Result<(), VarIntBoundsExceeded> {
62        buf.write_var(self.0)
63    }
64}
65
66impl coding::Codec for FrameType {
67    fn decode<B: Buf>(buf: &mut B) -> coding::Result<Self> {
68        Ok(Self(buf.get_var()?))
69    }
70    fn encode<B: BufMut>(&self, buf: &mut B) {
71        if self.try_encode(buf).is_err() {
72            log_encode_overflow("FrameType");
73        }
74    }
75}
76
77pub(crate) trait FrameStruct {
78    /// Smallest number of bytes this type of frame is guaranteed to fit within.
79    const SIZE_BOUND: usize;
80}
81
82macro_rules! frame_types {
83    {$($name:ident = $val:expr_2021,)*} => {
84        impl FrameType {
85            $(pub(crate) const $name: FrameType = FrameType($val);)*
86        }
87
88        impl fmt::Debug for FrameType {
89            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90                match self.0 {
91                    $($val => f.write_str(stringify!($name)),)*
92                    _ => write!(f, "Type({:02x})", self.0)
93                }
94            }
95        }
96
97        impl fmt::Display for FrameType {
98            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99                match self.0 {
100                    $($val => f.write_str(stringify!($name)),)*
101                    x if STREAM_TYS.contains(&x) => f.write_str("STREAM"),
102                    x if DATAGRAM_TYS.contains(&x) => f.write_str("DATAGRAM"),
103                    _ => write!(f, "<unknown {:02x}>", self.0),
104                }
105            }
106        }
107    }
108}
109
110#[derive(Debug, Copy, Clone, Eq, PartialEq)]
111pub(crate) struct StreamInfo(u8);
112
113impl StreamInfo {
114    fn fin(self) -> bool {
115        self.0 & 0x01 != 0
116    }
117    fn len(self) -> bool {
118        self.0 & 0x02 != 0
119    }
120    fn off(self) -> bool {
121        self.0 & 0x04 != 0
122    }
123}
124
125#[derive(Debug, Copy, Clone, Eq, PartialEq)]
126struct DatagramInfo(u8);
127
128impl DatagramInfo {
129    fn len(self) -> bool {
130        self.0 & 0x01 != 0
131    }
132}
133
134frame_types! {
135    PADDING = 0x00,
136    PING = 0x01,
137    ACK = 0x02,
138    ACK_ECN = 0x03,
139    RESET_STREAM = 0x04,
140    STOP_SENDING = 0x05,
141    CRYPTO = 0x06,
142    NEW_TOKEN = 0x07,
143    // STREAM
144    MAX_DATA = 0x10,
145    MAX_STREAM_DATA = 0x11,
146    MAX_STREAMS_BIDI = 0x12,
147    MAX_STREAMS_UNI = 0x13,
148    DATA_BLOCKED = 0x14,
149    STREAM_DATA_BLOCKED = 0x15,
150    STREAMS_BLOCKED_BIDI = 0x16,
151    STREAMS_BLOCKED_UNI = 0x17,
152    NEW_CONNECTION_ID = 0x18,
153    RETIRE_CONNECTION_ID = 0x19,
154    PATH_CHALLENGE = 0x1a,
155    PATH_RESPONSE = 0x1b,
156    CONNECTION_CLOSE = 0x1c,
157    APPLICATION_CLOSE = 0x1d,
158    HANDSHAKE_DONE = 0x1e,
159    // ACK Frequency
160    ACK_FREQUENCY = 0xaf,
161    IMMEDIATE_ACK = 0x1f,
162    // NAT Traversal Extension - draft-seemann-quic-nat-traversal-02
163    ADD_ADDRESS_IPV4 = 0x3d7e90,
164    ADD_ADDRESS_IPV6 = 0x3d7e91,
165    PUNCH_ME_NOW_IPV4 = 0x3d7e92,
166    PUNCH_ME_NOW_IPV6 = 0x3d7e93,
167    REMOVE_ADDRESS = 0x3d7e94,
168    // Address Discovery Extension - draft-ietf-quic-address-discovery-00
169    OBSERVED_ADDRESS_IPV4 = 0x9f81a6,
170    OBSERVED_ADDRESS_IPV6 = 0x9f81a7,
171    // NAT Traversal Callback - try_connect_to request/response
172    TRY_CONNECT_TO_IPV4 = 0x3d7e95,
173    TRY_CONNECT_TO_IPV6 = 0x3d7e96,
174    TRY_CONNECT_TO_RESPONSE_IPV4 = 0x3d7e97,
175    TRY_CONNECT_TO_RESPONSE_IPV6 = 0x3d7e98,
176    // DATAGRAM
177}
178
179const STREAM_TYS: RangeInclusive<u64> = RangeInclusive::new(0x08, 0x0f);
180const DATAGRAM_TYS: RangeInclusive<u64> = RangeInclusive::new(0x30, 0x31);
181
182/// All supported QUIC frame variants handled by this implementation
183#[derive(Debug)]
184pub(crate) enum Frame {
185    Padding,
186    Ping,
187    Ack(Ack),
188    ResetStream(ResetStream),
189    StopSending(StopSending),
190    Crypto(Crypto),
191    NewToken(NewToken),
192    Stream(Stream),
193    MaxData(VarInt),
194    MaxStreamData { id: StreamId, offset: u64 },
195    MaxStreams { dir: Dir, count: u64 },
196    DataBlocked { offset: u64 },
197    StreamDataBlocked { id: StreamId, offset: u64 },
198    StreamsBlocked { dir: Dir, limit: u64 },
199    NewConnectionId(NewConnectionId),
200    RetireConnectionId { sequence: u64 },
201    PathChallenge(u64),
202    PathResponse(u64),
203    Close(Close),
204    Datagram(Datagram),
205    AckFrequency(AckFrequency),
206    ImmediateAck,
207    HandshakeDone,
208    AddAddress(AddAddress),
209    PunchMeNow(PunchMeNow),
210    RemoveAddress(RemoveAddress),
211    ObservedAddress(ObservedAddress),
212    TryConnectTo(TryConnectTo),
213    TryConnectToResponse(TryConnectToResponse),
214}
215
216impl Frame {
217    pub(crate) fn ty(&self) -> FrameType {
218        use Frame::*;
219        match self {
220            Padding => FrameType::PADDING,
221            ResetStream(_) => FrameType::RESET_STREAM,
222            Close(self::Close::Connection(_)) => FrameType::CONNECTION_CLOSE,
223            Close(self::Close::Application(_)) => FrameType::APPLICATION_CLOSE,
224            MaxData(_) => FrameType::MAX_DATA,
225            MaxStreamData { .. } => FrameType::MAX_STREAM_DATA,
226            MaxStreams { dir: Dir::Bi, .. } => FrameType::MAX_STREAMS_BIDI,
227            MaxStreams { dir: Dir::Uni, .. } => FrameType::MAX_STREAMS_UNI,
228            Ping => FrameType::PING,
229            DataBlocked { .. } => FrameType::DATA_BLOCKED,
230            StreamDataBlocked { .. } => FrameType::STREAM_DATA_BLOCKED,
231            StreamsBlocked { dir: Dir::Bi, .. } => FrameType::STREAMS_BLOCKED_BIDI,
232            StreamsBlocked { dir: Dir::Uni, .. } => FrameType::STREAMS_BLOCKED_UNI,
233            StopSending { .. } => FrameType::STOP_SENDING,
234            RetireConnectionId { .. } => FrameType::RETIRE_CONNECTION_ID,
235            Ack(_) => FrameType::ACK,
236            Stream(x) => {
237                let mut ty = *STREAM_TYS.start();
238                if x.fin {
239                    ty |= 0x01;
240                }
241                if x.offset != 0 {
242                    ty |= 0x04;
243                }
244                FrameType(ty)
245            }
246            PathChallenge(_) => FrameType::PATH_CHALLENGE,
247            PathResponse(_) => FrameType::PATH_RESPONSE,
248            NewConnectionId { .. } => FrameType::NEW_CONNECTION_ID,
249            Crypto(_) => FrameType::CRYPTO,
250            NewToken(_) => FrameType::NEW_TOKEN,
251            Datagram(_) => FrameType(*DATAGRAM_TYS.start()),
252            AckFrequency(_) => FrameType::ACK_FREQUENCY,
253            ImmediateAck => FrameType::IMMEDIATE_ACK,
254            HandshakeDone => FrameType::HANDSHAKE_DONE,
255            AddAddress(a) => match a.address {
256                SocketAddr::V4(_) => FrameType::ADD_ADDRESS_IPV4,
257                SocketAddr::V6(_) => FrameType::ADD_ADDRESS_IPV6,
258            },
259            PunchMeNow(p) => match p.address {
260                SocketAddr::V4(_) => FrameType::PUNCH_ME_NOW_IPV4,
261                SocketAddr::V6(_) => FrameType::PUNCH_ME_NOW_IPV6,
262            },
263            RemoveAddress(_) => FrameType::REMOVE_ADDRESS,
264            ObservedAddress(o) => match o.address {
265                SocketAddr::V4(_) => FrameType::OBSERVED_ADDRESS_IPV4,
266                SocketAddr::V6(_) => FrameType::OBSERVED_ADDRESS_IPV6,
267            },
268            TryConnectTo(t) => match t.target_address {
269                SocketAddr::V4(_) => FrameType::TRY_CONNECT_TO_IPV4,
270                SocketAddr::V6(_) => FrameType::TRY_CONNECT_TO_IPV6,
271            },
272            TryConnectToResponse(r) => match r.source_address {
273                SocketAddr::V4(_) => FrameType::TRY_CONNECT_TO_RESPONSE_IPV4,
274                SocketAddr::V6(_) => FrameType::TRY_CONNECT_TO_RESPONSE_IPV6,
275            },
276        }
277    }
278
279    pub(crate) fn is_ack_eliciting(&self) -> bool {
280        !matches!(*self, Self::Ack(_) | Self::Padding | Self::Close(_))
281    }
282}
283
284/// Reason for closing a connection (transport or application)
285#[derive(Clone, Debug)]
286pub enum Close {
287    /// Transport-layer connection close
288    Connection(ConnectionClose),
289    /// Application-layer connection close
290    Application(ApplicationClose),
291}
292
293impl Close {
294    pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) {
295        if self.try_encode(out, max_len).is_err() {
296            log_encode_overflow("Close");
297        }
298    }
299
300    pub(crate) fn try_encode<W: BufMut>(
301        &self,
302        out: &mut W,
303        max_len: usize,
304    ) -> Result<(), VarIntBoundsExceeded> {
305        match *self {
306            Self::Connection(ref x) => x.try_encode(out, max_len),
307            Self::Application(ref x) => x.try_encode(out, max_len),
308        }
309    }
310
311    pub(crate) fn is_transport_layer(&self) -> bool {
312        matches!(*self, Self::Connection(_))
313    }
314}
315
316impl From<TransportError> for Close {
317    fn from(x: TransportError) -> Self {
318        Self::Connection(x.into())
319    }
320}
321impl From<ConnectionClose> for Close {
322    fn from(x: ConnectionClose) -> Self {
323        Self::Connection(x)
324    }
325}
326impl From<ApplicationClose> for Close {
327    fn from(x: ApplicationClose) -> Self {
328        Self::Application(x)
329    }
330}
331
332/// Reason given by the transport for closing the connection
333#[derive(Debug, Clone, PartialEq, Eq)]
334pub struct ConnectionClose {
335    /// Class of error as encoded in the specification
336    pub error_code: TransportErrorCode,
337    /// Type of frame that caused the close
338    pub frame_type: Option<FrameType>,
339    /// Human-readable reason for the close
340    pub reason: Bytes,
341}
342
343impl fmt::Display for ConnectionClose {
344    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
345        self.error_code.fmt(f)?;
346        if !self.reason.as_ref().is_empty() {
347            f.write_str(": ")?;
348            f.write_str(&String::from_utf8_lossy(&self.reason))?;
349        }
350        Ok(())
351    }
352}
353
354impl From<TransportError> for ConnectionClose {
355    fn from(x: TransportError) -> Self {
356        Self {
357            error_code: x.code,
358            frame_type: x.frame,
359            reason: x.reason.into(),
360        }
361    }
362}
363
364impl FrameStruct for ConnectionClose {
365    const SIZE_BOUND: usize = 1 + 8 + 8 + 8;
366}
367
368impl ConnectionClose {
369    #[allow(dead_code)]
370    pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) {
371        if self.try_encode(out, max_len).is_err() {
372            log_encode_overflow("ConnectionClose");
373        }
374    }
375
376    pub(crate) fn try_encode<W: BufMut>(
377        &self,
378        out: &mut W,
379        max_len: usize,
380    ) -> Result<(), VarIntBoundsExceeded> {
381        FrameType::CONNECTION_CLOSE.try_encode(out)?; // 1 byte
382        out.write_var(u64::from(self.error_code))?; // <= 8 bytes
383        let ty = self.frame_type.map_or(0, |x| x.0);
384        out.write_var(ty)?; // <= 8 bytes
385        let max_len = max_len
386            - 3
387            - VarInt::from_u64_bounded(ty).size()
388            - VarInt::from_u64_bounded(self.reason.len() as u64).size();
389        let actual_len = self.reason.len().min(max_len);
390        out.write_var(actual_len as u64)?; // <= 8 bytes
391        out.put_slice(&self.reason[0..actual_len]); // whatever's left
392        Ok(())
393    }
394}
395
396/// Reason given by an application for closing the connection
397#[derive(Debug, Clone, PartialEq, Eq)]
398pub struct ApplicationClose {
399    /// Application-specific reason code
400    pub error_code: VarInt,
401    /// Human-readable reason for the close
402    pub reason: Bytes,
403}
404
405impl fmt::Display for ApplicationClose {
406    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
407        if !self.reason.as_ref().is_empty() {
408            f.write_str(&String::from_utf8_lossy(&self.reason))?;
409            f.write_str(" (code ")?;
410            self.error_code.fmt(f)?;
411            f.write_str(")")?;
412        } else {
413            self.error_code.fmt(f)?;
414        }
415        Ok(())
416    }
417}
418
419impl FrameStruct for ApplicationClose {
420    const SIZE_BOUND: usize = 1 + 8 + 8;
421}
422
423impl ApplicationClose {
424    #[allow(dead_code)]
425    pub(crate) fn encode<W: BufMut>(&self, out: &mut W, max_len: usize) {
426        if self.try_encode(out, max_len).is_err() {
427            log_encode_overflow("ApplicationClose");
428        }
429    }
430
431    pub(crate) fn try_encode<W: BufMut>(
432        &self,
433        out: &mut W,
434        max_len: usize,
435    ) -> Result<(), VarIntBoundsExceeded> {
436        FrameType::APPLICATION_CLOSE.try_encode(out)?; // 1 byte
437        out.write_var(self.error_code.into_inner())?; // <= 8 bytes
438        let max_len = max_len - 3 - VarInt::from_u64_bounded(self.reason.len() as u64).size();
439        let actual_len = self.reason.len().min(max_len);
440        out.write_var(actual_len as u64)?; // <= 8 bytes
441        out.put_slice(&self.reason[0..actual_len]); // whatever's left
442        Ok(())
443    }
444}
445
446#[derive(Clone, Eq, PartialEq)]
447/// Contents of an ACK frame
448pub struct Ack {
449    /// Largest acknowledged packet number
450    pub largest: u64,
451    /// ACK delay in microseconds
452    pub delay: u64,
453    /// Additional ACK block data encoded per RFC 9000
454    pub additional: Bytes,
455    /// Explicit Congestion Notification counters, if present
456    pub ecn: Option<EcnCounts>,
457}
458
459impl fmt::Debug for Ack {
460    #[allow(clippy::panic)]
461    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
462        let mut ranges = "[".to_string();
463        let mut first = true;
464        for range in self.iter() {
465            if !first {
466                ranges.push(',');
467            }
468            write!(ranges, "{range:?}")
469                .unwrap_or_else(|_| panic!("writing to string should not fail"));
470            first = false;
471        }
472        ranges.push(']');
473
474        f.debug_struct("Ack")
475            .field("largest", &self.largest)
476            .field("delay", &self.delay)
477            .field("ecn", &self.ecn)
478            .field("ranges", &ranges)
479            .finish()
480    }
481}
482
483impl<'a> IntoIterator for &'a Ack {
484    type Item = RangeInclusive<u64>;
485    type IntoIter = AckIter<'a>;
486
487    fn into_iter(self) -> AckIter<'a> {
488        AckIter::new(self.largest, &self.additional[..])
489    }
490}
491
492impl Ack {
493    /// Encode an ACK frame into the provided buffer
494    #[allow(clippy::panic)]
495    pub fn encode<W: BufMut>(
496        delay: u64,
497        ranges: &ArrayRangeSet,
498        ecn: Option<&EcnCounts>,
499        buf: &mut W,
500    ) {
501        if Self::try_encode(delay, ranges, ecn, buf).is_err() {
502            log_encode_overflow("Ack");
503        }
504    }
505
506    pub fn try_encode<W: BufMut>(
507        delay: u64,
508        ranges: &ArrayRangeSet,
509        ecn: Option<&EcnCounts>,
510        buf: &mut W,
511    ) -> Result<(), VarIntBoundsExceeded> {
512        let mut rest = ranges.iter().rev();
513        let first = match rest.next() {
514            Some(first) => first,
515            None => {
516                tracing::error!("ACK ranges should have at least one range");
517                return Err(VarIntBoundsExceeded);
518            }
519        };
520        let largest = first.end - 1;
521        let first_size = first.end - first.start;
522        if ecn.is_some() {
523            FrameType::ACK_ECN.try_encode(buf)?;
524        } else {
525            FrameType::ACK.try_encode(buf)?;
526        }
527        buf.write_var(largest)?;
528        buf.write_var(delay)?;
529        buf.write_var(ranges.len() as u64 - 1)?;
530        buf.write_var(first_size - 1)?;
531        let mut prev = first.start;
532        for block in rest {
533            let size = block.end - block.start;
534            buf.write_var(prev - block.end - 1)?;
535            buf.write_var(size - 1)?;
536            prev = block.start;
537        }
538        if let Some(x) = ecn {
539            x.try_encode(buf)?;
540        }
541        Ok(())
542    }
543
544    /// Iterate over acknowledged packet ranges
545    pub fn iter(&self) -> AckIter<'_> {
546        self.into_iter()
547    }
548}
549
550#[derive(Debug, Copy, Clone, Eq, PartialEq)]
551/// Explicit Congestion Notification counters
552pub struct EcnCounts {
553    /// Number of ECT(0) marked packets
554    pub ect0: u64,
555    /// Number of ECT(1) marked packets
556    pub ect1: u64,
557    /// Number of CE marked packets
558    pub ce: u64,
559}
560
561impl std::ops::AddAssign<EcnCodepoint> for EcnCounts {
562    fn add_assign(&mut self, rhs: EcnCodepoint) {
563        match rhs {
564            EcnCodepoint::Ect0 => {
565                self.ect0 += 1;
566            }
567            EcnCodepoint::Ect1 => {
568                self.ect1 += 1;
569            }
570            EcnCodepoint::Ce => {
571                self.ce += 1;
572            }
573        }
574    }
575}
576
577impl EcnCounts {
578    pub const ZERO: Self = Self {
579        ect0: 0,
580        ect1: 0,
581        ce: 0,
582    };
583
584    pub fn encode<W: BufMut>(&self, out: &mut W) {
585        if self.try_encode(out).is_err() {
586            log_encode_overflow("EcnCounts");
587        }
588    }
589
590    pub fn try_encode<W: BufMut>(&self, out: &mut W) -> Result<(), VarIntBoundsExceeded> {
591        out.write_var(self.ect0)?;
592        out.write_var(self.ect1)?;
593        out.write_var(self.ce)?;
594        Ok(())
595    }
596}
597
598#[derive(Debug, Clone)]
599pub(crate) struct Stream {
600    pub(crate) id: StreamId,
601    pub(crate) offset: u64,
602    pub(crate) fin: bool,
603    pub(crate) data: Bytes,
604}
605
606impl FrameStruct for Stream {
607    const SIZE_BOUND: usize = 1 + 8 + 8 + 8;
608}
609
610/// Metadata from a stream frame
611#[derive(Debug, Clone)]
612pub(crate) struct StreamMeta {
613    pub(crate) id: StreamId,
614    pub(crate) offsets: Range<u64>,
615    pub(crate) fin: bool,
616}
617
618// This manual implementation exists because `Default` is not implemented for `StreamId`
619impl Default for StreamMeta {
620    fn default() -> Self {
621        Self {
622            id: StreamId(0),
623            offsets: 0..0,
624            fin: false,
625        }
626    }
627}
628
629impl StreamMeta {
630    pub(crate) fn encode<W: BufMut>(&self, length: bool, out: &mut W) {
631        if self.try_encode(length, out).is_err() {
632            log_encode_overflow("StreamMeta");
633        }
634    }
635
636    pub(crate) fn try_encode<W: BufMut>(
637        &self,
638        length: bool,
639        out: &mut W,
640    ) -> Result<(), VarIntBoundsExceeded> {
641        let mut ty = *STREAM_TYS.start();
642        if self.offsets.start != 0 {
643            ty |= 0x04;
644        }
645        if length {
646            ty |= 0x02;
647        }
648        if self.fin {
649            ty |= 0x01;
650        }
651        out.write_var(ty)?; // 1 byte
652        out.write(self.id); // <=8 bytes
653        if self.offsets.start != 0 {
654            out.write_var(self.offsets.start)?; // <=8 bytes
655        }
656        if length {
657            out.write_var(self.offsets.end - self.offsets.start)?; // <=8 bytes
658        }
659        Ok(())
660    }
661}
662
663/// A vector of [`StreamMeta`] with optimization for the single element case
664pub(crate) type StreamMetaVec = TinyVec<[StreamMeta; 1]>;
665
666#[derive(Debug, Clone)]
667pub(crate) struct Crypto {
668    pub(crate) offset: u64,
669    pub(crate) data: Bytes,
670}
671
672impl Crypto {
673    pub(crate) const SIZE_BOUND: usize = 17;
674
675    #[allow(dead_code)]
676    pub(crate) fn encode<W: BufMut>(&self, out: &mut W) {
677        if self.try_encode(out).is_err() {
678            log_encode_overflow("Crypto");
679        }
680    }
681
682    pub(crate) fn try_encode<W: BufMut>(&self, out: &mut W) -> Result<(), VarIntBoundsExceeded> {
683        FrameType::CRYPTO.try_encode(out)?;
684        out.write_var(self.offset)?;
685        out.write_var(self.data.len() as u64)?;
686        out.put_slice(&self.data);
687        Ok(())
688    }
689}
690
691#[derive(Debug, Clone)]
692pub(crate) struct NewToken {
693    pub(crate) token: Bytes,
694}
695
696impl NewToken {
697    #[allow(dead_code)]
698    pub(crate) fn encode<W: BufMut>(&self, out: &mut W) {
699        if self.try_encode(out).is_err() {
700            log_encode_overflow("NewToken");
701        }
702    }
703
704    pub(crate) fn try_encode<W: BufMut>(&self, out: &mut W) -> Result<(), VarIntBoundsExceeded> {
705        FrameType::NEW_TOKEN.try_encode(out)?;
706        out.write_var(self.token.len() as u64)?;
707        out.put_slice(&self.token);
708        Ok(())
709    }
710
711    pub(crate) fn size(&self) -> usize {
712        1 + VarInt::from_u64_bounded(self.token.len() as u64).size() + self.token.len()
713    }
714}
715
716pub(crate) struct Iter {
717    bytes: Bytes,
718    last_ty: Option<FrameType>,
719}
720
721impl Iter {
722    pub(crate) fn new(payload: Bytes) -> Result<Self, TransportError> {
723        if payload.is_empty() {
724            // "An endpoint MUST treat receipt of a packet containing no frames as a
725            // connection error of type PROTOCOL_VIOLATION."
726            // https://www.rfc-editor.org/rfc/rfc9000.html#name-frames-and-frame-types
727            return Err(TransportError::PROTOCOL_VIOLATION(
728                "packet payload is empty",
729            ));
730        }
731
732        Ok(Self {
733            bytes: payload,
734            last_ty: None,
735        })
736    }
737
738    fn take_len(&mut self) -> Result<Bytes, UnexpectedEnd> {
739        let len = self.bytes.get_var()?;
740        if len > self.bytes.remaining() as u64 {
741            return Err(UnexpectedEnd);
742        }
743        Ok(self.bytes.split_to(len as usize))
744    }
745
746    fn try_next(&mut self) -> Result<Frame, IterErr> {
747        let ty = self.bytes.get::<FrameType>()?;
748        self.last_ty = Some(ty);
749        Ok(match ty {
750            FrameType::PADDING => Frame::Padding,
751            FrameType::RESET_STREAM => Frame::ResetStream(ResetStream {
752                id: self.bytes.get()?,
753                error_code: self.bytes.get()?,
754                final_offset: self.bytes.get()?,
755            }),
756            FrameType::CONNECTION_CLOSE => Frame::Close(Close::Connection(ConnectionClose {
757                error_code: self.bytes.get()?,
758                frame_type: {
759                    let x = self.bytes.get_var()?;
760                    if x == 0 { None } else { Some(FrameType(x)) }
761                },
762                reason: self.take_len()?,
763            })),
764            FrameType::APPLICATION_CLOSE => Frame::Close(Close::Application(ApplicationClose {
765                error_code: self.bytes.get()?,
766                reason: self.take_len()?,
767            })),
768            FrameType::MAX_DATA => Frame::MaxData(self.bytes.get()?),
769            FrameType::MAX_STREAM_DATA => Frame::MaxStreamData {
770                id: self.bytes.get()?,
771                offset: self.bytes.get_var()?,
772            },
773            FrameType::MAX_STREAMS_BIDI => Frame::MaxStreams {
774                dir: Dir::Bi,
775                count: self.bytes.get_var()?,
776            },
777            FrameType::MAX_STREAMS_UNI => Frame::MaxStreams {
778                dir: Dir::Uni,
779                count: self.bytes.get_var()?,
780            },
781            FrameType::PING => Frame::Ping,
782            FrameType::DATA_BLOCKED => Frame::DataBlocked {
783                offset: self.bytes.get_var()?,
784            },
785            FrameType::STREAM_DATA_BLOCKED => Frame::StreamDataBlocked {
786                id: self.bytes.get()?,
787                offset: self.bytes.get_var()?,
788            },
789            FrameType::STREAMS_BLOCKED_BIDI => Frame::StreamsBlocked {
790                dir: Dir::Bi,
791                limit: self.bytes.get_var()?,
792            },
793            FrameType::STREAMS_BLOCKED_UNI => Frame::StreamsBlocked {
794                dir: Dir::Uni,
795                limit: self.bytes.get_var()?,
796            },
797            FrameType::STOP_SENDING => Frame::StopSending(StopSending {
798                id: self.bytes.get()?,
799                error_code: self.bytes.get()?,
800            }),
801            FrameType::RETIRE_CONNECTION_ID => Frame::RetireConnectionId {
802                sequence: self.bytes.get_var()?,
803            },
804            FrameType::ACK | FrameType::ACK_ECN => {
805                let largest = self.bytes.get_var()?;
806                let delay = self.bytes.get_var()?;
807                let extra_blocks = self.bytes.get_var()? as usize;
808                let n = scan_ack_blocks(&self.bytes, largest, extra_blocks)?;
809                Frame::Ack(Ack {
810                    delay,
811                    largest,
812                    additional: self.bytes.split_to(n),
813                    ecn: if ty != FrameType::ACK_ECN {
814                        None
815                    } else {
816                        Some(EcnCounts {
817                            ect0: self.bytes.get_var()?,
818                            ect1: self.bytes.get_var()?,
819                            ce: self.bytes.get_var()?,
820                        })
821                    },
822                })
823            }
824            FrameType::PATH_CHALLENGE => Frame::PathChallenge(self.bytes.get()?),
825            FrameType::PATH_RESPONSE => Frame::PathResponse(self.bytes.get()?),
826            FrameType::NEW_CONNECTION_ID => {
827                let sequence = self.bytes.get_var()?;
828                let retire_prior_to = self.bytes.get_var()?;
829                if retire_prior_to > sequence {
830                    return Err(IterErr::Malformed);
831                }
832                let length = self.bytes.get::<u8>()? as usize;
833                if length > MAX_CID_SIZE || length == 0 {
834                    return Err(IterErr::Malformed);
835                }
836                if length > self.bytes.remaining() {
837                    return Err(IterErr::UnexpectedEnd);
838                }
839                let mut stage = [0; MAX_CID_SIZE];
840                self.bytes.copy_to_slice(&mut stage[0..length]);
841                let id = ConnectionId::new(&stage[..length]);
842                if self.bytes.remaining() < 16 {
843                    return Err(IterErr::UnexpectedEnd);
844                }
845                let mut reset_token = [0; RESET_TOKEN_SIZE];
846                self.bytes.copy_to_slice(&mut reset_token);
847                Frame::NewConnectionId(NewConnectionId {
848                    sequence,
849                    retire_prior_to,
850                    id,
851                    reset_token: reset_token.into(),
852                })
853            }
854            FrameType::CRYPTO => Frame::Crypto(Crypto {
855                offset: self.bytes.get_var()?,
856                data: self.take_len()?,
857            }),
858            FrameType::NEW_TOKEN => Frame::NewToken(NewToken {
859                token: self.take_len()?,
860            }),
861            FrameType::HANDSHAKE_DONE => Frame::HandshakeDone,
862            FrameType::ACK_FREQUENCY => Frame::AckFrequency(AckFrequency {
863                sequence: self.bytes.get()?,
864                ack_eliciting_threshold: self.bytes.get()?,
865                request_max_ack_delay: self.bytes.get()?,
866                reordering_threshold: self.bytes.get()?,
867            }),
868            FrameType::IMMEDIATE_ACK => Frame::ImmediateAck,
869            FrameType::ADD_ADDRESS_IPV4 => {
870                Frame::AddAddress(AddAddress::decode_auto(&mut self.bytes, false)?)
871            }
872            FrameType::ADD_ADDRESS_IPV6 => {
873                Frame::AddAddress(AddAddress::decode_auto(&mut self.bytes, true)?)
874            }
875            FrameType::PUNCH_ME_NOW_IPV4 => {
876                Frame::PunchMeNow(PunchMeNow::decode_auto(&mut self.bytes, false)?)
877            }
878            FrameType::PUNCH_ME_NOW_IPV6 => {
879                Frame::PunchMeNow(PunchMeNow::decode_auto(&mut self.bytes, true)?)
880            }
881            FrameType::REMOVE_ADDRESS => {
882                // RemoveAddress doesn't have auto decode, uses same format for both
883                Frame::RemoveAddress(RemoveAddress::decode(&mut self.bytes)?)
884            }
885            FrameType::OBSERVED_ADDRESS_IPV4 => {
886                Frame::ObservedAddress(ObservedAddress::decode(&mut self.bytes, false)?)
887            }
888            FrameType::OBSERVED_ADDRESS_IPV6 => {
889                Frame::ObservedAddress(ObservedAddress::decode(&mut self.bytes, true)?)
890            }
891            FrameType::TRY_CONNECT_TO_IPV4 => {
892                Frame::TryConnectTo(TryConnectTo::decode(&mut self.bytes, false)?)
893            }
894            FrameType::TRY_CONNECT_TO_IPV6 => {
895                Frame::TryConnectTo(TryConnectTo::decode(&mut self.bytes, true)?)
896            }
897            FrameType::TRY_CONNECT_TO_RESPONSE_IPV4 => {
898                Frame::TryConnectToResponse(TryConnectToResponse::decode(&mut self.bytes, false)?)
899            }
900            FrameType::TRY_CONNECT_TO_RESPONSE_IPV6 => {
901                Frame::TryConnectToResponse(TryConnectToResponse::decode(&mut self.bytes, true)?)
902            }
903            _ => {
904                if let Some(s) = ty.stream() {
905                    Frame::Stream(Stream {
906                        id: self.bytes.get()?,
907                        offset: if s.off() { self.bytes.get_var()? } else { 0 },
908                        fin: s.fin(),
909                        data: if s.len() {
910                            self.take_len()?
911                        } else {
912                            self.take_remaining()
913                        },
914                    })
915                } else if let Some(d) = ty.datagram() {
916                    Frame::Datagram(Datagram {
917                        data: if d.len() {
918                            self.take_len()?
919                        } else {
920                            self.take_remaining()
921                        },
922                    })
923                } else {
924                    return Err(IterErr::InvalidFrameId);
925                }
926            }
927        })
928    }
929
930    fn take_remaining(&mut self) -> Bytes {
931        mem::take(&mut self.bytes)
932    }
933}
934
935impl Iterator for Iter {
936    type Item = Result<Frame, InvalidFrame>;
937    fn next(&mut self) -> Option<Self::Item> {
938        if !self.bytes.has_remaining() {
939            return None;
940        }
941        match self.try_next() {
942            Ok(x) => Some(Ok(x)),
943            Err(e) => {
944                // Corrupt frame, skip it and everything that follows
945                self.bytes.clear();
946                Some(Err(InvalidFrame {
947                    ty: self.last_ty,
948                    reason: e.reason(),
949                }))
950            }
951        }
952    }
953}
954
955#[derive(Debug)]
956pub(crate) struct InvalidFrame {
957    pub(crate) ty: Option<FrameType>,
958    pub(crate) reason: &'static str,
959}
960
961impl From<InvalidFrame> for TransportError {
962    fn from(err: InvalidFrame) -> Self {
963        let mut te = Self::FRAME_ENCODING_ERROR(err.reason);
964        te.frame = err.ty;
965        te
966    }
967}
968
969/// Validate exactly `n` ACK ranges in `buf` and return the number of bytes they cover
970fn scan_ack_blocks(mut buf: &[u8], largest: u64, n: usize) -> Result<usize, IterErr> {
971    let total_len = buf.remaining();
972    let first_block = buf.get_var()?;
973    let mut smallest = largest.checked_sub(first_block).ok_or(IterErr::Malformed)?;
974    for _ in 0..n {
975        let gap = buf.get_var()?;
976        smallest = smallest.checked_sub(gap + 2).ok_or(IterErr::Malformed)?;
977        let block = buf.get_var()?;
978        smallest = smallest.checked_sub(block).ok_or(IterErr::Malformed)?;
979    }
980    Ok(total_len - buf.remaining())
981}
982
983enum IterErr {
984    UnexpectedEnd,
985    InvalidFrameId,
986    Malformed,
987}
988
989impl IterErr {
990    fn reason(&self) -> &'static str {
991        use IterErr::*;
992        match *self {
993            UnexpectedEnd => "unexpected end",
994            InvalidFrameId => "invalid frame ID",
995            Malformed => "malformed",
996        }
997    }
998}
999
1000impl From<UnexpectedEnd> for IterErr {
1001    fn from(_: UnexpectedEnd) -> Self {
1002        Self::UnexpectedEnd
1003    }
1004}
1005
1006#[derive(Debug, Clone)]
1007pub struct AckIter<'a> {
1008    largest: u64,
1009    data: &'a [u8],
1010}
1011
1012impl<'a> AckIter<'a> {
1013    fn new(largest: u64, data: &'a [u8]) -> Self {
1014        Self { largest, data }
1015    }
1016}
1017
1018impl Iterator for AckIter<'_> {
1019    type Item = RangeInclusive<u64>;
1020    fn next(&mut self) -> Option<RangeInclusive<u64>> {
1021        if !self.data.has_remaining() {
1022            return None;
1023        }
1024        let block = match self.data.get_var() {
1025            Ok(block) => block,
1026            Err(_) => return None,
1027        };
1028        let largest = self.largest;
1029        if let Ok(gap) = self.data.get_var() {
1030            self.largest -= block + gap + 2;
1031        }
1032        Some(largest - block..=largest)
1033    }
1034}
1035
1036#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1037#[derive(Debug, Copy, Clone)]
1038pub struct ResetStream {
1039    pub(crate) id: StreamId,
1040    pub(crate) error_code: VarInt,
1041    pub(crate) final_offset: VarInt,
1042}
1043
1044impl FrameStruct for ResetStream {
1045    const SIZE_BOUND: usize = 1 + 8 + 8 + 8;
1046}
1047
1048impl ResetStream {
1049    #[allow(dead_code)]
1050    pub(crate) fn encode<W: BufMut>(&self, out: &mut W) {
1051        if self.try_encode(out).is_err() {
1052            log_encode_overflow("ResetStream");
1053        }
1054    }
1055
1056    pub(crate) fn try_encode<W: BufMut>(&self, out: &mut W) -> Result<(), VarIntBoundsExceeded> {
1057        FrameType::RESET_STREAM.try_encode(out)?; // 1 byte
1058        out.write(self.id); // <= 8 bytes
1059        out.write_var(self.error_code.into_inner())?; // <= 8 bytes
1060        out.write_var(self.final_offset.into_inner())?; // <= 8 bytes
1061        Ok(())
1062    }
1063}
1064
1065#[derive(Debug, Copy, Clone)]
1066pub(crate) struct StopSending {
1067    pub(crate) id: StreamId,
1068    pub(crate) error_code: VarInt,
1069}
1070
1071impl FrameStruct for StopSending {
1072    const SIZE_BOUND: usize = 1 + 8 + 8;
1073}
1074
1075impl StopSending {
1076    #[allow(dead_code)]
1077    pub(crate) fn encode<W: BufMut>(&self, out: &mut W) {
1078        if self.try_encode(out).is_err() {
1079            log_encode_overflow("StopSending");
1080        }
1081    }
1082
1083    pub(crate) fn try_encode<W: BufMut>(&self, out: &mut W) -> Result<(), VarIntBoundsExceeded> {
1084        FrameType::STOP_SENDING.try_encode(out)?; // 1 byte
1085        out.write(self.id); // <= 8 bytes
1086        out.write_var(self.error_code.into_inner())?; // <= 8 bytes
1087        Ok(())
1088    }
1089}
1090
1091#[derive(Debug, Copy, Clone)]
1092pub(crate) struct NewConnectionId {
1093    pub(crate) sequence: u64,
1094    pub(crate) retire_prior_to: u64,
1095    pub(crate) id: ConnectionId,
1096    pub(crate) reset_token: ResetToken,
1097}
1098
1099impl NewConnectionId {
1100    #[allow(dead_code)]
1101    pub(crate) fn encode<W: BufMut>(&self, out: &mut W) {
1102        if self.try_encode(out).is_err() {
1103            log_encode_overflow("NewConnectionId");
1104        }
1105    }
1106
1107    pub(crate) fn try_encode<W: BufMut>(&self, out: &mut W) -> Result<(), VarIntBoundsExceeded> {
1108        FrameType::NEW_CONNECTION_ID.try_encode(out)?;
1109        out.write_var(self.sequence)?;
1110        out.write_var(self.retire_prior_to)?;
1111        out.write(self.id.len() as u8);
1112        out.put_slice(&self.id);
1113        out.put_slice(&self.reset_token);
1114        Ok(())
1115    }
1116}
1117
1118/// Smallest number of bytes this type of frame is guaranteed to fit within.
1119pub(crate) const RETIRE_CONNECTION_ID_SIZE_BOUND: usize = 9;
1120
1121/// An unreliable datagram
1122#[derive(Debug, Clone)]
1123pub struct Datagram {
1124    /// Payload
1125    pub data: Bytes,
1126}
1127
1128impl FrameStruct for Datagram {
1129    const SIZE_BOUND: usize = 1 + 8;
1130}
1131
1132impl Datagram {
1133    pub(crate) fn encode(&self, length: bool, out: &mut Vec<u8>) {
1134        if self.try_encode(length, out).is_err() {
1135            log_encode_overflow("Datagram");
1136        }
1137    }
1138
1139    pub(crate) fn try_encode(
1140        &self,
1141        length: bool,
1142        out: &mut Vec<u8>,
1143    ) -> Result<(), VarIntBoundsExceeded> {
1144        FrameType(*DATAGRAM_TYS.start() | u64::from(length)).try_encode(out)?; // 1 byte
1145        if length {
1146            out.write_var(self.data.len() as u64)?; // <= 8 bytes
1147        }
1148        out.extend_from_slice(&self.data);
1149        Ok(())
1150    }
1151
1152    pub(crate) fn size(&self, length: bool) -> usize {
1153        1 + if length {
1154            VarInt::from_u64_bounded(self.data.len() as u64).size()
1155        } else {
1156            0
1157        } + self.data.len()
1158    }
1159}
1160
1161#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1162pub(crate) struct AckFrequency {
1163    pub(crate) sequence: VarInt,
1164    pub(crate) ack_eliciting_threshold: VarInt,
1165    pub(crate) request_max_ack_delay: VarInt,
1166    pub(crate) reordering_threshold: VarInt,
1167}
1168
1169impl AckFrequency {
1170    #[allow(dead_code)]
1171    pub(crate) fn encode<W: BufMut>(&self, buf: &mut W) {
1172        if self.try_encode(buf).is_err() {
1173            log_encode_overflow("AckFrequency");
1174        }
1175    }
1176
1177    pub(crate) fn try_encode<W: BufMut>(&self, buf: &mut W) -> Result<(), VarIntBoundsExceeded> {
1178        FrameType::ACK_FREQUENCY.try_encode(buf)?;
1179        buf.write_var(self.sequence.into_inner())?;
1180        buf.write_var(self.ack_eliciting_threshold.into_inner())?;
1181        buf.write_var(self.request_max_ack_delay.into_inner())?;
1182        buf.write_var(self.reordering_threshold.into_inner())?;
1183        Ok(())
1184    }
1185}
1186
1187// Re-export unified NAT traversal frames
1188pub(crate) use nat_traversal_unified::{
1189    AddAddress, PunchMeNow, RemoveAddress, TryConnectError, TryConnectTo, TryConnectToResponse,
1190};
1191
1192/// Address Discovery frame for informing peers of their observed address
1193/// draft-ietf-quic-address-discovery-00
1194#[derive(Debug, Clone, PartialEq, Eq)]
1195pub(crate) struct ObservedAddress {
1196    /// Monotonically increasing sequence number
1197    pub(crate) sequence_number: VarInt,
1198    /// The socket address observed by the sender
1199    pub(crate) address: SocketAddr,
1200}
1201
1202impl ObservedAddress {
1203    #[allow(dead_code)]
1204    pub(crate) fn encode<W: BufMut>(&self, buf: &mut W) {
1205        if self.try_encode(buf).is_err() {
1206            log_encode_overflow("ObservedAddress");
1207        }
1208    }
1209
1210    pub(crate) fn try_encode<W: BufMut>(&self, buf: &mut W) -> Result<(), VarIntBoundsExceeded> {
1211        match self.address {
1212            SocketAddr::V4(_) => FrameType::OBSERVED_ADDRESS_IPV4.try_encode(buf)?,
1213            SocketAddr::V6(_) => FrameType::OBSERVED_ADDRESS_IPV6.try_encode(buf)?,
1214        };
1215
1216        // Write sequence number as varint
1217        buf.write_var(self.sequence_number.0)?;
1218
1219        // Write address and port directly (no IP version byte needed)
1220        match self.address {
1221            SocketAddr::V4(addr) => {
1222                buf.put_slice(&addr.ip().octets());
1223                buf.put_u16(addr.port());
1224            }
1225            SocketAddr::V6(addr) => {
1226                buf.put_slice(&addr.ip().octets());
1227                buf.put_u16(addr.port());
1228            }
1229        }
1230        Ok(())
1231    }
1232
1233    pub(crate) fn decode<R: Buf>(r: &mut R, is_ipv6: bool) -> Result<Self, UnexpectedEnd> {
1234        // Read sequence number first
1235        let sequence_number = VarInt::from_u64(r.get_var()?).map_err(|_| UnexpectedEnd)?;
1236
1237        // Decode address based on frame type (no IP version byte)
1238        let address = if is_ipv6 {
1239            if r.remaining() < 18 {
1240                return Err(UnexpectedEnd);
1241            }
1242            let mut octets = [0u8; 16];
1243            r.copy_to_slice(&mut octets);
1244            let port = r.get::<u16>()?;
1245            SocketAddr::new(octets.into(), port)
1246        } else {
1247            if r.remaining() < 6 {
1248                return Err(UnexpectedEnd);
1249            }
1250            let mut octets = [0u8; 4];
1251            r.copy_to_slice(&mut octets);
1252            let port = r.get::<u16>()?;
1253            SocketAddr::new(octets.into(), port)
1254        };
1255
1256        Ok(Self {
1257            sequence_number,
1258            address,
1259        })
1260    }
1261}
1262
1263#[doc(hidden)]
1264pub fn encode_observed_address_frame(
1265    sequence_number: VarInt,
1266    address: SocketAddr,
1267) -> Result<Vec<u8>, &'static str> {
1268    let mut buf = Vec::with_capacity(ObservedAddress::SIZE_BOUND);
1269    ObservedAddress {
1270        sequence_number,
1271        address,
1272    }
1273    .try_encode(&mut buf)
1274    .map_err(|_| "observed address frame encode overflow")?;
1275    Ok(buf)
1276}
1277
1278#[doc(hidden)]
1279pub fn decode_observed_address_frame(payload: &[u8]) -> Result<(VarInt, SocketAddr), &'static str> {
1280    let mut iter =
1281        Iter::new(Bytes::copy_from_slice(payload)).map_err(|_| "invalid frame payload")?;
1282    let frame = iter
1283        .next()
1284        .ok_or("missing observed address frame")?
1285        .map_err(|_| "invalid observed address frame")?;
1286
1287    if iter.next().is_some() {
1288        return Err("unexpected trailing frame data");
1289    }
1290
1291    match frame {
1292        Frame::ObservedAddress(observed) => Ok((observed.sequence_number, observed.address)),
1293        _ => Err("frame is not an observed address frame"),
1294    }
1295}
1296
1297impl FrameStruct for ObservedAddress {
1298    const SIZE_BOUND: usize = 4 + 8 + 16 + 2; // frame type (4) + sequence (8) + IPv6 + port
1299}
1300
1301#[cfg(test)]
1302mod test {
1303    use super::*;
1304    use crate::coding::Codec;
1305    use assert_matches::assert_matches;
1306
1307    fn frames(buf: Vec<u8>) -> Vec<Frame> {
1308        Iter::new(Bytes::from(buf))
1309            .unwrap()
1310            .collect::<Result<Vec<_>, _>>()
1311            .unwrap()
1312    }
1313
1314    #[test]
1315    fn ack_coding() {
1316        const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14];
1317        let mut ranges = ArrayRangeSet::new();
1318        for &packet in PACKETS {
1319            ranges.insert(packet..packet + 1);
1320        }
1321        let mut buf = Vec::new();
1322        const ECN: EcnCounts = EcnCounts {
1323            ect0: 42,
1324            ect1: 24,
1325            ce: 12,
1326        };
1327        Ack::encode(42, &ranges, Some(&ECN), &mut buf);
1328        let frames = frames(buf);
1329        assert_eq!(frames.len(), 1);
1330        match frames[0] {
1331            Frame::Ack(ref ack) => {
1332                let mut packets = ack.iter().flatten().collect::<Vec<_>>();
1333                packets.sort_unstable();
1334                assert_eq!(&packets[..], PACKETS);
1335                assert_eq!(ack.ecn, Some(ECN));
1336            }
1337            ref x => panic!("incorrect frame {x:?}"),
1338        }
1339    }
1340
1341    #[test]
1342    fn ack_frequency_coding() {
1343        let mut buf = Vec::new();
1344        let original = AckFrequency {
1345            sequence: VarInt(42),
1346            ack_eliciting_threshold: VarInt(20),
1347            request_max_ack_delay: VarInt(50_000),
1348            reordering_threshold: VarInt(1),
1349        };
1350        original.encode(&mut buf);
1351        let frames = frames(buf);
1352        assert_eq!(frames.len(), 1);
1353        match &frames[0] {
1354            Frame::AckFrequency(decoded) => assert_eq!(decoded, &original),
1355            x => panic!("incorrect frame {x:?}"),
1356        }
1357    }
1358
1359    #[test]
1360    fn immediate_ack_coding() {
1361        let mut buf = Vec::new();
1362        FrameType::IMMEDIATE_ACK.encode(&mut buf);
1363        let frames = frames(buf);
1364        assert_eq!(frames.len(), 1);
1365        assert_matches!(&frames[0], Frame::ImmediateAck);
1366    }
1367
1368    #[test]
1369    fn add_address_ipv4_coding() {
1370        let mut buf = Vec::new();
1371        let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
1372        let original = AddAddress {
1373            sequence: VarInt(42),
1374            address: addr,
1375            priority: VarInt(100),
1376        };
1377        // Use RFC encoding to match the decoder expectations
1378        original.encode_rfc(&mut buf);
1379        let frames = frames(buf);
1380        assert_eq!(frames.len(), 1);
1381        match &frames[0] {
1382            Frame::AddAddress(decoded) => {
1383                assert_eq!(decoded.sequence, original.sequence);
1384                assert_eq!(decoded.address, original.address);
1385                // Priority is not encoded in RFC format
1386            }
1387            x => panic!("incorrect frame {x:?}"),
1388        }
1389    }
1390
1391    #[test]
1392    fn add_address_ipv6_coding() {
1393        let mut buf = Vec::new();
1394        let addr = SocketAddr::from(([0, 0, 0, 0, 0, 0, 0, 1], 8080));
1395        let original = AddAddress {
1396            sequence: VarInt(123),
1397            address: addr,
1398            priority: VarInt(200),
1399        };
1400        // Use RFC encoding to match the decoder expectations
1401        original.encode_rfc(&mut buf);
1402        let frames = frames(buf);
1403        assert_eq!(frames.len(), 1);
1404        match &frames[0] {
1405            Frame::AddAddress(decoded) => {
1406                assert_eq!(decoded.sequence, original.sequence);
1407                assert_eq!(decoded.address, original.address);
1408                // Priority is not encoded in RFC format
1409            }
1410            x => panic!("incorrect frame {x:?}"),
1411        }
1412    }
1413
1414    #[test]
1415    fn punch_me_now_ipv4_coding() {
1416        let mut buf = Vec::new();
1417        let addr = SocketAddr::from(([192, 168, 1, 1], 9000));
1418        let original = PunchMeNow {
1419            round: VarInt(1),
1420            paired_with_sequence_number: VarInt(42),
1421            address: addr,
1422            target_peer_id: None,
1423        };
1424        // Use RFC encoding to match the decoder expectations
1425        original.encode_rfc(&mut buf);
1426        let frames = frames(buf);
1427        assert_eq!(frames.len(), 1);
1428        match &frames[0] {
1429            Frame::PunchMeNow(decoded) => {
1430                assert_eq!(decoded.round, original.round);
1431                assert_eq!(
1432                    decoded.paired_with_sequence_number,
1433                    original.paired_with_sequence_number
1434                );
1435                assert_eq!(decoded.address, original.address);
1436            }
1437            x => panic!("incorrect frame {x:?}"),
1438        }
1439    }
1440
1441    #[test]
1442    fn punch_me_now_ipv6_coding() {
1443        let mut buf = Vec::new();
1444        let addr = SocketAddr::from(([0xfe80, 0, 0, 0, 0, 0, 0, 1], 9000));
1445        let original = PunchMeNow {
1446            round: VarInt(2),
1447            paired_with_sequence_number: VarInt(100),
1448            address: addr,
1449            target_peer_id: None,
1450        };
1451        // Use RFC encoding to match the decoder expectations
1452        original.encode_rfc(&mut buf);
1453        let frames = frames(buf);
1454        assert_eq!(frames.len(), 1);
1455        match &frames[0] {
1456            Frame::PunchMeNow(decoded) => {
1457                assert_eq!(decoded.round, original.round);
1458                assert_eq!(
1459                    decoded.paired_with_sequence_number,
1460                    original.paired_with_sequence_number
1461                );
1462                assert_eq!(decoded.address, original.address);
1463            }
1464            x => panic!("incorrect frame {x:?}"),
1465        }
1466    }
1467
1468    #[test]
1469    fn remove_address_coding() {
1470        let mut buf = Vec::new();
1471        let original = RemoveAddress {
1472            sequence: VarInt(42),
1473        };
1474        original.encode(&mut buf);
1475        let frames = frames(buf);
1476        assert_eq!(frames.len(), 1);
1477        match &frames[0] {
1478            Frame::RemoveAddress(decoded) => {
1479                assert_eq!(decoded.sequence, original.sequence);
1480            }
1481            x => panic!("incorrect frame {x:?}"),
1482        }
1483    }
1484
1485    #[test]
1486    fn nat_traversal_frame_size_bounds() {
1487        // Test that the SIZE_BOUND constants are correct
1488        let mut buf = Vec::new();
1489
1490        // AddAddress with IPv6 (worst case)
1491        let addr = AddAddress {
1492            sequence: VarInt::MAX,
1493            address: SocketAddr::from(([0xffff; 8], 65535)),
1494            priority: VarInt::MAX,
1495        };
1496        addr.encode(&mut buf);
1497        assert!(buf.len() <= AddAddress::SIZE_BOUND);
1498        buf.clear();
1499
1500        // PunchMeNow with IPv6 (worst case)
1501        let punch = PunchMeNow {
1502            round: VarInt::MAX,
1503            paired_with_sequence_number: VarInt::MAX,
1504            address: SocketAddr::from(([0xffff; 8], 65535)),
1505            target_peer_id: Some([0xff; 32]),
1506        };
1507        punch.encode(&mut buf);
1508        assert!(buf.len() <= PunchMeNow::SIZE_BOUND);
1509        buf.clear();
1510
1511        // RemoveAddress
1512        let remove = RemoveAddress {
1513            sequence: VarInt::MAX,
1514        };
1515        remove.encode(&mut buf);
1516        assert!(buf.len() <= RemoveAddress::SIZE_BOUND);
1517    }
1518
1519    #[test]
1520    fn punch_me_now_with_target_peer_id() {
1521        // Note: target_peer_id is only supported in legacy format, not RFC format
1522        // This test verifies the legacy format can be encoded, but when decoded
1523        // through the standard frame decoder, target_peer_id won't be preserved
1524        // (as it's not part of the RFC format)
1525        let mut buf = Vec::new();
1526        let target_peer_id = [0x42; 32]; // Test peer ID
1527        let addr = SocketAddr::from(([192, 168, 1, 100], 12345));
1528        let original = PunchMeNow {
1529            round: VarInt(5),
1530            paired_with_sequence_number: VarInt(999),
1531            address: addr,
1532            target_peer_id: Some(target_peer_id),
1533        };
1534        // Use RFC encoding which doesn't include target_peer_id
1535        original.encode_rfc(&mut buf);
1536        let frames = frames(buf);
1537        assert_eq!(frames.len(), 1);
1538        match &frames[0] {
1539            Frame::PunchMeNow(decoded) => {
1540                assert_eq!(decoded.round, original.round);
1541                assert_eq!(
1542                    decoded.paired_with_sequence_number,
1543                    original.paired_with_sequence_number
1544                );
1545                assert_eq!(decoded.address, original.address);
1546                // RFC format doesn't support target_peer_id
1547                assert_eq!(decoded.target_peer_id, None);
1548            }
1549            x => panic!("incorrect frame {x:?}"),
1550        }
1551    }
1552
1553    #[test]
1554    fn nat_traversal_frame_edge_cases() {
1555        // Test minimum values
1556        let mut buf = Vec::new();
1557
1558        // AddAddress with minimum values
1559        let min_addr = AddAddress {
1560            sequence: VarInt(0),
1561            address: SocketAddr::from(([0, 0, 0, 0], 0)),
1562            priority: VarInt(0),
1563        };
1564        min_addr.encode_rfc(&mut buf);
1565        let frames1 = frames(buf.clone());
1566        assert_eq!(frames1.len(), 1);
1567        buf.clear();
1568
1569        // PunchMeNow with minimum values
1570        let min_punch = PunchMeNow {
1571            round: VarInt(0),
1572            paired_with_sequence_number: VarInt(0),
1573            address: SocketAddr::from(([0, 0, 0, 0], 0)),
1574            target_peer_id: None,
1575        };
1576        min_punch.encode_rfc(&mut buf);
1577        let frames2 = frames(buf.clone());
1578        assert_eq!(frames2.len(), 1);
1579        buf.clear();
1580
1581        // RemoveAddress with minimum values
1582        let min_remove = RemoveAddress {
1583            sequence: VarInt(0),
1584        };
1585        min_remove.encode(&mut buf);
1586        let frames3 = frames(buf);
1587        assert_eq!(frames3.len(), 1);
1588    }
1589
1590    #[test]
1591    fn nat_traversal_frame_boundary_values() {
1592        // Test VarInt boundary values
1593        let mut buf = Vec::new();
1594
1595        // Test VarInt boundary values for AddAddress
1596        let boundary_values = [
1597            VarInt(0),
1598            VarInt(63),         // Maximum 1-byte VarInt
1599            VarInt(64),         // Minimum 2-byte VarInt
1600            VarInt(16383),      // Maximum 2-byte VarInt
1601            VarInt(16384),      // Minimum 4-byte VarInt
1602            VarInt(1073741823), // Maximum 4-byte VarInt
1603            VarInt(1073741824), // Minimum 8-byte VarInt
1604        ];
1605
1606        for &sequence in &boundary_values {
1607            for &priority in &boundary_values {
1608                let addr = AddAddress {
1609                    sequence,
1610                    address: SocketAddr::from(([127, 0, 0, 1], 8080)),
1611                    priority,
1612                };
1613                addr.encode_rfc(&mut buf);
1614                let parsed_frames = frames(buf.clone());
1615                assert_eq!(parsed_frames.len(), 1);
1616                match &parsed_frames[0] {
1617                    Frame::AddAddress(decoded) => {
1618                        assert_eq!(decoded.sequence, sequence);
1619                        // Priority not encoded in RFC format
1620                    }
1621                    x => panic!("incorrect frame {x:?}"),
1622                }
1623                buf.clear();
1624            }
1625        }
1626    }
1627
1628    #[test]
1629    fn nat_traversal_frame_error_handling() {
1630        // Test malformed frame data
1631        let malformed_frames = vec![
1632            // Too short for any NAT traversal frame (4-byte frame types)
1633            vec![0xc0, 0x90, 0xf9, 0x0f], // Just ADD_ADDRESS_IPV4 frame type, no data
1634            vec![0xc0, 0x92, 0xf9, 0x0f], // Just PUNCH_ME_NOW_IPV4 frame type, no data
1635            vec![0xc0, 0x94, 0xf9, 0x0f], // Just REMOVE_ADDRESS frame type, no data
1636            // Incomplete AddAddress frames
1637            vec![0xc0, 0x90, 0xf9, 0x0f, 0x01], // Frame type + partial sequence
1638            vec![0xc0, 0x90, 0xf9, 0x0f, 0x01, 0x04], // Frame type + sequence + incomplete
1639            // Incomplete PunchMeNow frames
1640            vec![0xc0, 0x92, 0xf9, 0x0f, 0x01], // Frame type + partial round
1641            vec![0xc0, 0x92, 0xf9, 0x0f, 0x01, 0x02], // Frame type + round + partial
1642            // Incomplete RemoveAddress frames
1643            // RemoveAddress is actually hard to make malformed since it only has sequence
1644
1645            // Invalid IP address types
1646            vec![0xc0, 0x90, 0xf9, 0x0f, 0x01, 0x99, 0x01, 0x02, 0x03, 0x04], // Invalid
1647        ];
1648
1649        for malformed in malformed_frames {
1650            let result = Iter::new(Bytes::from(malformed)).unwrap().next();
1651            if let Some(frame_result) = result {
1652                // Should either parse successfully (for valid but incomplete data)
1653                // or return an error (for truly malformed data)
1654                match frame_result {
1655                    Ok(_) => {}  // Valid frame parsed
1656                    Err(_) => {} // Expected error for malformed data
1657                }
1658            }
1659        }
1660    }
1661
1662    #[test]
1663    fn nat_traversal_frame_roundtrip_consistency() {
1664        // Test that encoding and then decoding produces identical frames
1665
1666        // Test AddAddress frames
1667        let add_test_cases = vec![
1668            AddAddress {
1669                sequence: VarInt(42),
1670                address: SocketAddr::from(([127, 0, 0, 1], 8080)),
1671                priority: VarInt(100),
1672            },
1673            AddAddress {
1674                sequence: VarInt(1000),
1675                address: SocketAddr::from(([0, 0, 0, 0, 0, 0, 0, 1], 443)),
1676                priority: VarInt(255),
1677            },
1678        ];
1679
1680        for original_add in add_test_cases {
1681            let mut buf = Vec::new();
1682            original_add.encode_rfc(&mut buf);
1683
1684            let decoded_frames = frames(buf);
1685            assert_eq!(decoded_frames.len(), 1);
1686
1687            match &decoded_frames[0] {
1688                Frame::AddAddress(decoded) => {
1689                    assert_eq!(original_add.sequence, decoded.sequence);
1690                    assert_eq!(original_add.address, decoded.address);
1691                    // Priority not encoded in RFC format
1692                }
1693                _ => panic!("Expected AddAddress frame"),
1694            }
1695        }
1696
1697        // Test PunchMeNow frames
1698        let punch_test_cases = vec![
1699            PunchMeNow {
1700                round: VarInt(1),
1701                paired_with_sequence_number: VarInt(42),
1702                address: SocketAddr::from(([192, 168, 1, 1], 9000)),
1703                target_peer_id: None,
1704            },
1705            PunchMeNow {
1706                round: VarInt(10),
1707                paired_with_sequence_number: VarInt(500),
1708                address: SocketAddr::from(([2001, 0xdb8, 0, 0, 0, 0, 0, 1], 12345)),
1709                target_peer_id: Some([0xaa; 32]),
1710            },
1711        ];
1712
1713        for original_punch in punch_test_cases {
1714            let mut buf = Vec::new();
1715            original_punch.encode_rfc(&mut buf);
1716
1717            let decoded_frames = frames(buf);
1718            assert_eq!(decoded_frames.len(), 1);
1719
1720            match &decoded_frames[0] {
1721                Frame::PunchMeNow(decoded) => {
1722                    assert_eq!(original_punch.round, decoded.round);
1723                    assert_eq!(
1724                        original_punch.paired_with_sequence_number,
1725                        decoded.paired_with_sequence_number
1726                    );
1727                    assert_eq!(original_punch.address, decoded.address);
1728                    // RFC format doesn't support target_peer_id, so it should always be None
1729                    assert_eq!(decoded.target_peer_id, None);
1730                }
1731                _ => panic!("Expected PunchMeNow frame"),
1732            }
1733        }
1734
1735        // Test RemoveAddress frames
1736        let remove_test_cases = vec![
1737            RemoveAddress {
1738                sequence: VarInt(123),
1739            },
1740            RemoveAddress {
1741                sequence: VarInt(0),
1742            },
1743        ];
1744
1745        for original_remove in remove_test_cases {
1746            let mut buf = Vec::new();
1747            original_remove.encode(&mut buf);
1748
1749            let decoded_frames = frames(buf);
1750            assert_eq!(decoded_frames.len(), 1);
1751
1752            match &decoded_frames[0] {
1753                Frame::RemoveAddress(decoded) => {
1754                    assert_eq!(original_remove.sequence, decoded.sequence);
1755                }
1756                _ => panic!("Expected RemoveAddress frame"),
1757            }
1758        }
1759    }
1760
1761    #[test]
1762    fn nat_traversal_frame_type_constants() {
1763        // Verify that the frame type constants match the NAT traversal draft specification
1764        assert_eq!(FrameType::ADD_ADDRESS_IPV4.0, 0x3d7e90);
1765        assert_eq!(FrameType::ADD_ADDRESS_IPV6.0, 0x3d7e91);
1766        assert_eq!(FrameType::PUNCH_ME_NOW_IPV4.0, 0x3d7e92);
1767        assert_eq!(FrameType::PUNCH_ME_NOW_IPV6.0, 0x3d7e93);
1768        assert_eq!(FrameType::REMOVE_ADDRESS.0, 0x3d7e94);
1769    }
1770
1771    #[test]
1772    fn observed_address_frame_encoding() {
1773        use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
1774
1775        // Test IPv4 address encoding/decoding
1776        let ipv4_cases = vec![
1777            ObservedAddress {
1778                sequence_number: VarInt::from_u32(1),
1779                address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)), 8080),
1780            },
1781            ObservedAddress {
1782                sequence_number: VarInt::from_u32(2),
1783                address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)), 443),
1784            },
1785            ObservedAddress {
1786                sequence_number: VarInt::from_u32(3),
1787                address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 65535),
1788            },
1789        ];
1790
1791        for original in ipv4_cases {
1792            let mut buf = Vec::new();
1793            original.encode(&mut buf);
1794
1795            let decoded_frames = frames(buf);
1796            assert_eq!(decoded_frames.len(), 1);
1797
1798            match &decoded_frames[0] {
1799                Frame::ObservedAddress(decoded) => {
1800                    assert_eq!(original.address, decoded.address);
1801                }
1802                _ => panic!("Expected ObservedAddress frame"),
1803            }
1804        }
1805
1806        // Test IPv6 address encoding/decoding
1807        let ipv6_cases = vec![
1808            ObservedAddress {
1809                sequence_number: VarInt::from_u32(4),
1810                address: SocketAddr::new(
1811                    IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)),
1812                    8080,
1813                ),
1814            },
1815            ObservedAddress {
1816                sequence_number: VarInt::from_u32(5),
1817                address: SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 443),
1818            },
1819            ObservedAddress {
1820                sequence_number: VarInt::from_u32(6),
1821                address: SocketAddr::new(
1822                    IpAddr::V6(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)),
1823                    65535,
1824                ),
1825            },
1826        ];
1827
1828        for original in ipv6_cases {
1829            let mut buf = Vec::new();
1830            original.encode(&mut buf);
1831
1832            let decoded_frames = frames(buf);
1833            assert_eq!(decoded_frames.len(), 1);
1834
1835            match &decoded_frames[0] {
1836                Frame::ObservedAddress(decoded) => {
1837                    assert_eq!(original.address, decoded.address);
1838                }
1839                _ => panic!("Expected ObservedAddress frame"),
1840            }
1841        }
1842    }
1843
1844    #[test]
1845    fn observed_address_malformed_frames() {
1846        use crate::coding::BufMutExt;
1847        use bytes::BufMut;
1848
1849        // Test truncated sequence number
1850        let mut buf = Vec::new();
1851        // Use IPv4 variant for test
1852        buf.write(FrameType::OBSERVED_ADDRESS_IPV4);
1853        // No sequence number, just go straight to address - this is invalid
1854
1855        let result = Iter::new(Bytes::from(buf));
1856        assert!(result.is_ok());
1857        let mut iter = result.unwrap();
1858        let frame_result = iter.next();
1859        assert!(frame_result.is_some());
1860        assert!(frame_result.unwrap().is_err());
1861
1862        // Test truncated IPv4 address
1863        let mut buf = Vec::new();
1864        // Use IPv4 variant for test
1865        buf.write(FrameType::OBSERVED_ADDRESS_IPV4);
1866        buf.put_u8(4); // IPv4
1867        buf.put_slice(&[192, 168]); // Only 2 bytes instead of 4
1868
1869        let result = Iter::new(Bytes::from(buf));
1870        assert!(result.is_ok());
1871        let mut iter = result.unwrap();
1872        let frame_result = iter.next();
1873        assert!(frame_result.is_some());
1874        assert!(frame_result.unwrap().is_err());
1875
1876        // Test truncated IPv6 address
1877        let mut buf = Vec::new();
1878        // Use IPv6 variant for test
1879        buf.write(FrameType::OBSERVED_ADDRESS_IPV6);
1880        buf.write_var_or_debug_assert(1); // sequence number
1881        buf.put_slice(&[0x20, 0x01, 0x0d, 0xb8]); // Only 4 bytes instead of 16
1882
1883        let result = Iter::new(Bytes::from(buf));
1884        assert!(result.is_ok());
1885        let mut iter = result.unwrap();
1886        let frame_result = iter.next();
1887        assert!(frame_result.is_some());
1888        assert!(frame_result.unwrap().is_err());
1889    }
1890
1891    #[test]
1892    fn observed_address_frame_type_constant() {
1893        // Verify that the frame type constant matches the address discovery draft
1894        assert_eq!(FrameType::OBSERVED_ADDRESS_IPV4.0, 0x9f81a6);
1895        assert_eq!(FrameType::OBSERVED_ADDRESS_IPV6.0, 0x9f81a7);
1896    }
1897
1898    #[test]
1899    fn observed_address_frame_serialization_edge_cases() {
1900        use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
1901
1902        // Test with port 0
1903        let frame_port_0 = ObservedAddress {
1904            sequence_number: VarInt::from_u32(100),
1905            address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)), 0),
1906        };
1907        let mut buf = Vec::new();
1908        frame_port_0.encode(&mut buf);
1909        let decoded_frames = frames(buf);
1910        assert_eq!(decoded_frames.len(), 1);
1911        match &decoded_frames[0] {
1912            Frame::ObservedAddress(decoded) => {
1913                assert_eq!(frame_port_0.address, decoded.address);
1914                assert_eq!(decoded.address.port(), 0);
1915            }
1916            _ => panic!("Expected ObservedAddress frame"),
1917        }
1918
1919        // Test with maximum port
1920        let frame_max_port = ObservedAddress {
1921            sequence_number: VarInt::from_u32(101),
1922            address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)), 65535),
1923        };
1924        let mut buf = Vec::new();
1925        frame_max_port.encode(&mut buf);
1926        let decoded_frames = frames(buf);
1927        assert_eq!(decoded_frames.len(), 1);
1928        match &decoded_frames[0] {
1929            Frame::ObservedAddress(decoded) => {
1930                assert_eq!(frame_max_port.address, decoded.address);
1931                assert_eq!(decoded.address.port(), 65535);
1932            }
1933            _ => panic!("Expected ObservedAddress frame"),
1934        }
1935
1936        // Test with unspecified addresses
1937        let unspecified_v4 = ObservedAddress {
1938            sequence_number: VarInt::from_u32(102),
1939            address: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 8080),
1940        };
1941        let mut buf = Vec::new();
1942        unspecified_v4.encode(&mut buf);
1943        let decoded_frames = frames(buf);
1944        assert_eq!(decoded_frames.len(), 1);
1945        match &decoded_frames[0] {
1946            Frame::ObservedAddress(decoded) => {
1947                assert_eq!(unspecified_v4.address, decoded.address);
1948                assert_eq!(decoded.address.ip(), IpAddr::V4(Ipv4Addr::UNSPECIFIED));
1949            }
1950            _ => panic!("Expected ObservedAddress frame"),
1951        }
1952
1953        let unspecified_v6 = ObservedAddress {
1954            sequence_number: VarInt::from_u32(103),
1955            address: SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 443),
1956        };
1957        let mut buf = Vec::new();
1958        unspecified_v6.encode(&mut buf);
1959        let decoded_frames = frames(buf);
1960        assert_eq!(decoded_frames.len(), 1);
1961        match &decoded_frames[0] {
1962            Frame::ObservedAddress(decoded) => {
1963                assert_eq!(unspecified_v6.address, decoded.address);
1964                assert_eq!(decoded.address.ip(), IpAddr::V6(Ipv6Addr::UNSPECIFIED));
1965            }
1966            _ => panic!("Expected ObservedAddress frame"),
1967        }
1968    }
1969
1970    #[test]
1971    fn observed_address_frame_size_compliance() {
1972        use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
1973
1974        // Test that frame sizes are reasonable and within expected bounds
1975        let test_addresses = vec![
1976            ObservedAddress {
1977                sequence_number: VarInt::from_u32(1),
1978                address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)), 8080),
1979            },
1980            ObservedAddress {
1981                sequence_number: VarInt::from_u32(2),
1982                address: SocketAddr::new(
1983                    IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)),
1984                    443,
1985                ),
1986            },
1987        ];
1988
1989        for frame in test_addresses {
1990            let mut buf = Vec::new();
1991            frame.encode(&mut buf);
1992
1993            // Frame type (4 bytes) + sequence (1 byte for small values) + address + port (2 bytes)
1994            // IPv4: 4 + 1 + 4 + 2 = 11 bytes
1995            // IPv6: 4 + 1 + 16 + 2 = 23 bytes
1996            match frame.address.ip() {
1997                IpAddr::V4(_) => {
1998                    assert!(
1999                        buf.len() == 11,
2000                        "IPv4 frame size {} out of expected range",
2001                        buf.len()
2002                    );
2003                }
2004                IpAddr::V6(_) => {
2005                    assert!(
2006                        buf.len() == 23,
2007                        "IPv6 frame size {} out of expected range",
2008                        buf.len()
2009                    );
2010                }
2011            }
2012        }
2013    }
2014
2015    #[test]
2016    fn observed_address_multiple_frames_in_packet() {
2017        use crate::coding::BufMutExt;
2018        use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
2019
2020        // Test that multiple OBSERVED_ADDRESS frames can be encoded/decoded in a single packet
2021        let observed1 = ObservedAddress {
2022            sequence_number: VarInt::from_u32(10),
2023            address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)), 1234),
2024        };
2025        let observed2 = ObservedAddress {
2026            sequence_number: VarInt::from_u32(11),
2027            address: SocketAddr::new(
2028                IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2)),
2029                5678,
2030            ),
2031        };
2032
2033        let mut buf = Vec::new();
2034        // Encode first ObservedAddress frame
2035        observed1.encode(&mut buf);
2036        // Encode PING frame
2037        buf.write(FrameType::PING);
2038        // Encode second ObservedAddress frame
2039        observed2.encode(&mut buf);
2040        // Padding frame is just zeros, no special encoding needed
2041        buf.push(0); // PADDING frame type
2042
2043        let decoded_frames = frames(buf);
2044        assert_eq!(decoded_frames.len(), 4);
2045
2046        // Verify each frame matches
2047        match &decoded_frames[0] {
2048            Frame::ObservedAddress(dec) => {
2049                assert_eq!(observed1.address, dec.address);
2050            }
2051            _ => panic!("Expected ObservedAddress at position 0"),
2052        }
2053
2054        match &decoded_frames[1] {
2055            Frame::Ping => {}
2056            _ => panic!("Expected Ping at position 1"),
2057        }
2058
2059        match &decoded_frames[2] {
2060            Frame::ObservedAddress(dec) => {
2061                assert_eq!(observed2.address, dec.address);
2062            }
2063            _ => panic!("Expected ObservedAddress at position 2"),
2064        }
2065
2066        match &decoded_frames[3] {
2067            Frame::Padding => {}
2068            _ => panic!("Expected Padding at position 3"),
2069        }
2070    }
2071
2072    #[test]
2073    fn observed_address_frame_error_recovery() {
2074        use bytes::BufMut;
2075
2076        // Test that parser can recover from malformed OBSERVED_ADDRESS frames
2077        let mut buf = Vec::new();
2078
2079        // Valid PING frame
2080        buf.put_u8(FrameType::PING.0 as u8);
2081
2082        // Malformed OBSERVED_ADDRESS frame (truncated)
2083        // Use IPv4 variant for test
2084        buf.write(FrameType::OBSERVED_ADDRESS_IPV4);
2085        buf.write_var_or_debug_assert(1); // sequence number
2086        buf.put_slice(&[192, 168]); // Only 2 bytes instead of 4 for IPv4
2087
2088        // Another valid PING frame (should not be parsed due to error above)
2089        buf.put_u8(FrameType::PING.0 as u8);
2090
2091        let result = Iter::new(Bytes::from(buf));
2092        assert!(result.is_ok());
2093        let mut iter = result.unwrap();
2094
2095        // First frame should parse successfully
2096        let frame1 = iter.next();
2097        assert!(frame1.is_some());
2098        assert!(frame1.unwrap().is_ok());
2099
2100        // Second frame should fail
2101        let frame2 = iter.next();
2102        assert!(frame2.is_some());
2103        assert!(frame2.unwrap().is_err());
2104
2105        // Iterator should stop after error
2106        let frame3 = iter.next();
2107        assert!(frame3.is_none());
2108    }
2109
2110    #[test]
2111    fn observed_address_frame_varint_encoding() {
2112        use std::net::{IpAddr, Ipv4Addr};
2113
2114        // Ensure frame type is correctly encoded as varint
2115        let frame = ObservedAddress {
2116            sequence_number: VarInt::from_u32(1000),
2117            address: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 80),
2118        };
2119
2120        let mut buf = Vec::new();
2121        frame.encode(&mut buf);
2122
2123        // Frame type 0x9f81a6 (10453414) needs 4-byte varint encoding
2124        // QUIC varint encoding for values >= 2^21 and < 2^30:
2125        // Format: 10xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
2126        // 0x9f81a6 = 10453414
2127        // First byte:  0x80 | ((value >> 24) & 0x3f) = 0x80
2128        // Second byte: (value >> 16) & 0xff = 0x9f
2129        // Third byte:  (value >> 8) & 0xff = 0x81
2130        // Fourth byte: value & 0xff = 0xa6
2131        assert_eq!(buf[0], 0x80); // First byte of 4-byte VarInt
2132        assert_eq!(buf[1], 0x9f); // Second byte
2133        assert_eq!(buf[2], 0x81); // Third byte
2134        assert_eq!(buf[3], 0xa6); // Fourth byte
2135    }
2136
2137    // Include comprehensive tests module
2138    mod comprehensive_tests {
2139        include!("frame/tests.rs");
2140    }
2141
2142    // Include sequence edge case tests
2143    mod sequence_edge_cases {
2144        include!("frame/sequence_edge_case_tests.rs");
2145    }
2146
2147    // Include IP version encoding tests
2148    mod ip_version_tests {
2149        include!("frame/ip_version_encoding_tests.rs");
2150    }
2151
2152    // Include observed address tests
2153    mod observed_address_test {
2154        include!("frame/observed_address_tests.rs");
2155    }
2156
2157    // Include observed address sequence validation tests
2158    mod observed_address_validation {
2159        include!("frame/observed_address_sequence_validation_tests.rs");
2160    }
2161
2162    // NAT frame interoperability tests
2163    mod nat_frame_interop {
2164        use super::*;
2165        use crate::frame::nat_compat::*;
2166
2167        #[test]
2168        fn test_add_address_conversions() {
2169            let old_frame = AddAddress {
2170                sequence: VarInt::from_u32(100),
2171                address: "10.0.0.1:8080".parse().unwrap(),
2172                priority: VarInt::from_u32(65535),
2173            };
2174
2175            let rfc_frame = add_address_to_rfc(&old_frame);
2176            assert_eq!(rfc_frame.sequence_number, old_frame.sequence);
2177            assert_eq!(rfc_frame.address, old_frame.address);
2178
2179            let default_priority = VarInt::from_u32(100000);
2180            let converted_back = rfc_to_add_address(&rfc_frame, default_priority);
2181            assert_eq!(converted_back.sequence, old_frame.sequence);
2182            assert_eq!(converted_back.address, old_frame.address);
2183            assert_eq!(converted_back.priority, default_priority);
2184        }
2185
2186        #[test]
2187        fn test_punch_me_now_conversions() {
2188            let old_frame = PunchMeNow {
2189                round: VarInt::from_u32(5),
2190                paired_with_sequence_number: VarInt::from_u32(100),
2191                address: "192.168.1.1:5000".parse().unwrap(),
2192                target_peer_id: Some([0x42; 32]),
2193            };
2194
2195            let rfc_frame = punch_me_now_to_rfc(&old_frame);
2196            assert_eq!(rfc_frame.round, old_frame.round);
2197            assert_eq!(
2198                rfc_frame.paired_with_sequence_number,
2199                old_frame.paired_with_sequence_number
2200            );
2201            assert_eq!(rfc_frame.address, old_frame.address);
2202
2203            let converted_back = rfc_to_punch_me_now(&rfc_frame);
2204            assert_eq!(converted_back.round, old_frame.round);
2205            assert_eq!(
2206                converted_back.paired_with_sequence_number,
2207                old_frame.paired_with_sequence_number
2208            );
2209            assert_eq!(converted_back.address, old_frame.address);
2210            assert_eq!(converted_back.target_peer_id, None);
2211        }
2212
2213        #[test]
2214        fn test_priority_strategy() {
2215            let strategy = PriorityStrategy {
2216                use_ice_priority: true,
2217                default_priority: VarInt::from_u32(50000),
2218            };
2219
2220            let public_v4: SocketAddr = "8.8.8.8:53".parse().unwrap();
2221            let private_v4: SocketAddr = "192.168.1.1:80".parse().unwrap();
2222            let loopback_v4: SocketAddr = "127.0.0.1:8080".parse().unwrap();
2223
2224            let pub_priority = strategy.calculate_priority(&public_v4);
2225            let priv_priority = strategy.calculate_priority(&private_v4);
2226            let loop_priority = strategy.calculate_priority(&loopback_v4);
2227
2228            assert!(pub_priority.into_inner() > priv_priority.into_inner());
2229            assert!(priv_priority.into_inner() > loop_priority.into_inner());
2230        }
2231
2232        #[test]
2233        fn test_compat_mode_detection() {
2234            assert_eq!(detect_frame_format(0x3d7e90), FrameFormat::Rfc);
2235            assert_eq!(detect_frame_format(0x3d7e91), FrameFormat::Rfc);
2236            assert_eq!(detect_frame_format(0x12345678), FrameFormat::Legacy);
2237        }
2238    }
2239}
2240
2241// RFC-compliant NAT traversal frames
2242pub(crate) mod rfc_nat_traversal;
2243
2244// Compatibility layer for NAT traversal frame migration
2245pub(crate) mod nat_compat;
2246
2247// Unified NAT traversal frames with RFC compliance and backward compatibility
2248pub mod nat_traversal_unified;