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