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