ant_quic/
transport_parameters.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
8//! QUIC connection transport parameters
9//!
10//! The `TransportParameters` type is used to represent the transport parameters
11//! negotiated by peers while establishing a QUIC connection. This process
12//! happens as part of the establishment of the TLS session. As such, the types
13//! contained in this modules should generally only be referred to by custom
14//! implementations of the `crypto::Session` trait.
15
16use std::{
17    convert::TryFrom,
18    net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6},
19};
20
21use bytes::{Buf, BufMut};
22use rand::{Rng as _, RngCore, seq::SliceRandom as _};
23use thiserror::Error;
24
25use crate::{
26    LOC_CID_COUNT, MAX_CID_SIZE, MAX_STREAM_COUNT, RESET_TOKEN_SIZE, ResetToken, Side,
27    TIMER_GRANULARITY, TransportError, TransportErrorCode, VarInt,
28    cid_generator::ConnectionIdGenerator,
29    cid_queue::CidQueue,
30    coding::{BufExt, BufMutExt, UnexpectedEnd},
31    config::{EndpointConfig, ServerConfig, TransportConfig},
32    shared::ConnectionId,
33};
34
35mod error_handling;
36#[cfg(test)]
37mod error_tests;
38#[cfg(test)]
39mod integration_tests;
40
41use error_handling::*;
42
43// Apply a given macro to a list of all the transport parameters having integer types, along with
44// their codes and default values. Using this helps us avoid error-prone duplication of the
45// contained information across decoding, encoding, and the `Default` impl. Whenever we want to do
46// something with transport parameters, we'll handle the bulk of cases by writing a macro that
47// takes a list of arguments in this form, then passing it to this macro.
48macro_rules! apply_params {
49    ($macro:ident) => {
50        $macro! {
51            // #[doc] name (id) = default,
52            /// Milliseconds, disabled if zero
53            max_idle_timeout(MaxIdleTimeout) = 0,
54            /// Limits the size of UDP payloads that the endpoint is willing to receive
55            max_udp_payload_size(MaxUdpPayloadSize) = 65527,
56
57            /// Initial value for the maximum amount of data that can be sent on the connection
58            initial_max_data(InitialMaxData) = 0,
59            /// Initial flow control limit for locally-initiated bidirectional streams
60            initial_max_stream_data_bidi_local(InitialMaxStreamDataBidiLocal) = 0,
61            /// Initial flow control limit for peer-initiated bidirectional streams
62            initial_max_stream_data_bidi_remote(InitialMaxStreamDataBidiRemote) = 0,
63            /// Initial flow control limit for unidirectional streams
64            initial_max_stream_data_uni(InitialMaxStreamDataUni) = 0,
65
66            /// Initial maximum number of bidirectional streams the peer may initiate
67            initial_max_streams_bidi(InitialMaxStreamsBidi) = 0,
68            /// Initial maximum number of unidirectional streams the peer may initiate
69            initial_max_streams_uni(InitialMaxStreamsUni) = 0,
70
71            /// Exponent used to decode the ACK Delay field in the ACK frame
72            ack_delay_exponent(AckDelayExponent) = 3,
73            /// Maximum amount of time in milliseconds by which the endpoint will delay sending
74            /// acknowledgments
75            max_ack_delay(MaxAckDelay) = 25,
76            /// Maximum number of connection IDs from the peer that an endpoint is willing to store
77            active_connection_id_limit(ActiveConnectionIdLimit) = 2,
78        }
79    };
80}
81
82macro_rules! make_struct {
83    {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {
84        /// Transport parameters used to negotiate connection-level preferences between peers
85        #[derive(Debug, Clone, Eq, PartialEq)]
86        pub struct TransportParameters {
87            $($(#[$doc])* pub(crate) $name : VarInt,)*
88
89            /// Does the endpoint support active connection migration
90            pub(crate) disable_active_migration: bool,
91            /// Maximum size for datagram frames
92            pub(crate) max_datagram_frame_size: Option<VarInt>,
93            /// The value that the endpoint included in the Source Connection ID field of the first
94            /// Initial packet it sends for the connection
95            pub(crate) initial_src_cid: Option<ConnectionId>,
96            /// The endpoint is willing to receive QUIC packets containing any value for the fixed
97            /// bit
98            pub(crate) grease_quic_bit: bool,
99
100            /// Minimum amount of time in microseconds by which the endpoint is able to delay
101            /// sending acknowledgments
102            ///
103            /// If a value is provided, it implies that the endpoint supports QUIC Acknowledgement
104            /// Frequency
105            pub(crate) min_ack_delay: Option<VarInt>,
106
107            /// NAT traversal configuration for this connection
108            ///
109            /// NAT traversal configuration for this connection
110            ///
111            /// When present, indicates support for QUIC NAT traversal extension
112            pub(crate) nat_traversal: Option<NatTraversalConfig>,
113
114            /// RFC NAT traversal format support
115            ///
116            /// When true, indicates support for RFC-compliant NAT traversal frame formats
117            pub(crate) rfc_nat_traversal: bool,
118
119            /// Address discovery configuration for this connection
120            ///
121            /// When present, indicates support for QUIC Address Discovery extension
122            pub(crate) address_discovery: Option<AddressDiscoveryConfig>,
123
124            /// Post-Quantum Cryptography algorithms supported by this endpoint
125            ///
126            /// When present, indicates support for PQC algorithms
127            pub(crate) pqc_algorithms: Option<PqcAlgorithms>,
128
129            // Server-only
130            /// The value of the Destination Connection ID field from the first Initial packet sent
131            /// by the client
132            pub(crate) original_dst_cid: Option<ConnectionId>,
133            /// The value that the server included in the Source Connection ID field of a Retry
134            /// packet
135            pub(crate) retry_src_cid: Option<ConnectionId>,
136            /// Token used by the client to verify a stateless reset from the server
137            pub(crate) stateless_reset_token: Option<ResetToken>,
138            /// The server's preferred address for communication after handshake completion
139            pub(crate) preferred_address: Option<PreferredAddress>,
140            /// The randomly generated reserved transport parameter to sustain future extensibility
141            /// of transport parameter extensions.
142            /// When present, it is included during serialization but ignored during deserialization.
143            pub(crate) grease_transport_parameter: Option<ReservedTransportParameter>,
144
145            /// Defines the order in which transport parameters are serialized.
146            ///
147            /// This field is initialized only for outgoing `TransportParameters` instances and
148            /// is set to `None` for `TransportParameters` received from a peer.
149            pub(crate) write_order: Option<[u8; TransportParameterId::SUPPORTED.len()]>,
150        }
151
152        // We deliberately don't implement the `Default` trait, since that would be public, and
153        // downstream crates should never construct `TransportParameters` except by decoding those
154        // supplied by a peer.
155        impl TransportParameters {
156            /// Standard defaults, used if the peer does not supply a given parameter.
157            pub(crate) fn default() -> Self {
158                Self {
159                    $($name: VarInt::from_u32($default),)*
160
161                    disable_active_migration: false,
162                    max_datagram_frame_size: None,
163                    initial_src_cid: None,
164                    grease_quic_bit: false,
165                    min_ack_delay: None,
166                    nat_traversal: None,
167                    rfc_nat_traversal: false,
168                    address_discovery: None,
169                    pqc_algorithms: None,
170
171                    original_dst_cid: None,
172                    retry_src_cid: None,
173                    stateless_reset_token: None,
174                    preferred_address: None,
175                    grease_transport_parameter: None,
176                    write_order: None,
177                }
178            }
179        }
180    }
181}
182
183apply_params!(make_struct);
184
185impl TransportParameters {
186    pub(crate) fn new(
187        config: &TransportConfig,
188        endpoint_config: &EndpointConfig,
189        cid_gen: &dyn ConnectionIdGenerator,
190        initial_src_cid: ConnectionId,
191        server_config: Option<&ServerConfig>,
192        rng: &mut impl RngCore,
193    ) -> Result<Self, TransportError> {
194        Ok(Self {
195            initial_src_cid: Some(initial_src_cid),
196            initial_max_streams_bidi: config.max_concurrent_bidi_streams,
197            initial_max_streams_uni: config.max_concurrent_uni_streams,
198            initial_max_data: config.receive_window,
199            initial_max_stream_data_bidi_local: config.stream_receive_window,
200            initial_max_stream_data_bidi_remote: config.stream_receive_window,
201            initial_max_stream_data_uni: config.stream_receive_window,
202            max_udp_payload_size: endpoint_config.max_udp_payload_size,
203            max_idle_timeout: config.max_idle_timeout.unwrap_or(VarInt(0)),
204            disable_active_migration: server_config.is_some_and(|c| !c.migration),
205            active_connection_id_limit: if cid_gen.cid_len() == 0 {
206                2 // i.e. default, i.e. unsent
207            } else {
208                CidQueue::LEN as u32
209            }
210            .into(),
211            max_datagram_frame_size: config
212                .datagram_receive_buffer_size
213                .map(|x| (x.min(u16::MAX.into()) as u16).into()),
214            grease_quic_bit: endpoint_config.grease_quic_bit,
215            min_ack_delay: Some({
216                let micros = TIMER_GRANULARITY.as_micros();
217                // TIMER_GRANULARITY should always fit in u64 and be less than 2^62
218                let micros_u64 = u64::try_from(micros).unwrap_or_else(|_| {
219                    tracing::error!("Timer granularity {} micros exceeds u64::MAX", micros);
220                    1_000_000 // Default to 1 second
221                });
222                VarInt::from_u64_bounded(micros_u64)
223            }),
224            grease_transport_parameter: Some(ReservedTransportParameter::random(rng)?),
225            write_order: Some({
226                let mut order = std::array::from_fn(|i| i as u8);
227                order.shuffle(rng);
228                order
229            }),
230            nat_traversal: config.nat_traversal_config.clone(),
231            rfc_nat_traversal: config.nat_traversal_config.is_some(), // Enable RFC format when NAT traversal is enabled
232            address_discovery: config.address_discovery_config,
233            pqc_algorithms: config.pqc_algorithms.clone(),
234            ..Self::default()
235        })
236    }
237
238    /// Check that these parameters are legal when resuming from
239    /// certain cached parameters
240    pub(crate) fn validate_resumption_from(&self, cached: &Self) -> Result<(), TransportError> {
241        if cached.active_connection_id_limit > self.active_connection_id_limit
242            || cached.initial_max_data > self.initial_max_data
243            || cached.initial_max_stream_data_bidi_local > self.initial_max_stream_data_bidi_local
244            || cached.initial_max_stream_data_bidi_remote > self.initial_max_stream_data_bidi_remote
245            || cached.initial_max_stream_data_uni > self.initial_max_stream_data_uni
246            || cached.initial_max_streams_bidi > self.initial_max_streams_bidi
247            || cached.initial_max_streams_uni > self.initial_max_streams_uni
248            || cached.max_datagram_frame_size > self.max_datagram_frame_size
249            || cached.grease_quic_bit && !self.grease_quic_bit
250        {
251            return Err(TransportError::PROTOCOL_VIOLATION(
252                "0-RTT accepted with incompatible transport parameters",
253            ));
254        }
255        Ok(())
256    }
257
258    /// Maximum number of CIDs to issue to this peer
259    ///
260    /// Consider both a) the active_connection_id_limit from the other end; and
261    /// b) LOC_CID_COUNT used locally
262    pub(crate) fn issue_cids_limit(&self) -> u64 {
263        self.active_connection_id_limit.0.min(LOC_CID_COUNT)
264    }
265
266    /// Get the NAT traversal configuration for this connection
267    ///
268    /// This is a public accessor method for tests and external code that need to
269    /// examine the negotiated NAT traversal parameters.
270    pub fn nat_traversal_config(&self) -> Option<&NatTraversalConfig> {
271        self.nat_traversal.as_ref()
272    }
273
274    /// Check if RFC-compliant NAT traversal frames are supported
275    ///
276    /// Returns true if both endpoints support RFC NAT traversal
277    pub fn supports_rfc_nat_traversal(&self) -> bool {
278        self.rfc_nat_traversal
279    }
280
281    /// Get the PQC algorithms configuration for this connection
282    ///
283    /// This is a public accessor method for tests and external code that need to
284    /// examine the negotiated PQC algorithm support.
285    pub fn pqc_algorithms(&self) -> Option<&PqcAlgorithms> {
286        self.pqc_algorithms.as_ref()
287    }
288}
289
290/// NAT traversal configuration for a QUIC connection
291///
292/// This configuration is negotiated as part of the transport parameters and
293/// enables QUIC NAT traversal extension functionality.
294#[derive(Debug, Clone, Eq, PartialEq, Default)]
295pub enum NatTraversalConfig {
296    /// Client supports NAT traversal (sends empty parameter)
297    #[default]
298    ClientSupport,
299    /// Server supports NAT traversal with specified concurrency limit
300    ServerSupport {
301        /// Maximum concurrent path validation attempts (must be > 0)
302        concurrency_limit: VarInt,
303    },
304}
305
306// Note: NatTraversalConfig is encoded/decoded according to draft-seemann-quic-nat-traversal-01
307// which uses a simple format (empty value from client, 1-byte concurrency limit from server)
308// rather than a complex custom encoding.
309impl NatTraversalConfig {
310    /// Create a client configuration
311    pub fn client() -> Self {
312        Self::ClientSupport
313    }
314
315    /// Create a server configuration with concurrency limit
316    pub fn server(concurrency_limit: VarInt) -> Result<Self, TransportError> {
317        if concurrency_limit.0 == 0 {
318            return Err(TransportError::TRANSPORT_PARAMETER_ERROR(
319                "concurrency_limit must be greater than 0",
320            ));
321        }
322        if concurrency_limit.0 > 100 {
323            return Err(TransportError::TRANSPORT_PARAMETER_ERROR(
324                "concurrency_limit must not exceed 100",
325            ));
326        }
327        Ok(Self::ServerSupport { concurrency_limit })
328    }
329
330    /// Get the concurrency limit if this is a server config
331    pub fn concurrency_limit(&self) -> Option<VarInt> {
332        match self {
333            Self::ClientSupport => None,
334            Self::ServerSupport { concurrency_limit } => Some(*concurrency_limit),
335        }
336    }
337
338    /// Check if this is a client configuration
339    pub fn is_client(&self) -> bool {
340        matches!(self, Self::ClientSupport)
341    }
342
343    /// Check if this is a server configuration
344    pub fn is_server(&self) -> bool {
345        matches!(self, Self::ServerSupport { .. })
346    }
347}
348
349/// Configuration for QUIC Address Discovery extension
350#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
351pub enum AddressDiscoveryConfig {
352    /// 0: The node is willing to provide address observations to its peer,
353    /// but is not interested in receiving address observations itself.
354    SendOnly,
355    /// 1: The node is interested in receiving address observations,
356    /// but it is not willing to provide address observations.
357    ReceiveOnly,
358    /// 2: The node is interested in receiving address observations,
359    /// and it is willing to provide address observations.
360    #[default]
361    SendAndReceive,
362}
363
364/// Post-Quantum Cryptography algorithms configuration
365///
366/// This parameter advertises which PQC algorithms are supported by the endpoint.
367/// When both endpoints support PQC, they can negotiate the use of quantum-resistant algorithms.
368#[derive(Debug, Clone, Eq, PartialEq, Default)]
369pub struct PqcAlgorithms {
370    /// ML-KEM-768 (NIST FIPS 203) support for key encapsulation
371    pub ml_kem_768: bool,
372    /// ML-DSA-65 (NIST FIPS 204) support for digital signatures
373    pub ml_dsa_65: bool,
374    /// Hybrid X25519+ML-KEM-768 key exchange
375    pub hybrid_x25519_ml_kem: bool,
376    /// Hybrid Ed25519+ML-DSA-65 signatures
377    pub hybrid_ed25519_ml_dsa: bool,
378}
379
380impl AddressDiscoveryConfig {
381    /// Get the numeric value for this configuration as per IETF spec
382    pub fn to_value(&self) -> VarInt {
383        match self {
384            Self::SendOnly => VarInt::from_u32(0),
385            Self::ReceiveOnly => VarInt::from_u32(1),
386            Self::SendAndReceive => VarInt::from_u32(2),
387        }
388    }
389
390    /// Create from numeric value as per IETF spec
391    pub fn from_value(value: VarInt) -> Result<Self, Error> {
392        match value.into_inner() {
393            0 => Ok(Self::SendOnly),
394            1 => Ok(Self::ReceiveOnly),
395            2 => Ok(Self::SendAndReceive),
396            _ => Err(Error::Malformed),
397        }
398    }
399}
400
401/// Role of an endpoint in NAT traversal coordination
402#[derive(Debug, Copy, Clone, Eq, PartialEq)]
403pub enum NatTraversalRole {
404    /// Client endpoint (initiates connections, on-demand)
405    Client,
406    /// Server endpoint (accepts connections, always reachable)
407    Server {
408        /// Whether this server can act as a relay for other connections
409        can_relay: bool,
410    },
411    /// Bootstrap/relay endpoint (publicly reachable, coordinates traversal)
412    Bootstrap,
413}
414
415/// A server's preferred address
416///
417/// This is communicated as a transport parameter during TLS session establishment.
418#[derive(Debug, Copy, Clone, Eq, PartialEq)]
419pub(crate) struct PreferredAddress {
420    pub(crate) address_v4: Option<SocketAddrV4>,
421    pub(crate) address_v6: Option<SocketAddrV6>,
422    pub(crate) connection_id: ConnectionId,
423    pub(crate) stateless_reset_token: ResetToken,
424}
425
426impl PreferredAddress {
427    fn wire_size(&self) -> u16 {
428        4 + 2 + 16 + 2 + 1 + self.connection_id.len() as u16 + 16
429    }
430
431    fn write<W: BufMut>(&self, w: &mut W) {
432        w.write(self.address_v4.map_or(Ipv4Addr::UNSPECIFIED, |x| *x.ip()));
433        w.write::<u16>(self.address_v4.map_or(0, |x| x.port()));
434        w.write(self.address_v6.map_or(Ipv6Addr::UNSPECIFIED, |x| *x.ip()));
435        w.write::<u16>(self.address_v6.map_or(0, |x| x.port()));
436        w.write::<u8>(self.connection_id.len() as u8);
437        w.put_slice(&self.connection_id);
438        w.put_slice(&self.stateless_reset_token);
439    }
440
441    fn read<R: Buf>(r: &mut R) -> Result<Self, Error> {
442        let ip_v4 = r.get::<Ipv4Addr>()?;
443        let port_v4 = r.get::<u16>()?;
444        let ip_v6 = r.get::<Ipv6Addr>()?;
445        let port_v6 = r.get::<u16>()?;
446        let cid_len = r.get::<u8>()?;
447        if r.remaining() < cid_len as usize || cid_len > MAX_CID_SIZE as u8 {
448            return Err(Error::Malformed);
449        }
450        let mut stage = [0; MAX_CID_SIZE];
451        r.copy_to_slice(&mut stage[0..cid_len as usize]);
452        let cid = ConnectionId::new(&stage[0..cid_len as usize]);
453        if r.remaining() < 16 {
454            return Err(Error::Malformed);
455        }
456        let mut token = [0; RESET_TOKEN_SIZE];
457        r.copy_to_slice(&mut token);
458        let address_v4 = if ip_v4.is_unspecified() && port_v4 == 0 {
459            None
460        } else {
461            Some(SocketAddrV4::new(ip_v4, port_v4))
462        };
463        let address_v6 = if ip_v6.is_unspecified() && port_v6 == 0 {
464            None
465        } else {
466            Some(SocketAddrV6::new(ip_v6, port_v6, 0, 0))
467        };
468        if address_v4.is_none() && address_v6.is_none() {
469            return Err(Error::IllegalValue);
470        }
471        Ok(Self {
472            address_v4,
473            address_v6,
474            connection_id: cid,
475            stateless_reset_token: token.into(),
476        })
477    }
478}
479
480/// Errors encountered while decoding `TransportParameters`
481#[derive(Debug, Copy, Clone, Eq, PartialEq, Error)]
482pub enum Error {
483    /// Parameters that are semantically invalid
484    #[error("parameter had illegal value")]
485    IllegalValue,
486    /// Catch-all error for problems while decoding transport parameters
487    #[error("parameters were malformed")]
488    Malformed,
489}
490
491impl From<Error> for TransportError {
492    fn from(e: Error) -> Self {
493        match e {
494            Error::IllegalValue => Self::TRANSPORT_PARAMETER_ERROR("illegal value"),
495            Error::Malformed => Self::TRANSPORT_PARAMETER_ERROR("malformed"),
496        }
497    }
498}
499
500impl From<UnexpectedEnd> for Error {
501    fn from(_: UnexpectedEnd) -> Self {
502        Self::Malformed
503    }
504}
505
506impl TransportParameters {
507    /// Encode `TransportParameters` into buffer
508    pub fn write<W: BufMut>(&self, w: &mut W) {
509        for idx in self
510            .write_order
511            .as_ref()
512            .unwrap_or(&std::array::from_fn(|i| i as u8))
513        {
514            let id = TransportParameterId::SUPPORTED[*idx as usize];
515            match id {
516                TransportParameterId::ReservedTransportParameter => {
517                    if let Some(param) = self.grease_transport_parameter {
518                        param.write(w);
519                    }
520                }
521                TransportParameterId::StatelessResetToken => {
522                    if let Some(ref x) = self.stateless_reset_token {
523                        w.write_var(id as u64);
524                        w.write_var(16);
525                        w.put_slice(x);
526                    }
527                }
528                TransportParameterId::DisableActiveMigration => {
529                    if self.disable_active_migration {
530                        w.write_var(id as u64);
531                        w.write_var(0);
532                    }
533                }
534                TransportParameterId::MaxDatagramFrameSize => {
535                    if let Some(x) = self.max_datagram_frame_size {
536                        w.write_var(id as u64);
537                        w.write_var(x.size() as u64);
538                        w.write(x);
539                    }
540                }
541                TransportParameterId::PreferredAddress => {
542                    if let Some(ref x) = self.preferred_address {
543                        w.write_var(id as u64);
544                        w.write_var(x.wire_size() as u64);
545                        x.write(w);
546                    }
547                }
548                TransportParameterId::OriginalDestinationConnectionId => {
549                    if let Some(ref cid) = self.original_dst_cid {
550                        w.write_var(id as u64);
551                        w.write_var(cid.len() as u64);
552                        w.put_slice(cid);
553                    }
554                }
555                TransportParameterId::InitialSourceConnectionId => {
556                    if let Some(ref cid) = self.initial_src_cid {
557                        w.write_var(id as u64);
558                        w.write_var(cid.len() as u64);
559                        w.put_slice(cid);
560                    }
561                }
562                TransportParameterId::RetrySourceConnectionId => {
563                    if let Some(ref cid) = self.retry_src_cid {
564                        w.write_var(id as u64);
565                        w.write_var(cid.len() as u64);
566                        w.put_slice(cid);
567                    }
568                }
569                TransportParameterId::GreaseQuicBit => {
570                    if self.grease_quic_bit {
571                        w.write_var(id as u64);
572                        w.write_var(0);
573                    }
574                }
575                TransportParameterId::MinAckDelayDraft07 => {
576                    if let Some(x) = self.min_ack_delay {
577                        w.write_var(id as u64);
578                        w.write_var(x.size() as u64);
579                        w.write(x);
580                    }
581                }
582                TransportParameterId::NatTraversal => {
583                    if let Some(ref config) = self.nat_traversal {
584                        // Per draft-seemann-quic-nat-traversal-02:
585                        // - Client sends empty value to indicate support
586                        // - Server sends VarInt concurrency limit
587                        match config {
588                            NatTraversalConfig::ClientSupport => {
589                                // Client sends empty value
590                                w.write_var(id as u64);
591                                w.write_var(0); // Empty value
592                            }
593                            NatTraversalConfig::ServerSupport { concurrency_limit } => {
594                                // Server sends concurrency limit as VarInt
595                                w.write_var(id as u64);
596                                w.write_var(concurrency_limit.size() as u64);
597                                w.write_var(concurrency_limit.0);
598                            }
599                        }
600                    }
601                }
602                TransportParameterId::AddressDiscovery => {
603                    if let Some(ref config) = self.address_discovery {
604                        w.write_var(id as u64);
605                        let value = config.to_value();
606                        w.write_var(value.size() as u64);
607                        w.write_var(value.into_inner());
608                    }
609                }
610                TransportParameterId::RfcNatTraversal => {
611                    if self.rfc_nat_traversal {
612                        // Send empty parameter to indicate support
613                        w.write_var(id as u64);
614                        w.write_var(0); // Empty value
615                    }
616                }
617                TransportParameterId::PqcAlgorithms => {
618                    if let Some(ref algorithms) = self.pqc_algorithms {
619                        w.write_var(id as u64);
620                        // Encode as bit field: 4 bits for 4 algorithms
621                        let mut value = 0u8;
622                        if algorithms.ml_kem_768 {
623                            value |= 1 << 0;
624                        }
625                        if algorithms.ml_dsa_65 {
626                            value |= 1 << 1;
627                        }
628                        if algorithms.hybrid_x25519_ml_kem {
629                            value |= 1 << 2;
630                        }
631                        if algorithms.hybrid_ed25519_ml_dsa {
632                            value |= 1 << 3;
633                        }
634                        w.write_var(1u64); // Length is always 1 byte
635                        w.write(value);
636                    }
637                }
638                id => {
639                    macro_rules! write_params {
640                        {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {
641                            match id {
642                                $(TransportParameterId::$id => {
643                                    if self.$name.0 != $default {
644                                        w.write_var(id as u64);
645                                        w.write(VarInt::try_from(self.$name.size()).unwrap());
646                                        w.write(self.$name);
647                                    }
648                                })*,
649                                _ => {
650                                    // This should never be reached for supported parameters
651                                    // All supported parameters should be handled in specific match arms above
652                                    panic!("Unsupported transport parameter reached write implementation: {id:?}");
653                                }
654                            }
655                        }
656                    }
657                    apply_params!(write_params);
658                }
659            }
660        }
661    }
662
663    /// Decode `TransportParameters` from buffer
664    pub fn read<R: Buf>(side: Side, r: &mut R) -> Result<Self, Error> {
665        // Initialize to protocol-specified defaults
666        let mut params = Self::default();
667
668        // State to check for duplicate transport parameters.
669        macro_rules! param_state {
670            {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {{
671                struct ParamState {
672                    $($name: bool,)*
673                }
674
675                ParamState {
676                    $($name: false,)*
677                }
678            }}
679        }
680        let mut got = apply_params!(param_state);
681
682        while r.has_remaining() {
683            let id = r.get_var()?;
684            let len = r.get_var()?;
685            if (r.remaining() as u64) < len {
686                return Err(Error::Malformed);
687            }
688            let len = len as usize;
689            let Ok(id) = TransportParameterId::try_from(id) else {
690                // unknown transport parameters are ignored
691                r.advance(len);
692                continue;
693            };
694
695            match id {
696                TransportParameterId::OriginalDestinationConnectionId => {
697                    decode_cid(len, &mut params.original_dst_cid, r)?
698                }
699                TransportParameterId::StatelessResetToken => {
700                    if len != 16 || params.stateless_reset_token.is_some() {
701                        return Err(Error::Malformed);
702                    }
703                    let mut tok = [0; RESET_TOKEN_SIZE];
704                    r.copy_to_slice(&mut tok);
705                    params.stateless_reset_token = Some(tok.into());
706                }
707                TransportParameterId::DisableActiveMigration => {
708                    if len != 0 || params.disable_active_migration {
709                        return Err(Error::Malformed);
710                    }
711                    params.disable_active_migration = true;
712                }
713                TransportParameterId::PreferredAddress => {
714                    if params.preferred_address.is_some() {
715                        return Err(Error::Malformed);
716                    }
717                    params.preferred_address = Some(PreferredAddress::read(&mut r.take(len))?);
718                }
719                TransportParameterId::InitialSourceConnectionId => {
720                    decode_cid(len, &mut params.initial_src_cid, r)?
721                }
722                TransportParameterId::RetrySourceConnectionId => {
723                    decode_cid(len, &mut params.retry_src_cid, r)?
724                }
725                TransportParameterId::MaxDatagramFrameSize => {
726                    if len > 8 || params.max_datagram_frame_size.is_some() {
727                        return Err(Error::Malformed);
728                    }
729                    params.max_datagram_frame_size = Some(r.get().map_err(|_| Error::Malformed)?);
730                }
731                TransportParameterId::GreaseQuicBit => match len {
732                    0 => params.grease_quic_bit = true,
733                    _ => return Err(Error::Malformed),
734                },
735                TransportParameterId::MinAckDelayDraft07 => {
736                    params.min_ack_delay = Some(r.get().map_err(|_| Error::Malformed)?)
737                }
738                TransportParameterId::NatTraversal => {
739                    if params.nat_traversal.is_some() {
740                        return Err(Error::Malformed);
741                    }
742                    // Per draft-seemann-quic-nat-traversal-02:
743                    // - Empty value (len=0) indicates ClientSupport
744                    // - VarInt value indicates ServerSupport with concurrency limit
745                    // P2P support: Either side can send either parameter type
746                    match len {
747                        0 => {
748                            // Empty value - ClientSupport
749                            // Traditional: Client -> Server
750                            // P2P: Either peer can send this
751                            params.nat_traversal = Some(NatTraversalConfig::ClientSupport);
752                        }
753                        _ if len > 0 => {
754                            // VarInt value - ServerSupport with concurrency limit
755                            // Traditional: Server -> Client
756                            // P2P: Either peer can send this
757                            let limit = r.get_var()?;
758                            if limit == 0 {
759                                return Err(Error::IllegalValue);
760                            }
761                            params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
762                                concurrency_limit: VarInt::from_u64(limit)
763                                    .map_err(|_| Error::IllegalValue)?,
764                            });
765                        }
766                        _ => {
767                            // This should be unreachable, but included for safety
768                            return Err(Error::IllegalValue);
769                        }
770                    }
771                }
772                TransportParameterId::AddressDiscovery => {
773                    if params.address_discovery.is_some() {
774                        return Err(Error::Malformed);
775                    }
776                    let value = r.get_var()?;
777                    let varint = VarInt::from_u64(value).map_err(|_| Error::Malformed)?;
778                    params.address_discovery = Some(AddressDiscoveryConfig::from_value(varint)?);
779                }
780                TransportParameterId::RfcNatTraversal => {
781                    if params.rfc_nat_traversal {
782                        return Err(Error::Malformed);
783                    }
784                    if len != 0 {
785                        // Must be empty parameter
786                        return Err(Error::Malformed);
787                    }
788                    params.rfc_nat_traversal = true;
789                }
790                TransportParameterId::PqcAlgorithms => {
791                    if params.pqc_algorithms.is_some() {
792                        return Err(Error::Malformed);
793                    }
794                    if len != 1 {
795                        return Err(Error::Malformed);
796                    }
797                    let value = r.get::<u8>()?;
798                    params.pqc_algorithms = Some(PqcAlgorithms {
799                        ml_kem_768: (value & (1 << 0)) != 0,
800                        ml_dsa_65: (value & (1 << 1)) != 0,
801                        hybrid_x25519_ml_kem: (value & (1 << 2)) != 0,
802                        hybrid_ed25519_ml_dsa: (value & (1 << 3)) != 0,
803                    });
804                }
805                _ => {
806                    macro_rules! parse {
807                        {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {
808                            match id {
809                                $(TransportParameterId::$id => {
810                                    let value = r.get::<VarInt>()?;
811                                    if len != value.size() || got.$name { return Err(Error::Malformed); }
812                                    params.$name = value.into();
813                                    got.$name = true;
814                                })*
815                                _ => r.advance(len),
816                            }
817                        }
818                    }
819                    apply_params!(parse);
820                }
821            }
822        }
823
824        // Semantic validation with detailed error reporting
825
826        // Validate individual parameters
827        validate_ack_delay_exponent(params.ack_delay_exponent.0 as u8)
828            .map_err(|_| Error::IllegalValue)?;
829
830        validate_max_ack_delay(params.max_ack_delay).map_err(|_| Error::IllegalValue)?;
831
832        validate_active_connection_id_limit(params.active_connection_id_limit)
833            .map_err(|_| Error::IllegalValue)?;
834
835        validate_max_udp_payload_size(params.max_udp_payload_size)
836            .map_err(|_| Error::IllegalValue)?;
837
838        // Stream count validation
839        if params.initial_max_streams_bidi.0 > MAX_STREAM_COUNT {
840            TransportParameterErrorHandler::log_validation_failure(
841                "initial_max_streams_bidi",
842                params.initial_max_streams_bidi.0,
843                &format!("must be <= {MAX_STREAM_COUNT}"),
844                "RFC 9000 Section 4.6-2",
845            );
846            return Err(Error::IllegalValue);
847        }
848        if params.initial_max_streams_uni.0 > MAX_STREAM_COUNT {
849            TransportParameterErrorHandler::log_validation_failure(
850                "initial_max_streams_uni",
851                params.initial_max_streams_uni.0,
852                &format!("must be <= {MAX_STREAM_COUNT}"),
853                "RFC 9000 Section 4.6-2",
854            );
855            return Err(Error::IllegalValue);
856        }
857
858        // Min/max ack delay validation
859        validate_min_ack_delay(params.min_ack_delay, params.max_ack_delay)
860            .map_err(|_| Error::IllegalValue)?;
861
862        // Server-only parameter validation
863        validate_server_only_params(side, &params).map_err(|_| Error::IllegalValue)?;
864
865        // Preferred address validation
866        if let Some(ref pref_addr) = params.preferred_address {
867            if pref_addr.connection_id.is_empty() {
868                TransportParameterErrorHandler::log_semantic_error(
869                    "preferred_address with empty connection_id",
870                    "RFC 9000 Section 18.2-4.38.1",
871                );
872                return Err(Error::IllegalValue);
873            }
874        }
875
876        // NAT traversal parameter validation with detailed logging
877        if let Some(ref nat_config) = params.nat_traversal {
878            // Validate NAT traversal configuration based on side
879            match (side, nat_config) {
880                // Traditional: Server receives ClientSupport from client
881                (Side::Server, NatTraversalConfig::ClientSupport) => {
882                    tracing::debug!("Server received valid ClientSupport NAT traversal parameter");
883                }
884                // Traditional: Client receives ServerSupport from server
885                (Side::Client, NatTraversalConfig::ServerSupport { concurrency_limit }) => {
886                    tracing::debug!(
887                        "Client received valid ServerSupport with concurrency_limit: {}",
888                        concurrency_limit
889                    );
890                }
891                // P2P: Server receives ServerSupport from peer (symmetric P2P)
892                (Side::Server, NatTraversalConfig::ServerSupport { concurrency_limit }) => {
893                    tracing::debug!(
894                        "P2P: Server received ServerSupport with concurrency_limit: {} (symmetric P2P)",
895                        concurrency_limit
896                    );
897                    // Validate concurrency limit (1-100 per draft-seemann-quic-nat-traversal-02)
898                    if concurrency_limit.0 == 0 || concurrency_limit.0 > 100 {
899                        TransportParameterErrorHandler::log_validation_failure(
900                            "nat_traversal_concurrency_limit",
901                            concurrency_limit.0,
902                            "1-100",
903                            "draft-seemann-quic-nat-traversal-02",
904                        );
905                        return Err(Error::IllegalValue);
906                    }
907                }
908                // P2P: Client receives ClientSupport from peer (symmetric P2P)
909                (Side::Client, NatTraversalConfig::ClientSupport) => {
910                    tracing::debug!("P2P: Client received ClientSupport (symmetric P2P)");
911                    // Valid for P2P - both peers have client capabilities
912                }
913            }
914        }
915
916        Ok(params)
917    }
918
919    /// Negotiate effective NAT traversal concurrency limit for this connection
920    ///
921    /// Returns the effective concurrency limit based on local and remote NAT traversal
922    /// configurations. For P2P connections where both peers have `ServerSupport`,
923    /// returns the minimum of the two limits. For traditional client/server, returns
924    /// the server's limit. Returns `None` if NAT traversal is not configured.
925    ///
926    /// # Examples
927    ///
928    /// ```
929    /// use ant_quic::VarInt;
930    /// use ant_quic::TransportParameters;
931    /// use ant_quic::NatTraversalConfig;
932    ///
933    /// // P2P: Both peers have ServerSupport - use minimum
934    /// let local = NatTraversalConfig::ServerSupport {
935    ///     concurrency_limit: VarInt::from_u32(10),
936    /// };
937    /// let mut remote_params = TransportParameters::default();
938    /// remote_params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
939    ///     concurrency_limit: VarInt::from_u32(5),
940    /// });
941    /// assert_eq!(remote_params.negotiated_nat_concurrency_limit(&local), Some(5));
942    /// ```
943    pub fn negotiated_nat_concurrency_limit(
944        &self,
945        local_config: &NatTraversalConfig,
946    ) -> Option<u64> {
947        match (&self.nat_traversal, local_config) {
948            // P2P: Both sides have ServerSupport - use minimum for fairness
949            (
950                Some(NatTraversalConfig::ServerSupport {
951                    concurrency_limit: remote,
952                }),
953                NatTraversalConfig::ServerSupport {
954                    concurrency_limit: local,
955                },
956            ) => Some(local.0.min(remote.0)),
957
958            // Traditional: One side server, one side client - use server's limit
959            (
960                Some(NatTraversalConfig::ServerSupport { concurrency_limit }),
961                NatTraversalConfig::ClientSupport,
962            )
963            | (
964                Some(NatTraversalConfig::ClientSupport),
965                NatTraversalConfig::ServerSupport { concurrency_limit },
966            ) => Some(concurrency_limit.0),
967
968            // Both clients or no NAT traversal - no concurrency limit
969            _ => None,
970        }
971    }
972
973    /// Check if this connection supports bidirectional NAT traversal (P2P)
974    ///
975    /// Returns `true` if the remote peer sent `ServerSupport`, indicating they
976    /// can accept NAT traversal path validation requests. This is used to detect
977    /// P2P connections where both peers have equal capabilities.
978    ///
979    /// # Examples
980    ///
981    /// ```
982    /// use ant_quic::VarInt;
983    /// use ant_quic::TransportParameters;
984    /// use ant_quic::NatTraversalConfig;
985    ///
986    /// let mut params = TransportParameters::default();
987    /// params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
988    ///     concurrency_limit: VarInt::from_u32(5),
989    /// });
990    /// assert!(params.supports_bidirectional_nat_traversal());
991    ///
992    /// let mut client_params = TransportParameters::default();
993    /// client_params.nat_traversal = Some(NatTraversalConfig::ClientSupport);
994    /// assert!(!client_params.supports_bidirectional_nat_traversal());
995    /// ```
996    pub fn supports_bidirectional_nat_traversal(&self) -> bool {
997        matches!(
998            &self.nat_traversal,
999            Some(NatTraversalConfig::ServerSupport { .. })
1000        )
1001    }
1002}
1003
1004/// A reserved transport parameter.
1005///
1006/// It has an identifier of the form 31 * N + 27 for the integer value of N.
1007/// Such identifiers are reserved to exercise the requirement that unknown transport parameters be ignored.
1008/// The reserved transport parameter has no semantics and can carry arbitrary values.
1009/// It may be included in transport parameters sent to the peer, and should be ignored when received.
1010///
1011/// See spec: <https://www.rfc-editor.org/rfc/rfc9000.html#section-18.1>
1012#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1013pub(crate) struct ReservedTransportParameter {
1014    /// The reserved identifier of the transport parameter
1015    id: VarInt,
1016
1017    /// Buffer to store the parameter payload
1018    payload: [u8; Self::MAX_PAYLOAD_LEN],
1019
1020    /// The number of bytes to include in the wire format from the `payload` buffer
1021    payload_len: usize,
1022}
1023
1024impl ReservedTransportParameter {
1025    /// Generates a transport parameter with a random payload and a reserved ID.
1026    ///
1027    /// The implementation is inspired by quic-go and quiche:
1028    /// 1. <https://github.com/quic-go/quic-go/blob/3e0a67b2476e1819752f04d75968de042b197b56/internal/wire/transport_parameters.go#L338-L344>
1029    /// 2. <https://github.com/google/quiche/blob/cb1090b20c40e2f0815107857324e99acf6ec567/quiche/quic/core/crypto/transport_parameters.cc#L843-L860>
1030    fn random(rng: &mut impl RngCore) -> Result<Self, TransportError> {
1031        let id = Self::generate_reserved_id(rng)?;
1032
1033        let payload_len = rng.gen_range(0..Self::MAX_PAYLOAD_LEN);
1034
1035        let payload = {
1036            let mut slice = [0u8; Self::MAX_PAYLOAD_LEN];
1037            rng.fill_bytes(&mut slice[..payload_len]);
1038            slice
1039        };
1040
1041        Ok(Self {
1042            id,
1043            payload,
1044            payload_len,
1045        })
1046    }
1047
1048    fn write(&self, w: &mut impl BufMut) {
1049        w.write_var(self.id.0);
1050        w.write_var(self.payload_len as u64);
1051        w.put_slice(&self.payload[..self.payload_len]);
1052    }
1053
1054    /// Generates a random reserved identifier of the form `31 * N + 27`, as required by RFC 9000.
1055    /// Reserved transport parameter identifiers are used to test compliance with the requirement
1056    /// that unknown transport parameters must be ignored by peers.
1057    /// See: <https://www.rfc-editor.org/rfc/rfc9000.html#section-18.1> and <https://www.rfc-editor.org/rfc/rfc9000.html#section-22.3>
1058    fn generate_reserved_id(rng: &mut impl RngCore) -> Result<VarInt, TransportError> {
1059        let id = {
1060            let rand = rng.gen_range(0u64..(1 << 62) - 27);
1061            let n = rand / 31;
1062            31 * n + 27
1063        };
1064        debug_assert!(
1065            id % 31 == 27,
1066            "generated id does not have the form of 31 * N + 27"
1067        );
1068        VarInt::from_u64(id).map_err(|_| TransportError {
1069            code: TransportErrorCode::INTERNAL_ERROR,
1070            frame: None,
1071            reason: "generated id does not fit into range of allowed transport parameter IDs"
1072                .to_string(),
1073        })
1074    }
1075
1076    /// The maximum length of the payload to include as the parameter payload.
1077    /// This value is not a specification-imposed limit but is chosen to match
1078    /// the limit used by other implementations of QUIC, e.g., quic-go and quiche.
1079    const MAX_PAYLOAD_LEN: usize = 16;
1080}
1081
1082#[repr(u64)]
1083#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1084pub(crate) enum TransportParameterId {
1085    // https://www.rfc-editor.org/rfc/rfc9000.html#iana-tp-table
1086    OriginalDestinationConnectionId = 0x00,
1087    MaxIdleTimeout = 0x01,
1088    StatelessResetToken = 0x02,
1089    MaxUdpPayloadSize = 0x03,
1090    InitialMaxData = 0x04,
1091    InitialMaxStreamDataBidiLocal = 0x05,
1092    InitialMaxStreamDataBidiRemote = 0x06,
1093    InitialMaxStreamDataUni = 0x07,
1094    InitialMaxStreamsBidi = 0x08,
1095    InitialMaxStreamsUni = 0x09,
1096    AckDelayExponent = 0x0A,
1097    MaxAckDelay = 0x0B,
1098    DisableActiveMigration = 0x0C,
1099    PreferredAddress = 0x0D,
1100    ActiveConnectionIdLimit = 0x0E,
1101    InitialSourceConnectionId = 0x0F,
1102    RetrySourceConnectionId = 0x10,
1103
1104    // Smallest possible ID of reserved transport parameter https://datatracker.ietf.org/doc/html/rfc9000#section-22.3
1105    ReservedTransportParameter = 0x1B,
1106
1107    // https://www.rfc-editor.org/rfc/rfc9221.html#section-3
1108    MaxDatagramFrameSize = 0x20,
1109
1110    // https://www.rfc-editor.org/rfc/rfc9287.html#section-3
1111    GreaseQuicBit = 0x2AB2,
1112
1113    // https://datatracker.ietf.org/doc/html/draft-ietf-quic-ack-frequency#section-10.1
1114    MinAckDelayDraft07 = 0xFF04DE1B,
1115
1116    // NAT Traversal Extension - draft-seemann-quic-nat-traversal-01
1117    // Transport parameter ID from the IETF draft specification
1118    NatTraversal = 0x3d7e9f0bca12fea6,
1119
1120    // RFC NAT Traversal Format Support
1121    // Indicates support for RFC-compliant NAT traversal frame formats
1122    RfcNatTraversal = 0x3d7e9f0bca12fea8,
1123
1124    // Address Discovery Extension - draft-ietf-quic-address-discovery-00
1125    // Transport parameter ID from the specification
1126    AddressDiscovery = 0x9f81a176,
1127    // Post-Quantum Cryptography Algorithms
1128    // Using experimental range for now (will be assigned by IANA)
1129    PqcAlgorithms = 0x50C0,
1130}
1131
1132impl TransportParameterId {
1133    /// Array with all supported transport parameter IDs
1134    const SUPPORTED: [Self; 25] = [
1135        Self::MaxIdleTimeout,
1136        Self::MaxUdpPayloadSize,
1137        Self::InitialMaxData,
1138        Self::InitialMaxStreamDataBidiLocal,
1139        Self::InitialMaxStreamDataBidiRemote,
1140        Self::InitialMaxStreamDataUni,
1141        Self::InitialMaxStreamsBidi,
1142        Self::InitialMaxStreamsUni,
1143        Self::AckDelayExponent,
1144        Self::MaxAckDelay,
1145        Self::ActiveConnectionIdLimit,
1146        Self::ReservedTransportParameter,
1147        Self::StatelessResetToken,
1148        Self::DisableActiveMigration,
1149        Self::MaxDatagramFrameSize,
1150        Self::PreferredAddress,
1151        Self::OriginalDestinationConnectionId,
1152        Self::InitialSourceConnectionId,
1153        Self::RetrySourceConnectionId,
1154        Self::GreaseQuicBit,
1155        Self::MinAckDelayDraft07,
1156        Self::NatTraversal,
1157        Self::RfcNatTraversal,
1158        Self::AddressDiscovery,
1159        Self::PqcAlgorithms,
1160    ];
1161}
1162
1163impl std::cmp::PartialEq<u64> for TransportParameterId {
1164    fn eq(&self, other: &u64) -> bool {
1165        *other == (*self as u64)
1166    }
1167}
1168
1169impl TryFrom<u64> for TransportParameterId {
1170    type Error = ();
1171
1172    fn try_from(value: u64) -> Result<Self, Self::Error> {
1173        let param = match value {
1174            id if Self::MaxIdleTimeout == id => Self::MaxIdleTimeout,
1175            id if Self::MaxUdpPayloadSize == id => Self::MaxUdpPayloadSize,
1176            id if Self::InitialMaxData == id => Self::InitialMaxData,
1177            id if Self::InitialMaxStreamDataBidiLocal == id => Self::InitialMaxStreamDataBidiLocal,
1178            id if Self::InitialMaxStreamDataBidiRemote == id => {
1179                Self::InitialMaxStreamDataBidiRemote
1180            }
1181            id if Self::InitialMaxStreamDataUni == id => Self::InitialMaxStreamDataUni,
1182            id if Self::InitialMaxStreamsBidi == id => Self::InitialMaxStreamsBidi,
1183            id if Self::InitialMaxStreamsUni == id => Self::InitialMaxStreamsUni,
1184            id if Self::AckDelayExponent == id => Self::AckDelayExponent,
1185            id if Self::MaxAckDelay == id => Self::MaxAckDelay,
1186            id if Self::ActiveConnectionIdLimit == id => Self::ActiveConnectionIdLimit,
1187            id if Self::ReservedTransportParameter == id => Self::ReservedTransportParameter,
1188            id if Self::StatelessResetToken == id => Self::StatelessResetToken,
1189            id if Self::DisableActiveMigration == id => Self::DisableActiveMigration,
1190            id if Self::MaxDatagramFrameSize == id => Self::MaxDatagramFrameSize,
1191            id if Self::PreferredAddress == id => Self::PreferredAddress,
1192            id if Self::OriginalDestinationConnectionId == id => {
1193                Self::OriginalDestinationConnectionId
1194            }
1195            id if Self::InitialSourceConnectionId == id => Self::InitialSourceConnectionId,
1196            id if Self::RetrySourceConnectionId == id => Self::RetrySourceConnectionId,
1197            id if Self::GreaseQuicBit == id => Self::GreaseQuicBit,
1198            id if Self::MinAckDelayDraft07 == id => Self::MinAckDelayDraft07,
1199            id if Self::NatTraversal == id => Self::NatTraversal,
1200            id if Self::RfcNatTraversal == id => Self::RfcNatTraversal,
1201            id if Self::AddressDiscovery == id => Self::AddressDiscovery,
1202            id if Self::PqcAlgorithms == id => Self::PqcAlgorithms,
1203            _ => return Err(()),
1204        };
1205        Ok(param)
1206    }
1207}
1208
1209fn decode_cid(len: usize, value: &mut Option<ConnectionId>, r: &mut impl Buf) -> Result<(), Error> {
1210    if len > MAX_CID_SIZE || value.is_some() || r.remaining() < len {
1211        return Err(Error::Malformed);
1212    }
1213
1214    *value = Some(ConnectionId::from_buf(r, len));
1215    Ok(())
1216}
1217
1218#[cfg(test)]
1219mod test {
1220    use super::*;
1221
1222    #[test]
1223    fn test_nat_traversal_transport_parameter_encoding_decoding() {
1224        // Test draft-compliant NAT traversal parameter encoding/decoding
1225
1226        // Test 1: Client sends empty value, server reads it
1227        let client_config = NatTraversalConfig::ClientSupport;
1228
1229        let mut client_params = TransportParameters::default();
1230        client_params.nat_traversal = Some(client_config);
1231
1232        let mut encoded = Vec::new();
1233        client_params.write(&mut encoded);
1234
1235        // Server reads client params
1236        let server_decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1237            .expect("Failed to decode client transport parameters");
1238
1239        // Server should see that client supports NAT traversal
1240        assert!(server_decoded.nat_traversal.is_some());
1241        let server_view = server_decoded.nat_traversal.unwrap();
1242        assert!(matches!(server_view, NatTraversalConfig::ClientSupport));
1243
1244        // Test 2: Server sends concurrency limit, client reads it
1245        let server_config = NatTraversalConfig::ServerSupport {
1246            concurrency_limit: VarInt::from_u32(5),
1247        };
1248
1249        let mut server_params = TransportParameters::default();
1250        server_params.nat_traversal = Some(server_config);
1251
1252        let mut encoded = Vec::new();
1253        server_params.write(&mut encoded);
1254
1255        // Client reads server params
1256        let client_decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1257            .expect("Failed to decode server transport parameters");
1258
1259        // Client should see server's concurrency limit
1260        assert!(client_decoded.nat_traversal.is_some());
1261        let client_view = client_decoded.nat_traversal.unwrap();
1262        assert!(matches!(
1263            client_view,
1264            NatTraversalConfig::ServerSupport { .. }
1265        ));
1266        assert_eq!(client_view.concurrency_limit(), Some(VarInt::from_u32(5)));
1267    }
1268
1269    #[test]
1270    fn test_nat_traversal_parameter_without_peer_id() {
1271        // Test client-side NAT traversal config (sends empty value)
1272        let config = NatTraversalConfig::ClientSupport;
1273
1274        let mut params = TransportParameters::default();
1275        params.nat_traversal = Some(config);
1276
1277        let mut encoded = Vec::new();
1278        params.write(&mut encoded);
1279
1280        // Server reads client's parameters
1281        let decoded_params = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1282            .expect("Failed to decode transport parameters");
1283
1284        let decoded_config = decoded_params
1285            .nat_traversal
1286            .expect("NAT traversal config should be present");
1287
1288        assert!(matches!(decoded_config, NatTraversalConfig::ClientSupport));
1289
1290        // Test server-side NAT traversal config (sends concurrency limit)
1291        let server_config = NatTraversalConfig::ServerSupport {
1292            concurrency_limit: VarInt::from_u32(4),
1293        };
1294
1295        let mut server_params = TransportParameters::default();
1296        server_params.nat_traversal = Some(server_config);
1297
1298        let mut server_encoded = Vec::new();
1299        server_params.write(&mut server_encoded);
1300
1301        // Client reads server's parameters
1302        let decoded_server_params =
1303            TransportParameters::read(Side::Client, &mut server_encoded.as_slice())
1304                .expect("Failed to decode server transport parameters");
1305
1306        let decoded_server_config = decoded_server_params
1307            .nat_traversal
1308            .expect("Server NAT traversal config should be present");
1309
1310        assert!(matches!(
1311            decoded_server_config,
1312            NatTraversalConfig::ServerSupport { concurrency_limit } if concurrency_limit == VarInt::from_u32(4)
1313        ));
1314    }
1315
1316    #[test]
1317    fn test_transport_parameters_without_nat_traversal() {
1318        // Test that transport parameters work without NAT traversal config
1319        let mut params = TransportParameters::default();
1320        params.nat_traversal = None;
1321
1322        let mut encoded = Vec::new();
1323        params.write(&mut encoded);
1324
1325        let decoded_params = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1326            .expect("Failed to decode transport parameters");
1327
1328        assert!(decoded_params.nat_traversal.is_none());
1329    }
1330
1331    #[test]
1332    fn test_nat_traversal_draft_compliant_encoding() {
1333        // Test draft-seemann-quic-nat-traversal-01 compliant encoding
1334
1335        // Test 1: Client sends empty value
1336        let client_config = NatTraversalConfig::ClientSupport;
1337
1338        let mut client_params = TransportParameters::default();
1339        client_params.nat_traversal = Some(client_config);
1340
1341        let mut encoded = Vec::new();
1342        client_params.write(&mut encoded);
1343
1344        // Verify the encoded data contains empty value for client
1345        // Find the NAT traversal parameter in the encoded data
1346        use bytes::Buf;
1347        let mut cursor = &encoded[..];
1348        while cursor.has_remaining() {
1349            let id = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1350            let len = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1351            if id.0 == 0x3d7e9f0bca12fea6 {
1352                // Found NAT traversal parameter
1353                assert_eq!(len.0, 0, "Client should send empty value");
1354                break;
1355            }
1356            // Skip this parameter
1357            cursor.advance(len.0 as usize);
1358        }
1359
1360        // Test 2: Server sends 1-byte concurrency limit
1361        let server_config = NatTraversalConfig::ServerSupport {
1362            concurrency_limit: VarInt::from_u32(5),
1363        };
1364
1365        let mut server_params = TransportParameters::default();
1366        server_params.nat_traversal = Some(server_config);
1367
1368        let mut encoded = Vec::new();
1369        server_params.write(&mut encoded);
1370
1371        // Verify the encoded data contains 1-byte value for server
1372        let mut cursor = &encoded[..];
1373        while cursor.has_remaining() {
1374            let id = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1375            let len = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1376            if id.0 == 0x3d7e9f0bca12fea6 {
1377                // Found NAT traversal parameter
1378                assert_eq!(len.0, 1, "Server should send 1-byte value");
1379                let limit = cursor.chunk()[0];
1380                assert_eq!(limit, 5, "Server should send concurrency limit");
1381                break;
1382            }
1383            // Skip this parameter
1384            cursor.advance(len.0 as usize);
1385        }
1386    }
1387
1388    #[test]
1389    fn test_nat_traversal_draft_compliant_decoding() {
1390        // Test 1: Decode empty value from client
1391        let mut buf = Vec::new();
1392        buf.write_var(0x3d7e9f0bca12fea6); // NAT traversal parameter ID
1393        buf.write_var(0); // Empty value
1394
1395        let params = TransportParameters::read(Side::Server, &mut buf.as_slice())
1396            .expect("Failed to decode transport parameters");
1397
1398        let config = params
1399            .nat_traversal
1400            .expect("NAT traversal should be present");
1401        assert!(matches!(config, NatTraversalConfig::ClientSupport));
1402
1403        // Test 2: Decode 1-byte concurrency limit from server
1404        let mut buf = Vec::new();
1405        buf.write_var(0x3d7e9f0bca12fea6); // NAT traversal parameter ID
1406        buf.write_var(1); // 1-byte value
1407        buf.put_u8(7); // Concurrency limit of 7
1408
1409        let params = TransportParameters::read(Side::Client, &mut buf.as_slice())
1410            .expect("Failed to decode transport parameters");
1411
1412        let config = params
1413            .nat_traversal
1414            .expect("NAT traversal should be present");
1415        assert!(matches!(
1416            config,
1417            NatTraversalConfig::ServerSupport { concurrency_limit } if concurrency_limit == VarInt::from_u32(7)
1418        ));
1419
1420        // Test 3: Invalid length should fail
1421        let mut buf = Vec::new();
1422        buf.write_var(0x3d7e9f0bca12fea6); // NAT traversal parameter ID
1423        buf.write_var(2); // Invalid 2-byte value
1424        buf.put_u8(7);
1425        buf.put_u8(8);
1426
1427        let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1428        assert!(result.is_err(), "Should fail with invalid length");
1429    }
1430
1431    #[test]
1432    fn test_nat_traversal_parameter_id() {
1433        // Verify the correct parameter ID is used
1434        assert_eq!(
1435            TransportParameterId::NatTraversal as u64,
1436            0x3d7e9f0bca12fea6
1437        );
1438    }
1439
1440    #[test]
1441    fn test_nat_traversal_simple_encoding() {
1442        // Test the simplified NAT traversal encoding per draft-seemann-quic-nat-traversal-02
1443
1444        // Test 1: Client sends empty parameter
1445        let mut client_params = TransportParameters::default();
1446        client_params.nat_traversal = Some(NatTraversalConfig::ClientSupport);
1447
1448        let mut encoded = Vec::new();
1449        client_params.write(&mut encoded);
1450
1451        // Verify it can be decoded by server
1452        let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1453            .expect("Should decode client params");
1454        assert!(matches!(
1455            decoded.nat_traversal,
1456            Some(NatTraversalConfig::ClientSupport)
1457        ));
1458
1459        // Test 2: Server sends concurrency limit
1460        let mut server_params = TransportParameters::default();
1461        server_params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1462            concurrency_limit: VarInt::from_u32(10),
1463        });
1464
1465        let mut encoded = Vec::new();
1466        server_params.write(&mut encoded);
1467
1468        // Verify it can be decoded by client
1469        let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1470            .expect("Should decode server params");
1471
1472        match decoded.nat_traversal {
1473            Some(NatTraversalConfig::ServerSupport { concurrency_limit }) => {
1474                assert_eq!(concurrency_limit, VarInt::from_u32(10));
1475            }
1476            _ => panic!("Expected ServerSupport variant"),
1477        }
1478    }
1479
1480    #[test]
1481    fn test_nat_traversal_config_validation() {
1482        // Test valid client configuration
1483        let client_config = NatTraversalConfig::ClientSupport;
1484        assert!(client_config.is_client());
1485        assert_eq!(client_config.concurrency_limit(), None);
1486
1487        // Test valid server configuration
1488        let server_config = NatTraversalConfig::server(VarInt::from_u32(5)).unwrap();
1489        assert!(server_config.is_server());
1490        assert_eq!(server_config.concurrency_limit(), Some(VarInt::from_u32(5)));
1491
1492        // Test invalid server configuration (concurrency limit = 0)
1493        let result = NatTraversalConfig::server(VarInt::from_u32(0));
1494        assert!(result.is_err());
1495
1496        // Test invalid server configuration (concurrency limit > 100)
1497        let result = NatTraversalConfig::server(VarInt::from_u32(101));
1498        assert!(result.is_err());
1499
1500        // Test valid server configurations at boundaries
1501        let min_server = NatTraversalConfig::server(VarInt::from_u32(1)).unwrap();
1502        assert_eq!(min_server.concurrency_limit(), Some(VarInt::from_u32(1)));
1503
1504        let max_server = NatTraversalConfig::server(VarInt::from_u32(100)).unwrap();
1505        assert_eq!(max_server.concurrency_limit(), Some(VarInt::from_u32(100)));
1506    }
1507
1508    #[test]
1509    fn test_nat_traversal_role_validation() {
1510        // Test client role validation - should fail when received by client
1511        let mut buf = Vec::new();
1512        buf.write_var(0x3d7e9f0bca12fea6); // NAT traversal parameter ID
1513        buf.write_var(0); // Empty value (client role)
1514
1515        // P2P: Client receiving client role should succeed (symmetric P2P connection)
1516        let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1517        assert!(
1518            result.is_ok(),
1519            "P2P: Client should accept ClientSupport from peer for symmetric P2P"
1520        );
1521
1522        // Traditional: Server receiving client role should succeed
1523        let result = TransportParameters::read(Side::Server, &mut buf.as_slice());
1524        assert!(
1525            result.is_ok(),
1526            "Server should accept ClientSupport from client"
1527        );
1528
1529        // Test server role validation
1530        let mut buf = Vec::new();
1531        buf.write_var(0x3d7e9f0bca12fea6); // NAT traversal parameter ID
1532        buf.write_var(1); // 1-byte value (server role)
1533        buf.put_u8(5); // Concurrency limit
1534
1535        // P2P: Server receiving server role should succeed (symmetric P2P connection)
1536        let result = TransportParameters::read(Side::Server, &mut buf.as_slice());
1537        assert!(
1538            result.is_ok(),
1539            "P2P: Server should accept ServerSupport from peer for symmetric P2P"
1540        );
1541
1542        // Traditional: Client receiving server role should succeed
1543        let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1544        assert!(
1545            result.is_ok(),
1546            "Client should accept ServerSupport from server"
1547        );
1548    }
1549
1550    #[test]
1551    fn test_nat_traversal_parameter_combinations() {
1552        // Test that NAT traversal works with other transport parameters
1553        let nat_config = NatTraversalConfig::ClientSupport;
1554
1555        let mut params = TransportParameters::default();
1556        params.nat_traversal = Some(nat_config);
1557        params.max_idle_timeout = VarInt::from_u32(30000);
1558        params.initial_max_data = VarInt::from_u32(1048576);
1559        params.grease_quic_bit = true;
1560
1561        // Test encoding
1562        let mut encoded = Vec::new();
1563        params.write(&mut encoded);
1564        assert!(!encoded.is_empty());
1565
1566        // Test decoding
1567        let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1568            .expect("Should decode successfully");
1569
1570        // Verify NAT traversal config is preserved
1571        let decoded_config = decoded
1572            .nat_traversal
1573            .expect("NAT traversal should be present");
1574        assert!(matches!(decoded_config, NatTraversalConfig::ClientSupport));
1575
1576        // Verify other parameters are preserved
1577        assert_eq!(decoded.max_idle_timeout, VarInt::from_u32(30000));
1578        assert_eq!(decoded.initial_max_data, VarInt::from_u32(1048576));
1579        assert!(decoded.grease_quic_bit);
1580    }
1581
1582    #[test]
1583    fn test_nat_traversal_default_config() {
1584        let default_config = NatTraversalConfig::default();
1585
1586        assert!(matches!(default_config, NatTraversalConfig::ClientSupport));
1587        assert!(default_config.is_client());
1588        assert_eq!(default_config.concurrency_limit(), None);
1589    }
1590
1591    #[test]
1592    fn test_nat_traversal_endpoint_role_negotiation() {
1593        // Test complete client-server negotiation
1594
1595        // 1. Client creates parameters with NAT traversal support
1596        let client_config = NatTraversalConfig::ClientSupport;
1597
1598        let mut client_params = TransportParameters::default();
1599        client_params.nat_traversal = Some(client_config);
1600
1601        // 2. Client encodes and sends to server
1602        let mut client_encoded = Vec::new();
1603        client_params.write(&mut client_encoded);
1604
1605        // 3. Server receives and decodes client parameters
1606        let server_received =
1607            TransportParameters::read(Side::Server, &mut client_encoded.as_slice())
1608                .expect("Server should decode client params");
1609
1610        // Server should see client role
1611        let server_view = server_received
1612            .nat_traversal
1613            .expect("NAT traversal should be present");
1614        assert!(matches!(server_view, NatTraversalConfig::ClientSupport));
1615
1616        // 4. Server creates response with server role
1617        let server_config = NatTraversalConfig::ServerSupport {
1618            concurrency_limit: VarInt::from_u32(8),
1619        };
1620
1621        let mut server_params = TransportParameters::default();
1622        server_params.nat_traversal = Some(server_config);
1623
1624        // 5. Server encodes and sends to client
1625        let mut server_encoded = Vec::new();
1626        server_params.write(&mut server_encoded);
1627
1628        // 6. Client receives and decodes server parameters
1629        let client_received =
1630            TransportParameters::read(Side::Client, &mut server_encoded.as_slice())
1631                .expect("Client should decode server params");
1632
1633        // Client should see server role with concurrency limit
1634        let client_view = client_received
1635            .nat_traversal
1636            .expect("NAT traversal should be present");
1637        assert!(matches!(
1638            client_view,
1639            NatTraversalConfig::ServerSupport { concurrency_limit } if concurrency_limit == VarInt::from_u32(8)
1640        ));
1641    }
1642
1643    // ===== P2P NAT Traversal Tests =====
1644
1645    #[test]
1646    fn test_p2p_nat_traversal_both_server_support() {
1647        // Test P2P scenario: Both peers send ServerSupport with concurrency limits
1648        // This should now PASS after implementing P2P support
1649
1650        let peer1_config = NatTraversalConfig::ServerSupport {
1651            concurrency_limit: VarInt::from_u32(10),
1652        };
1653        let _peer2_config = NatTraversalConfig::ServerSupport {
1654            concurrency_limit: VarInt::from_u32(5),
1655        };
1656
1657        // Peer 1 sends its ServerSupport config
1658        let mut peer1_params = TransportParameters::default();
1659        peer1_params.nat_traversal = Some(peer1_config);
1660
1661        let mut encoded = Vec::new();
1662        peer1_params.write(&mut encoded);
1663
1664        // Peer 2 (acting as server side) receives peer 1's ServerSupport
1665        // This currently FAILS but should PASS after P2P fix
1666        let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1667            .expect("P2P: Server should accept ServerSupport from peer");
1668
1669        // Should preserve peer's ServerSupport config
1670        assert!(matches!(
1671            decoded.nat_traversal,
1672            Some(NatTraversalConfig::ServerSupport { concurrency_limit })
1673            if concurrency_limit == VarInt::from_u32(10)
1674        ));
1675    }
1676
1677    #[test]
1678    fn test_p2p_nat_traversal_concurrency_negotiation() {
1679        // Test that P2P connections negotiate minimum concurrency limit
1680
1681        let local = NatTraversalConfig::ServerSupport {
1682            concurrency_limit: VarInt::from_u32(10),
1683        };
1684        let mut remote_params = TransportParameters::default();
1685        remote_params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1686            concurrency_limit: VarInt::from_u32(5),
1687        });
1688
1689        // Negotiated limit should be minimum of both
1690        let negotiated = remote_params.negotiated_nat_concurrency_limit(&local);
1691        assert_eq!(negotiated, Some(5));
1692
1693        // Test opposite direction
1694        let local2 = NatTraversalConfig::ServerSupport {
1695            concurrency_limit: VarInt::from_u32(3),
1696        };
1697        let mut remote_params2 = TransportParameters::default();
1698        remote_params2.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1699            concurrency_limit: VarInt::from_u32(8),
1700        });
1701
1702        let negotiated2 = remote_params2.negotiated_nat_concurrency_limit(&local2);
1703        assert_eq!(negotiated2, Some(3));
1704    }
1705
1706    #[test]
1707    fn test_p2p_nat_traversal_invalid_concurrency() {
1708        // Test that P2P connections reject zero concurrency limit
1709
1710        let config = NatTraversalConfig::ServerSupport {
1711            concurrency_limit: VarInt::from_u32(0), // Invalid - must be > 0
1712        };
1713
1714        let mut params = TransportParameters::default();
1715        params.nat_traversal = Some(config);
1716
1717        let mut encoded = Vec::new();
1718        params.write(&mut encoded);
1719
1720        // Should reject zero concurrency limit
1721        let result = TransportParameters::read(Side::Server, &mut encoded.as_slice());
1722        assert!(
1723            matches!(result, Err(Error::IllegalValue)),
1724            "Should reject concurrency_limit = 0"
1725        );
1726    }
1727
1728    #[test]
1729    fn test_p2p_nat_traversal_max_concurrency() {
1730        // Test that P2P connections reject excessive concurrency limit
1731
1732        let config = NatTraversalConfig::ServerSupport {
1733            concurrency_limit: VarInt::from_u32(101), // Exceeds max of 100
1734        };
1735
1736        let mut params = TransportParameters::default();
1737        params.nat_traversal = Some(config);
1738
1739        let mut encoded = Vec::new();
1740        params.write(&mut encoded);
1741
1742        // Should reject concurrency limit > 100
1743        let result = TransportParameters::read(Side::Server, &mut encoded.as_slice());
1744        assert!(
1745            matches!(result, Err(Error::IllegalValue)),
1746            "Should reject concurrency_limit > 100"
1747        );
1748    }
1749
1750    #[test]
1751    fn test_p2p_both_client_support() {
1752        // Test P2P scenario: Client receiving ClientSupport from peer
1753        // This means both peers have client-only capabilities
1754
1755        let config = NatTraversalConfig::ClientSupport;
1756
1757        let mut params = TransportParameters::default();
1758        params.nat_traversal = Some(config);
1759
1760        let mut encoded = Vec::new();
1761        params.write(&mut encoded);
1762
1763        // Client receiving ClientSupport (currently FAILS, should PASS after P2P fix)
1764        let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1765            .expect("P2P: Client should accept ClientSupport from peer");
1766
1767        assert!(matches!(
1768            decoded.nat_traversal,
1769            Some(NatTraversalConfig::ClientSupport)
1770        ));
1771    }
1772
1773    #[test]
1774    fn test_p2p_helper_methods() {
1775        // Test helper methods for P2P capability detection
1776
1777        // Test supports_bidirectional_nat_traversal
1778        let mut params_with_server = TransportParameters::default();
1779        params_with_server.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1780            concurrency_limit: VarInt::from_u32(5),
1781        });
1782        assert!(params_with_server.supports_bidirectional_nat_traversal());
1783
1784        let mut params_with_client = TransportParameters::default();
1785        params_with_client.nat_traversal = Some(NatTraversalConfig::ClientSupport);
1786        assert!(!params_with_client.supports_bidirectional_nat_traversal());
1787
1788        let params_without_nat = TransportParameters::default();
1789        assert!(!params_without_nat.supports_bidirectional_nat_traversal());
1790
1791        // Test mixed client/server negotiation
1792        let local = NatTraversalConfig::ClientSupport;
1793        let mut remote_params = TransportParameters::default();
1794        remote_params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1795            concurrency_limit: VarInt::from_u32(10),
1796        });
1797
1798        // Should use server's limit
1799        let negotiated = remote_params.negotiated_nat_concurrency_limit(&local);
1800        assert_eq!(negotiated, Some(10));
1801    }
1802
1803    // ===== Regression Tests =====
1804
1805    #[test]
1806    fn test_traditional_client_server_unchanged() {
1807        // Verify that traditional client/server NAT traversal still works
1808        // after P2P changes (regression test)
1809
1810        // Client sends empty value (ClientSupport)
1811        let client_config = NatTraversalConfig::ClientSupport;
1812        let mut client_params = TransportParameters::default();
1813        client_params.nat_traversal = Some(client_config);
1814
1815        let mut encoded = Vec::new();
1816        client_params.write(&mut encoded);
1817
1818        // Server decodes client's parameters
1819        let server_decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1820            .expect("Traditional client/server should still work");
1821
1822        assert!(matches!(
1823            server_decoded.nat_traversal,
1824            Some(NatTraversalConfig::ClientSupport)
1825        ));
1826    }
1827
1828    #[test]
1829    fn test_traditional_server_client_unchanged() {
1830        // Verify that traditional server/client NAT traversal still works
1831        // after P2P changes (regression test)
1832
1833        // Server sends concurrency limit (ServerSupport)
1834        let server_config = NatTraversalConfig::ServerSupport {
1835            concurrency_limit: VarInt::from_u32(10),
1836        };
1837        let mut server_params = TransportParameters::default();
1838        server_params.nat_traversal = Some(server_config);
1839
1840        let mut encoded = Vec::new();
1841        server_params.write(&mut encoded);
1842
1843        // Client decodes server's parameters
1844        let client_decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1845            .expect("Traditional server/client should still work");
1846
1847        assert!(matches!(
1848            client_decoded.nat_traversal,
1849            Some(NatTraversalConfig::ServerSupport { concurrency_limit })
1850            if concurrency_limit == VarInt::from_u32(10)
1851        ));
1852    }
1853
1854    #[test]
1855    fn coding() {
1856        let mut buf = Vec::new();
1857        let params = TransportParameters {
1858            initial_src_cid: Some(ConnectionId::new(&[])),
1859            original_dst_cid: Some(ConnectionId::new(&[])),
1860            initial_max_streams_bidi: 16u32.into(),
1861            initial_max_streams_uni: 16u32.into(),
1862            ack_delay_exponent: 2u32.into(),
1863            max_udp_payload_size: 1200u32.into(),
1864            preferred_address: Some(PreferredAddress {
1865                address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
1866                address_v6: Some(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 24, 0, 0)),
1867                connection_id: ConnectionId::new(&[0x42]),
1868                stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
1869            }),
1870            grease_quic_bit: true,
1871            min_ack_delay: Some(2_000u32.into()),
1872            ..TransportParameters::default()
1873        };
1874        params.write(&mut buf);
1875        assert_eq!(
1876            TransportParameters::read(Side::Client, &mut buf.as_slice()).unwrap(),
1877            params
1878        );
1879    }
1880
1881    #[test]
1882    fn reserved_transport_parameter_generate_reserved_id() {
1883        use rand::rngs::mock::StepRng;
1884        let mut rngs = [
1885            StepRng::new(0, 1),
1886            StepRng::new(1, 1),
1887            StepRng::new(27, 1),
1888            StepRng::new(31, 1),
1889            StepRng::new(u32::MAX as u64, 1),
1890            StepRng::new(u32::MAX as u64 - 1, 1),
1891            StepRng::new(u32::MAX as u64 + 1, 1),
1892            StepRng::new(u32::MAX as u64 - 27, 1),
1893            StepRng::new(u32::MAX as u64 + 27, 1),
1894            StepRng::new(u32::MAX as u64 - 31, 1),
1895            StepRng::new(u32::MAX as u64 + 31, 1),
1896            StepRng::new(u64::MAX, 1),
1897            StepRng::new(u64::MAX - 1, 1),
1898            StepRng::new(u64::MAX - 27, 1),
1899            StepRng::new(u64::MAX - 31, 1),
1900            StepRng::new(1 << 62, 1),
1901            StepRng::new((1 << 62) - 1, 1),
1902            StepRng::new((1 << 62) + 1, 1),
1903            StepRng::new((1 << 62) - 27, 1),
1904            StepRng::new((1 << 62) + 27, 1),
1905            StepRng::new((1 << 62) - 31, 1),
1906            StepRng::new((1 << 62) + 31, 1),
1907        ];
1908        for rng in &mut rngs {
1909            let id = ReservedTransportParameter::generate_reserved_id(rng).unwrap();
1910            assert!(id.0 % 31 == 27)
1911        }
1912    }
1913
1914    #[test]
1915    fn reserved_transport_parameter_ignored_when_read() {
1916        let mut buf = Vec::new();
1917        let reserved_parameter =
1918            ReservedTransportParameter::random(&mut rand::thread_rng()).unwrap();
1919        assert!(reserved_parameter.payload_len < ReservedTransportParameter::MAX_PAYLOAD_LEN);
1920        assert!(reserved_parameter.id.0 % 31 == 27);
1921
1922        reserved_parameter.write(&mut buf);
1923        assert!(!buf.is_empty());
1924        let read_params = TransportParameters::read(Side::Server, &mut buf.as_slice()).unwrap();
1925        assert_eq!(read_params, TransportParameters::default());
1926    }
1927
1928    #[test]
1929    fn read_semantic_validation() {
1930        #[allow(clippy::type_complexity)]
1931        let illegal_params_builders: Vec<Box<dyn FnMut(&mut TransportParameters)>> = vec![
1932            Box::new(|t| {
1933                // This min_ack_delay is bigger than max_ack_delay!
1934                let min_ack_delay = t.max_ack_delay.0 * 1_000 + 1;
1935                t.min_ack_delay = Some(VarInt::from_u64(min_ack_delay).unwrap())
1936            }),
1937            Box::new(|t| {
1938                // Preferred address can only be sent by senders (and we are reading the transport
1939                // params as a client)
1940                t.preferred_address = Some(PreferredAddress {
1941                    address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
1942                    address_v6: None,
1943                    connection_id: ConnectionId::new(&[]),
1944                    stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
1945                })
1946            }),
1947        ];
1948
1949        for mut builder in illegal_params_builders {
1950            let mut buf = Vec::new();
1951            let mut params = TransportParameters::default();
1952            builder(&mut params);
1953            params.write(&mut buf);
1954
1955            assert_eq!(
1956                TransportParameters::read(Side::Server, &mut buf.as_slice()),
1957                Err(Error::IllegalValue)
1958            );
1959        }
1960    }
1961
1962    #[test]
1963    fn resumption_params_validation() {
1964        let high_limit = TransportParameters {
1965            initial_max_streams_uni: 32u32.into(),
1966            ..TransportParameters::default()
1967        };
1968        let low_limit = TransportParameters {
1969            initial_max_streams_uni: 16u32.into(),
1970            ..TransportParameters::default()
1971        };
1972        high_limit.validate_resumption_from(&low_limit).unwrap();
1973        low_limit.validate_resumption_from(&high_limit).unwrap_err();
1974    }
1975
1976    #[test]
1977    fn test_address_discovery_parameter_id() {
1978        // Test that ADDRESS_DISCOVERY parameter ID is defined correctly
1979        assert_eq!(TransportParameterId::AddressDiscovery as u64, 0x9f81a176);
1980    }
1981
1982    #[test]
1983    fn test_address_discovery_config_struct() {
1984        // Test AddressDiscoveryConfig enum variants
1985        let send_only = AddressDiscoveryConfig::SendOnly;
1986        let receive_only = AddressDiscoveryConfig::ReceiveOnly;
1987        let send_receive = AddressDiscoveryConfig::SendAndReceive;
1988
1989        assert_eq!(send_only.to_value(), VarInt::from_u32(0));
1990        assert_eq!(receive_only.to_value(), VarInt::from_u32(1));
1991        assert_eq!(send_receive.to_value(), VarInt::from_u32(2));
1992    }
1993
1994    #[test]
1995    fn test_address_discovery_config_from_value() {
1996        // Test from_value conversion
1997        assert_eq!(
1998            AddressDiscoveryConfig::from_value(VarInt::from_u32(0)).unwrap(),
1999            AddressDiscoveryConfig::SendOnly
2000        );
2001        assert_eq!(
2002            AddressDiscoveryConfig::from_value(VarInt::from_u32(1)).unwrap(),
2003            AddressDiscoveryConfig::ReceiveOnly
2004        );
2005        assert_eq!(
2006            AddressDiscoveryConfig::from_value(VarInt::from_u32(2)).unwrap(),
2007            AddressDiscoveryConfig::SendAndReceive
2008        );
2009        assert!(AddressDiscoveryConfig::from_value(VarInt::from_u32(3)).is_err());
2010    }
2011
2012    #[test]
2013    fn test_transport_parameters_with_address_discovery() {
2014        // Test that TransportParameters can hold address_discovery field
2015        let mut params = TransportParameters::default();
2016        assert!(params.address_discovery.is_none());
2017
2018        let config = AddressDiscoveryConfig::SendAndReceive;
2019
2020        params.address_discovery = Some(config);
2021        assert!(params.address_discovery.is_some());
2022
2023        let stored_config = params.address_discovery.as_ref().unwrap();
2024        assert_eq!(*stored_config, AddressDiscoveryConfig::SendAndReceive);
2025    }
2026
2027    #[test]
2028    fn test_address_discovery_parameter_encoding() {
2029        // Test encoding of address discovery transport parameter
2030        let config = AddressDiscoveryConfig::SendAndReceive;
2031
2032        let mut params = TransportParameters::default();
2033        params.address_discovery = Some(config);
2034
2035        let mut encoded = Vec::new();
2036        params.write(&mut encoded);
2037
2038        // The encoded data should contain our parameter
2039        assert!(!encoded.is_empty());
2040    }
2041
2042    #[test]
2043    fn test_address_discovery_parameter_roundtrip() {
2044        // Test encoding and decoding of address discovery parameter
2045        let config = AddressDiscoveryConfig::ReceiveOnly;
2046
2047        let mut params = TransportParameters::default();
2048        params.address_discovery = Some(config);
2049
2050        let mut encoded = Vec::new();
2051        params.write(&mut encoded);
2052
2053        // Decode as peer
2054        let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2055            .expect("Failed to decode transport parameters");
2056
2057        assert!(decoded.address_discovery.is_some());
2058        let decoded_config = decoded.address_discovery.as_ref().unwrap();
2059        assert_eq!(*decoded_config, AddressDiscoveryConfig::ReceiveOnly);
2060    }
2061
2062    #[test]
2063    fn test_address_discovery_disabled_by_default() {
2064        // Test that address discovery is disabled by default
2065        let params = TransportParameters::default();
2066        assert!(params.address_discovery.is_none());
2067    }
2068
2069    #[test]
2070    fn test_address_discovery_all_variants() {
2071        // Test all address discovery variants roundtrip correctly
2072        for variant in [
2073            AddressDiscoveryConfig::SendOnly,
2074            AddressDiscoveryConfig::ReceiveOnly,
2075            AddressDiscoveryConfig::SendAndReceive,
2076        ] {
2077            let mut params = TransportParameters::default();
2078            params.address_discovery = Some(variant);
2079
2080            let mut encoded = Vec::new();
2081            params.write(&mut encoded);
2082
2083            let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
2084                .expect("Failed to decode");
2085
2086            assert_eq!(decoded.address_discovery, Some(variant));
2087        }
2088    }
2089
2090    #[test]
2091    fn test_address_discovery_none_not_encoded() {
2092        // Test that None address discovery is not encoded
2093        let mut params = TransportParameters::default();
2094        params.address_discovery = None;
2095
2096        let mut encoded = Vec::new();
2097        params.write(&mut encoded);
2098
2099        let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2100            .expect("Failed to decode");
2101        assert!(decoded.address_discovery.is_none());
2102    }
2103
2104    #[test]
2105    fn test_address_discovery_serialization_roundtrip() {
2106        let config = AddressDiscoveryConfig::SendOnly;
2107
2108        let mut params = TransportParameters::default();
2109        params.address_discovery = Some(config);
2110        params.initial_max_data = VarInt::from_u32(1_000_000);
2111
2112        let mut encoded = Vec::new();
2113        params.write(&mut encoded);
2114
2115        let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2116            .expect("Failed to decode");
2117
2118        assert_eq!(
2119            decoded.address_discovery,
2120            Some(AddressDiscoveryConfig::SendOnly)
2121        );
2122        assert_eq!(decoded.initial_max_data, VarInt::from_u32(1_000_000));
2123    }
2124
2125    #[test]
2126    fn test_address_discovery_invalid_value() {
2127        // Test that invalid values are rejected
2128
2129        let mut encoded = Vec::new();
2130        encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2131        encoded.write_var(1); // Length
2132        encoded.write_var(3); // Invalid value (only 0, 1, 2 are valid)
2133
2134        let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2135        assert!(result.is_err());
2136    }
2137
2138    #[test]
2139    fn test_address_discovery_edge_cases() {
2140        // Test edge cases for address discovery
2141
2142        // Test empty parameter (zero-length)
2143        let mut encoded = Vec::new();
2144        encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2145        encoded.write_var(0); // Zero length
2146
2147        let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2148        assert!(result.is_err());
2149
2150        // Test value too large
2151        let mut encoded = Vec::new();
2152        encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2153        encoded.write_var(1); // Length
2154        encoded.put_u8(255); // Invalid value (only 0, 1, 2 are valid)
2155
2156        let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2157        assert!(result.is_err());
2158    }
2159
2160    #[test]
2161    fn test_address_discovery_malformed_length() {
2162        // Create a malformed parameter with wrong length
2163        let mut encoded = Vec::new();
2164        encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2165        encoded.write_var(1); // Says 1 byte but no data follows
2166
2167        let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2168        assert!(result.is_err());
2169        assert!(matches!(result.unwrap_err(), Error::Malformed));
2170    }
2171
2172    #[test]
2173    fn test_address_discovery_duplicate_parameter() {
2174        // Create parameters with duplicate address discovery
2175        let mut encoded = Vec::new();
2176
2177        // First occurrence
2178        encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2179        encoded.write_var(1);
2180        encoded.put_u8(0x80); // enabled=true
2181
2182        // Duplicate occurrence
2183        encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2184        encoded.write_var(1);
2185        encoded.put_u8(0xC0); // Different config
2186
2187        let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2188        assert!(result.is_err());
2189        assert!(matches!(result.unwrap_err(), Error::Malformed));
2190    }
2191
2192    #[test]
2193    fn test_address_discovery_with_other_parameters() {
2194        // Test that address discovery works alongside other transport parameters
2195        let mut params = TransportParameters::default();
2196        params.max_idle_timeout = VarInt::from_u32(30000);
2197        params.initial_max_data = VarInt::from_u32(1_000_000);
2198        params.address_discovery = Some(AddressDiscoveryConfig::SendAndReceive);
2199
2200        let mut encoded = Vec::new();
2201        params.write(&mut encoded);
2202
2203        let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2204            .expect("Failed to decode");
2205
2206        // Check all parameters are preserved
2207        assert_eq!(decoded.max_idle_timeout, params.max_idle_timeout);
2208        assert_eq!(decoded.initial_max_data, params.initial_max_data);
2209        assert_eq!(
2210            decoded.address_discovery,
2211            Some(AddressDiscoveryConfig::SendAndReceive)
2212        );
2213    }
2214
2215    #[test]
2216    fn test_pqc_algorithms_transport_parameter() {
2217        // Test that PQC algorithms can be encoded and decoded correctly
2218        let mut params = TransportParameters::default();
2219        params.pqc_algorithms = Some(PqcAlgorithms {
2220            ml_kem_768: true,
2221            ml_dsa_65: false,
2222            hybrid_x25519_ml_kem: true,
2223            hybrid_ed25519_ml_dsa: true,
2224        });
2225
2226        // Encode
2227        let mut encoded = Vec::new();
2228        params.write(&mut encoded);
2229
2230        // Decode
2231        let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2232            .expect("Failed to decode");
2233
2234        // Verify
2235        assert!(decoded.pqc_algorithms.is_some());
2236        let pqc = decoded.pqc_algorithms.unwrap();
2237        assert!(pqc.ml_kem_768);
2238        assert!(!pqc.ml_dsa_65);
2239        assert!(pqc.hybrid_x25519_ml_kem);
2240        assert!(pqc.hybrid_ed25519_ml_dsa);
2241    }
2242
2243    #[test]
2244    fn test_pqc_algorithms_all_combinations() {
2245        // Test all possible combinations of PQC algorithm flags
2246        for ml_kem in [false, true] {
2247            for ml_dsa in [false, true] {
2248                for hybrid_kex in [false, true] {
2249                    for hybrid_sig in [false, true] {
2250                        let mut params = TransportParameters::default();
2251                        params.pqc_algorithms = Some(PqcAlgorithms {
2252                            ml_kem_768: ml_kem,
2253                            ml_dsa_65: ml_dsa,
2254                            hybrid_x25519_ml_kem: hybrid_kex,
2255                            hybrid_ed25519_ml_dsa: hybrid_sig,
2256                        });
2257
2258                        // Encode and decode
2259                        let mut encoded = Vec::new();
2260                        params.write(&mut encoded);
2261                        let decoded =
2262                            TransportParameters::read(Side::Client, &mut encoded.as_slice())
2263                                .expect("Failed to decode");
2264
2265                        // Verify
2266                        let pqc = decoded.pqc_algorithms.unwrap();
2267                        assert_eq!(pqc.ml_kem_768, ml_kem);
2268                        assert_eq!(pqc.ml_dsa_65, ml_dsa);
2269                        assert_eq!(pqc.hybrid_x25519_ml_kem, hybrid_kex);
2270                        assert_eq!(pqc.hybrid_ed25519_ml_dsa, hybrid_sig);
2271                    }
2272                }
2273            }
2274        }
2275    }
2276
2277    #[test]
2278    fn test_pqc_algorithms_not_sent_when_none() {
2279        // Test that PQC algorithms parameter is not sent when None
2280        let mut params = TransportParameters::default();
2281        params.pqc_algorithms = None;
2282
2283        let mut encoded = Vec::new();
2284        params.write(&mut encoded);
2285
2286        // Check that the parameter ID doesn't appear in the encoding
2287        // (Can't easily check for exact bytes due to VarInt encoding)
2288        let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2289            .expect("Failed to decode");
2290        assert!(decoded.pqc_algorithms.is_none());
2291    }
2292
2293    #[test]
2294    fn test_pqc_algorithms_duplicate_parameter() {
2295        // Test that duplicate PQC algorithms parameters are rejected
2296        let mut encoded = Vec::new();
2297
2298        // Write a valid parameter
2299        encoded.write_var(TransportParameterId::PqcAlgorithms as u64);
2300        encoded.write_var(1u64); // Length
2301        encoded.write(0b1111u8); // All algorithms enabled
2302
2303        // Write duplicate
2304        encoded.write_var(TransportParameterId::PqcAlgorithms as u64);
2305        encoded.write_var(1u64);
2306        encoded.write(0b0000u8);
2307
2308        // Should fail to decode
2309        let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2310        assert!(result.is_err());
2311        assert!(matches!(result.unwrap_err(), Error::Malformed));
2312    }
2313
2314    // Include comprehensive tests module
2315    mod comprehensive_tests {
2316        include!("transport_parameters/tests.rs");
2317    }
2318}