ant_quic/
transport_parameters.rs

1//! QUIC connection transport parameters
2//!
3//! The `TransportParameters` type is used to represent the transport parameters
4//! negotiated by peers while establishing a QUIC connection. This process
5//! happens as part of the establishment of the TLS session. As such, the types
6//! contained in this modules should generally only be referred to by custom
7//! implementations of the `crypto::Session` trait.
8
9use std::{
10    convert::TryFrom,
11    net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6},
12};
13
14use bytes::{Buf, BufMut};
15use rand::{Rng as _, RngCore, seq::SliceRandom as _};
16use thiserror::Error;
17
18use crate::{
19    LOC_CID_COUNT, MAX_CID_SIZE, MAX_STREAM_COUNT, RESET_TOKEN_SIZE, ResetToken, Side,
20    TIMER_GRANULARITY, TransportError, VarInt,
21    cid_generator::ConnectionIdGenerator,
22    cid_queue::CidQueue,
23    coding::{BufExt, BufMutExt, UnexpectedEnd},
24    config::{EndpointConfig, ServerConfig, TransportConfig},
25    shared::ConnectionId,
26};
27
28// Apply a given macro to a list of all the transport parameters having integer types, along with
29// their codes and default values. Using this helps us avoid error-prone duplication of the
30// contained information across decoding, encoding, and the `Default` impl. Whenever we want to do
31// something with transport parameters, we'll handle the bulk of cases by writing a macro that
32// takes a list of arguments in this form, then passing it to this macro.
33macro_rules! apply_params {
34    ($macro:ident) => {
35        $macro! {
36            // #[doc] name (id) = default,
37            /// Milliseconds, disabled if zero
38            max_idle_timeout(MaxIdleTimeout) = 0,
39            /// Limits the size of UDP payloads that the endpoint is willing to receive
40            max_udp_payload_size(MaxUdpPayloadSize) = 65527,
41
42            /// Initial value for the maximum amount of data that can be sent on the connection
43            initial_max_data(InitialMaxData) = 0,
44            /// Initial flow control limit for locally-initiated bidirectional streams
45            initial_max_stream_data_bidi_local(InitialMaxStreamDataBidiLocal) = 0,
46            /// Initial flow control limit for peer-initiated bidirectional streams
47            initial_max_stream_data_bidi_remote(InitialMaxStreamDataBidiRemote) = 0,
48            /// Initial flow control limit for unidirectional streams
49            initial_max_stream_data_uni(InitialMaxStreamDataUni) = 0,
50
51            /// Initial maximum number of bidirectional streams the peer may initiate
52            initial_max_streams_bidi(InitialMaxStreamsBidi) = 0,
53            /// Initial maximum number of unidirectional streams the peer may initiate
54            initial_max_streams_uni(InitialMaxStreamsUni) = 0,
55
56            /// Exponent used to decode the ACK Delay field in the ACK frame
57            ack_delay_exponent(AckDelayExponent) = 3,
58            /// Maximum amount of time in milliseconds by which the endpoint will delay sending
59            /// acknowledgments
60            max_ack_delay(MaxAckDelay) = 25,
61            /// Maximum number of connection IDs from the peer that an endpoint is willing to store
62            active_connection_id_limit(ActiveConnectionIdLimit) = 2,
63        }
64    };
65}
66
67macro_rules! make_struct {
68    {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => {
69        /// Transport parameters used to negotiate connection-level preferences between peers
70        #[derive(Debug, Clone, Eq, PartialEq)]
71        pub struct TransportParameters {
72            $($(#[$doc])* pub(crate) $name : VarInt,)*
73
74            /// Does the endpoint support active connection migration
75            pub(crate) disable_active_migration: bool,
76            /// Maximum size for datagram frames
77            pub(crate) max_datagram_frame_size: Option<VarInt>,
78            /// The value that the endpoint included in the Source Connection ID field of the first
79            /// Initial packet it sends for the connection
80            pub(crate) initial_src_cid: Option<ConnectionId>,
81            /// The endpoint is willing to receive QUIC packets containing any value for the fixed
82            /// bit
83            pub(crate) grease_quic_bit: bool,
84
85            /// Minimum amount of time in microseconds by which the endpoint is able to delay
86            /// sending acknowledgments
87            ///
88            /// If a value is provided, it implies that the endpoint supports QUIC Acknowledgement
89            /// Frequency
90            pub(crate) min_ack_delay: Option<VarInt>,
91
92            /// NAT traversal configuration for this connection
93            ///
94            /// When present, indicates support for QUIC NAT traversal extension
95            pub(crate) nat_traversal: Option<NatTraversalConfig>,
96
97            // Server-only
98            /// The value of the Destination Connection ID field from the first Initial packet sent
99            /// by the client
100            pub(crate) original_dst_cid: Option<ConnectionId>,
101            /// The value that the server included in the Source Connection ID field of a Retry
102            /// packet
103            pub(crate) retry_src_cid: Option<ConnectionId>,
104            /// Token used by the client to verify a stateless reset from the server
105            pub(crate) stateless_reset_token: Option<ResetToken>,
106            /// The server's preferred address for communication after handshake completion
107            pub(crate) preferred_address: Option<PreferredAddress>,
108            /// The randomly generated reserved transport parameter to sustain future extensibility
109            /// of transport parameter extensions.
110            /// When present, it is included during serialization but ignored during deserialization.
111            pub(crate) grease_transport_parameter: Option<ReservedTransportParameter>,
112
113            /// Defines the order in which transport parameters are serialized.
114            ///
115            /// This field is initialized only for outgoing `TransportParameters` instances and
116            /// is set to `None` for `TransportParameters` received from a peer.
117            pub(crate) write_order: Option<[u8; TransportParameterId::SUPPORTED.len()]>,
118        }
119
120        // We deliberately don't implement the `Default` trait, since that would be public, and
121        // downstream crates should never construct `TransportParameters` except by decoding those
122        // supplied by a peer.
123        impl TransportParameters {
124            /// Standard defaults, used if the peer does not supply a given parameter.
125            pub(crate) fn default() -> Self {
126                Self {
127                    $($name: VarInt::from_u32($default),)*
128
129                    disable_active_migration: false,
130                    max_datagram_frame_size: None,
131                    initial_src_cid: None,
132                    grease_quic_bit: false,
133                    min_ack_delay: None,
134                    nat_traversal: None,
135
136                    original_dst_cid: None,
137                    retry_src_cid: None,
138                    stateless_reset_token: None,
139                    preferred_address: None,
140                    grease_transport_parameter: None,
141                    write_order: None,
142                }
143            }
144        }
145    }
146}
147
148apply_params!(make_struct);
149
150impl TransportParameters {
151    pub(crate) fn new(
152        config: &TransportConfig,
153        endpoint_config: &EndpointConfig,
154        cid_gen: &dyn ConnectionIdGenerator,
155        initial_src_cid: ConnectionId,
156        server_config: Option<&ServerConfig>,
157        rng: &mut impl RngCore,
158    ) -> Self {
159        Self {
160            initial_src_cid: Some(initial_src_cid),
161            initial_max_streams_bidi: config.max_concurrent_bidi_streams,
162            initial_max_streams_uni: config.max_concurrent_uni_streams,
163            initial_max_data: config.receive_window,
164            initial_max_stream_data_bidi_local: config.stream_receive_window,
165            initial_max_stream_data_bidi_remote: config.stream_receive_window,
166            initial_max_stream_data_uni: config.stream_receive_window,
167            max_udp_payload_size: endpoint_config.max_udp_payload_size,
168            max_idle_timeout: config.max_idle_timeout.unwrap_or(VarInt(0)),
169            disable_active_migration: server_config.is_some_and(|c| !c.migration),
170            active_connection_id_limit: if cid_gen.cid_len() == 0 {
171                2 // i.e. default, i.e. unsent
172            } else {
173                CidQueue::LEN as u32
174            }
175            .into(),
176            max_datagram_frame_size: config
177                .datagram_receive_buffer_size
178                .map(|x| (x.min(u16::MAX.into()) as u16).into()),
179            grease_quic_bit: endpoint_config.grease_quic_bit,
180            min_ack_delay: Some(
181                VarInt::from_u64(u64::try_from(TIMER_GRANULARITY.as_micros()).unwrap()).unwrap(),
182            ),
183            grease_transport_parameter: Some(ReservedTransportParameter::random(rng)),
184            write_order: Some({
185                let mut order = std::array::from_fn(|i| i as u8);
186                order.shuffle(rng);
187                order
188            }),
189            nat_traversal: config.nat_traversal_config.clone(),
190            ..Self::default()
191        }
192    }
193
194    /// Check that these parameters are legal when resuming from
195    /// certain cached parameters
196    pub(crate) fn validate_resumption_from(&self, cached: &Self) -> Result<(), TransportError> {
197        if cached.active_connection_id_limit > self.active_connection_id_limit
198            || cached.initial_max_data > self.initial_max_data
199            || cached.initial_max_stream_data_bidi_local > self.initial_max_stream_data_bidi_local
200            || cached.initial_max_stream_data_bidi_remote > self.initial_max_stream_data_bidi_remote
201            || cached.initial_max_stream_data_uni > self.initial_max_stream_data_uni
202            || cached.initial_max_streams_bidi > self.initial_max_streams_bidi
203            || cached.initial_max_streams_uni > self.initial_max_streams_uni
204            || cached.max_datagram_frame_size > self.max_datagram_frame_size
205            || cached.grease_quic_bit && !self.grease_quic_bit
206        {
207            return Err(TransportError::PROTOCOL_VIOLATION(
208                "0-RTT accepted with incompatible transport parameters",
209            ));
210        }
211        Ok(())
212    }
213
214    /// Maximum number of CIDs to issue to this peer
215    ///
216    /// Consider both a) the active_connection_id_limit from the other end; and
217    /// b) LOC_CID_COUNT used locally
218    pub(crate) fn issue_cids_limit(&self) -> u64 {
219        self.active_connection_id_limit.0.min(LOC_CID_COUNT)
220    }
221
222    /// Get the NAT traversal configuration for this connection
223    ///
224    /// This is a public accessor method for tests and external code that need to
225    /// examine the negotiated NAT traversal parameters.
226    pub fn nat_traversal_config(&self) -> Option<&NatTraversalConfig> {
227        self.nat_traversal.as_ref()
228    }
229}
230
231/// NAT traversal configuration for a QUIC connection
232///
233/// This configuration is negotiated as part of the transport parameters and
234/// enables QUIC NAT traversal extension functionality.
235#[derive(Debug, Clone, Eq, PartialEq)]
236pub struct NatTraversalConfig {
237    /// Role of this endpoint in NAT traversal coordination
238    pub(crate) role: NatTraversalRole,
239    /// Maximum number of candidate addresses to exchange
240    pub(crate) max_candidates: VarInt,
241    /// Timeout for coordination protocol in milliseconds
242    pub(crate) coordination_timeout: VarInt,
243    /// Maximum number of concurrent traversal attempts
244    pub(crate) max_concurrent_attempts: VarInt,
245    /// Peer ID for this endpoint (used for relay functionality)
246    pub(crate) peer_id: Option<[u8; 32]>,
247}
248
249// Note: NatTraversalConfig is encoded/decoded according to draft-seemann-quic-nat-traversal-01
250// which uses a simple format (empty value from client, 1-byte concurrency limit from server)
251// rather than a complex custom encoding.
252impl NatTraversalConfig {
253
254    /// Create a new NAT traversal configuration
255    ///
256    /// This is a public constructor for creating NAT traversal configurations
257    /// in tests and external code.
258    pub fn new(
259        role: NatTraversalRole,
260        max_candidates: VarInt,
261        coordination_timeout: VarInt,
262        max_concurrent_attempts: VarInt,
263        peer_id: Option<[u8; 32]>,
264    ) -> Self {
265        Self {
266            role,
267            max_candidates,
268            coordination_timeout,
269            max_concurrent_attempts,
270            peer_id,
271        }
272    }
273
274    /// Get the role for this NAT traversal configuration
275    pub fn role(&self) -> NatTraversalRole {
276        self.role
277    }
278
279    /// Get the maximum number of candidates
280    pub fn max_candidates(&self) -> VarInt {
281        self.max_candidates
282    }
283
284    /// Get the coordination timeout
285    pub fn coordination_timeout(&self) -> VarInt {
286        self.coordination_timeout
287    }
288
289    /// Get the maximum concurrent attempts
290    pub fn max_concurrent_attempts(&self) -> VarInt {
291        self.max_concurrent_attempts
292    }
293
294    /// Get the peer ID
295    pub fn peer_id(&self) -> Option<[u8; 32]> {
296        self.peer_id
297    }
298
299    /// Validate NAT traversal configuration for consistency
300    pub fn validate(&self) -> Result<(), Error> {
301        // Validate max_candidates is reasonable
302        if self.max_candidates.0 == 0 || self.max_candidates.0 > 100 {
303            return Err(Error::IllegalValue);
304        }
305
306        // Validate coordination timeout is reasonable (1s to 60s)
307        if self.coordination_timeout.0 < 1000 || self.coordination_timeout.0 > 60000 {
308            return Err(Error::IllegalValue);
309        }
310
311        // Validate max_concurrent_attempts is reasonable
312        if self.max_concurrent_attempts.0 == 0 || self.max_concurrent_attempts.0 > 10 {
313            return Err(Error::IllegalValue);
314        }
315
316        Ok(())
317    }
318}
319
320impl Default for NatTraversalConfig {
321    fn default() -> Self {
322        Self {
323            role: NatTraversalRole::Client,
324            max_candidates: VarInt::from_u32(8),
325            coordination_timeout: VarInt::from_u32(10000), // 10 seconds
326            max_concurrent_attempts: VarInt::from_u32(3),
327            peer_id: None,
328        }
329    }
330}
331
332/// Role of an endpoint in NAT traversal coordination
333#[derive(Debug, Copy, Clone, Eq, PartialEq)]
334pub enum NatTraversalRole {
335    /// Client endpoint (initiates connections, on-demand)
336    Client,
337    /// Server endpoint (accepts connections, always reachable)
338    Server { 
339        /// Whether this server can act as a relay for other connections
340        can_relay: bool,
341    },
342    /// Bootstrap/relay endpoint (publicly reachable, coordinates traversal)
343    Bootstrap,
344}
345
346/// A server's preferred address
347///
348/// This is communicated as a transport parameter during TLS session establishment.
349#[derive(Debug, Copy, Clone, Eq, PartialEq)]
350pub(crate) struct PreferredAddress {
351    pub(crate) address_v4: Option<SocketAddrV4>,
352    pub(crate) address_v6: Option<SocketAddrV6>,
353    pub(crate) connection_id: ConnectionId,
354    pub(crate) stateless_reset_token: ResetToken,
355}
356
357impl PreferredAddress {
358    fn wire_size(&self) -> u16 {
359        4 + 2 + 16 + 2 + 1 + self.connection_id.len() as u16 + 16
360    }
361
362    fn write<W: BufMut>(&self, w: &mut W) {
363        w.write(self.address_v4.map_or(Ipv4Addr::UNSPECIFIED, |x| *x.ip()));
364        w.write::<u16>(self.address_v4.map_or(0, |x| x.port()));
365        w.write(self.address_v6.map_or(Ipv6Addr::UNSPECIFIED, |x| *x.ip()));
366        w.write::<u16>(self.address_v6.map_or(0, |x| x.port()));
367        w.write::<u8>(self.connection_id.len() as u8);
368        w.put_slice(&self.connection_id);
369        w.put_slice(&self.stateless_reset_token);
370    }
371
372    fn read<R: Buf>(r: &mut R) -> Result<Self, Error> {
373        let ip_v4 = r.get::<Ipv4Addr>()?;
374        let port_v4 = r.get::<u16>()?;
375        let ip_v6 = r.get::<Ipv6Addr>()?;
376        let port_v6 = r.get::<u16>()?;
377        let cid_len = r.get::<u8>()?;
378        if r.remaining() < cid_len as usize || cid_len > MAX_CID_SIZE as u8 {
379            return Err(Error::Malformed);
380        }
381        let mut stage = [0; MAX_CID_SIZE];
382        r.copy_to_slice(&mut stage[0..cid_len as usize]);
383        let cid = ConnectionId::new(&stage[0..cid_len as usize]);
384        if r.remaining() < 16 {
385            return Err(Error::Malformed);
386        }
387        let mut token = [0; RESET_TOKEN_SIZE];
388        r.copy_to_slice(&mut token);
389        let address_v4 = if ip_v4.is_unspecified() && port_v4 == 0 {
390            None
391        } else {
392            Some(SocketAddrV4::new(ip_v4, port_v4))
393        };
394        let address_v6 = if ip_v6.is_unspecified() && port_v6 == 0 {
395            None
396        } else {
397            Some(SocketAddrV6::new(ip_v6, port_v6, 0, 0))
398        };
399        if address_v4.is_none() && address_v6.is_none() {
400            return Err(Error::IllegalValue);
401        }
402        Ok(Self {
403            address_v4,
404            address_v6,
405            connection_id: cid,
406            stateless_reset_token: token.into(),
407        })
408    }
409}
410
411/// Errors encountered while decoding `TransportParameters`
412#[derive(Debug, Copy, Clone, Eq, PartialEq, Error)]
413pub enum Error {
414    /// Parameters that are semantically invalid
415    #[error("parameter had illegal value")]
416    IllegalValue,
417    /// Catch-all error for problems while decoding transport parameters
418    #[error("parameters were malformed")]
419    Malformed,
420}
421
422impl From<Error> for TransportError {
423    fn from(e: Error) -> Self {
424        match e {
425            Error::IllegalValue => Self::TRANSPORT_PARAMETER_ERROR("illegal value"),
426            Error::Malformed => Self::TRANSPORT_PARAMETER_ERROR("malformed"),
427        }
428    }
429}
430
431impl From<UnexpectedEnd> for Error {
432    fn from(_: UnexpectedEnd) -> Self {
433        Self::Malformed
434    }
435}
436
437impl TransportParameters {
438    /// Encode `TransportParameters` into buffer
439    pub fn write<W: BufMut>(&self, w: &mut W) {
440        for idx in self
441            .write_order
442            .as_ref()
443            .unwrap_or(&std::array::from_fn(|i| i as u8))
444        {
445            let id = TransportParameterId::SUPPORTED[*idx as usize];
446            match id {
447                TransportParameterId::ReservedTransportParameter => {
448                    if let Some(param) = self.grease_transport_parameter {
449                        param.write(w);
450                    }
451                }
452                TransportParameterId::StatelessResetToken => {
453                    if let Some(ref x) = self.stateless_reset_token {
454                        w.write_var(id as u64);
455                        w.write_var(16);
456                        w.put_slice(x);
457                    }
458                }
459                TransportParameterId::DisableActiveMigration => {
460                    if self.disable_active_migration {
461                        w.write_var(id as u64);
462                        w.write_var(0);
463                    }
464                }
465                TransportParameterId::MaxDatagramFrameSize => {
466                    if let Some(x) = self.max_datagram_frame_size {
467                        w.write_var(id as u64);
468                        w.write_var(x.size() as u64);
469                        w.write(x);
470                    }
471                }
472                TransportParameterId::PreferredAddress => {
473                    if let Some(ref x) = self.preferred_address {
474                        w.write_var(id as u64);
475                        w.write_var(x.wire_size() as u64);
476                        x.write(w);
477                    }
478                }
479                TransportParameterId::OriginalDestinationConnectionId => {
480                    if let Some(ref cid) = self.original_dst_cid {
481                        w.write_var(id as u64);
482                        w.write_var(cid.len() as u64);
483                        w.put_slice(cid);
484                    }
485                }
486                TransportParameterId::InitialSourceConnectionId => {
487                    if let Some(ref cid) = self.initial_src_cid {
488                        w.write_var(id as u64);
489                        w.write_var(cid.len() as u64);
490                        w.put_slice(cid);
491                    }
492                }
493                TransportParameterId::RetrySourceConnectionId => {
494                    if let Some(ref cid) = self.retry_src_cid {
495                        w.write_var(id as u64);
496                        w.write_var(cid.len() as u64);
497                        w.put_slice(cid);
498                    }
499                }
500                TransportParameterId::GreaseQuicBit => {
501                    if self.grease_quic_bit {
502                        w.write_var(id as u64);
503                        w.write_var(0);
504                    }
505                }
506                TransportParameterId::MinAckDelayDraft07 => {
507                    if let Some(x) = self.min_ack_delay {
508                        w.write_var(id as u64);
509                        w.write_var(x.size() as u64);
510                        w.write(x);
511                    }
512                }
513                TransportParameterId::NatTraversal => {
514                    if let Some(ref config) = self.nat_traversal {
515                        // Per draft-seemann-quic-nat-traversal-01:
516                        // - Client sends empty value to indicate support
517                        // - Server sends concurrency limit (1 byte)
518                        match config.role {
519                            NatTraversalRole::Client => {
520                                // Client sends empty value
521                                w.write_var(id as u64);
522                                w.write_var(0); // Empty value
523                            }
524                            NatTraversalRole::Server { can_relay: _ } => {
525                                // Server sends concurrency limit
526                                w.write_var(id as u64);
527                                w.write_var(1); // 1 byte for concurrency limit
528                                // Use max_concurrent_attempts as concurrency limit
529                                let limit = config.max_concurrent_attempts.0.min(255) as u8;
530                                w.put_u8(limit);
531                            }
532                            NatTraversalRole::Bootstrap => {
533                                // Bootstrap endpoints act as servers
534                                w.write_var(id as u64);
535                                w.write_var(1); // 1 byte for concurrency limit
536                                let limit = config.max_concurrent_attempts.0.min(255) as u8;
537                                w.put_u8(limit);
538                            }
539                        }
540                    }
541                }
542                id => {
543                    macro_rules! write_params {
544                        {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => {
545                            match id {
546                                $(TransportParameterId::$id => {
547                                    if self.$name.0 != $default {
548                                        w.write_var(id as u64);
549                                        w.write(VarInt::try_from(self.$name.size()).unwrap());
550                                        w.write(self.$name);
551                                    }
552                                })*,
553                                _ => {
554                                    // This should never be reached for supported parameters
555                                    // All supported parameters should be handled in specific match arms above
556                                    panic!("Unsupported transport parameter reached write implementation: {id:?}");
557                                }
558                            }
559                        }
560                    }
561                    apply_params!(write_params);
562                }
563            }
564        }
565    }
566
567    /// Decode `TransportParameters` from buffer
568    pub fn read<R: Buf>(side: Side, r: &mut R) -> Result<Self, Error> {
569        // Initialize to protocol-specified defaults
570        let mut params = Self::default();
571
572        // State to check for duplicate transport parameters.
573        macro_rules! param_state {
574            {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => {{
575                struct ParamState {
576                    $($name: bool,)*
577                }
578
579                ParamState {
580                    $($name: false,)*
581                }
582            }}
583        }
584        let mut got = apply_params!(param_state);
585
586        while r.has_remaining() {
587            let id = r.get_var()?;
588            let len = r.get_var()?;
589            if (r.remaining() as u64) < len {
590                return Err(Error::Malformed);
591            }
592            let len = len as usize;
593            let Ok(id) = TransportParameterId::try_from(id) else {
594                // unknown transport parameters are ignored
595                r.advance(len);
596                continue;
597            };
598
599            match id {
600                TransportParameterId::OriginalDestinationConnectionId => {
601                    decode_cid(len, &mut params.original_dst_cid, r)?
602                }
603                TransportParameterId::StatelessResetToken => {
604                    if len != 16 || params.stateless_reset_token.is_some() {
605                        return Err(Error::Malformed);
606                    }
607                    let mut tok = [0; RESET_TOKEN_SIZE];
608                    r.copy_to_slice(&mut tok);
609                    params.stateless_reset_token = Some(tok.into());
610                }
611                TransportParameterId::DisableActiveMigration => {
612                    if len != 0 || params.disable_active_migration {
613                        return Err(Error::Malformed);
614                    }
615                    params.disable_active_migration = true;
616                }
617                TransportParameterId::PreferredAddress => {
618                    if params.preferred_address.is_some() {
619                        return Err(Error::Malformed);
620                    }
621                    params.preferred_address = Some(PreferredAddress::read(&mut r.take(len))?);
622                }
623                TransportParameterId::InitialSourceConnectionId => {
624                    decode_cid(len, &mut params.initial_src_cid, r)?
625                }
626                TransportParameterId::RetrySourceConnectionId => {
627                    decode_cid(len, &mut params.retry_src_cid, r)?
628                }
629                TransportParameterId::MaxDatagramFrameSize => {
630                    if len > 8 || params.max_datagram_frame_size.is_some() {
631                        return Err(Error::Malformed);
632                    }
633                    params.max_datagram_frame_size = Some(r.get().unwrap());
634                }
635                TransportParameterId::GreaseQuicBit => match len {
636                    0 => params.grease_quic_bit = true,
637                    _ => return Err(Error::Malformed),
638                },
639                TransportParameterId::MinAckDelayDraft07 => {
640                    params.min_ack_delay = Some(r.get().unwrap())
641                }
642                TransportParameterId::NatTraversal => {
643                    if params.nat_traversal.is_some() {
644                        return Err(Error::Malformed);
645                    }
646                    // Per draft-seemann-quic-nat-traversal-01:
647                    // - Empty value (len=0) from client indicates support
648                    // - 1 byte value from server is concurrency limit
649                    match (side, len) {
650                        (Side::Server, 0) => {
651                            // Client sent empty value - they support NAT traversal
652                            params.nat_traversal = Some(NatTraversalConfig {
653                                role: NatTraversalRole::Client,
654                                max_candidates: VarInt::from_u32(8), // Default
655                                coordination_timeout: VarInt::from_u32(10000), // Default 10s
656                                max_concurrent_attempts: VarInt::from_u32(3), // Default
657                                peer_id: None,
658                            });
659                        }
660                        (Side::Client, 1) => {
661                            // Server sent concurrency limit
662                            let limit = r.get::<u8>()?;
663                            params.nat_traversal = Some(NatTraversalConfig {
664                                role: NatTraversalRole::Server { can_relay: false }, // Determined later
665                                max_candidates: VarInt::from_u32(8), // Default
666                                coordination_timeout: VarInt::from_u32(10000), // Default 10s
667                                max_concurrent_attempts: VarInt::from_u32(limit as u32),
668                                peer_id: None,
669                            });
670                        }
671                        _ => {
672                            // Invalid combination
673                            return Err(Error::Malformed);
674                        }
675                    }
676                }
677                _ => {
678                    macro_rules! parse {
679                        {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => {
680                            match id {
681                                $(TransportParameterId::$id => {
682                                    let value = r.get::<VarInt>()?;
683                                    if len != value.size() || got.$name { return Err(Error::Malformed); }
684                                    params.$name = value.into();
685                                    got.$name = true;
686                                })*
687                                _ => r.advance(len),
688                            }
689                        }
690                    }
691                    apply_params!(parse);
692                }
693            }
694        }
695
696        // Semantic validation
697
698        // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-4.26.1
699        if params.ack_delay_exponent.0 > 20
700            // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-4.28.1
701            || params.max_ack_delay.0 >= 1 << 14
702            // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-6.2.1
703            || params.active_connection_id_limit.0 < 2
704            // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-4.10.1
705            || params.max_udp_payload_size.0 < 1200
706            // https://www.rfc-editor.org/rfc/rfc9000.html#section-4.6-2
707            || params.initial_max_streams_bidi.0 > MAX_STREAM_COUNT
708            || params.initial_max_streams_uni.0 > MAX_STREAM_COUNT
709            // https://www.ietf.org/archive/id/draft-ietf-quic-ack-frequency-08.html#section-3-4
710            || params.min_ack_delay.is_some_and(|min_ack_delay| {
711                // min_ack_delay uses microseconds, whereas max_ack_delay uses milliseconds
712                min_ack_delay.0 > params.max_ack_delay.0 * 1_000
713            })
714            // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-8
715            || (side.is_server()
716                && (params.original_dst_cid.is_some()
717                    || params.preferred_address.is_some()
718                    || params.retry_src_cid.is_some()
719                    || params.stateless_reset_token.is_some()))
720            // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-4.38.1
721            || params
722                .preferred_address.is_some_and(|x| x.connection_id.is_empty())
723        {
724            return Err(Error::IllegalValue);
725        }
726
727        // NAT traversal parameter validation
728        if let Some(ref nat_config) = params.nat_traversal {
729            // Validate NAT traversal configuration
730            if let Err(_) = nat_config.validate() {
731                return Err(Error::IllegalValue);
732            }
733
734            // Validate role-specific constraints
735            match nat_config.role {
736                NatTraversalRole::Server { .. } | NatTraversalRole::Bootstrap => {
737                    // Server/Bootstrap roles should only be received by clients
738                    if side.is_server() {
739                        return Err(Error::IllegalValue);
740                    }
741                }
742                NatTraversalRole::Client => {
743                    // Client role should only be received by servers
744                    if side.is_client() {
745                        return Err(Error::IllegalValue);
746                    }
747                }
748            }
749        }
750
751        Ok(params)
752    }
753}
754
755/// A reserved transport parameter.
756///
757/// It has an identifier of the form 31 * N + 27 for the integer value of N.
758/// Such identifiers are reserved to exercise the requirement that unknown transport parameters be ignored.
759/// The reserved transport parameter has no semantics and can carry arbitrary values.
760/// It may be included in transport parameters sent to the peer, and should be ignored when received.
761///
762/// See spec: <https://www.rfc-editor.org/rfc/rfc9000.html#section-18.1>
763#[derive(Debug, Copy, Clone, Eq, PartialEq)]
764pub(crate) struct ReservedTransportParameter {
765    /// The reserved identifier of the transport parameter
766    id: VarInt,
767
768    /// Buffer to store the parameter payload
769    payload: [u8; Self::MAX_PAYLOAD_LEN],
770
771    /// The number of bytes to include in the wire format from the `payload` buffer
772    payload_len: usize,
773}
774
775impl ReservedTransportParameter {
776    /// Generates a transport parameter with a random payload and a reserved ID.
777    ///
778    /// The implementation is inspired by quic-go and quiche:
779    /// 1. <https://github.com/quic-go/quic-go/blob/3e0a67b2476e1819752f04d75968de042b197b56/internal/wire/transport_parameters.go#L338-L344>
780    /// 2. <https://github.com/google/quiche/blob/cb1090b20c40e2f0815107857324e99acf6ec567/quiche/quic/core/crypto/transport_parameters.cc#L843-L860>
781    fn random(rng: &mut impl RngCore) -> Self {
782        let id = Self::generate_reserved_id(rng);
783
784        let payload_len = rng.gen_range(0..Self::MAX_PAYLOAD_LEN);
785
786        let payload = {
787            let mut slice = [0u8; Self::MAX_PAYLOAD_LEN];
788            rng.fill_bytes(&mut slice[..payload_len]);
789            slice
790        };
791
792        Self {
793            id,
794            payload,
795            payload_len,
796        }
797    }
798
799    fn write(&self, w: &mut impl BufMut) {
800        w.write_var(self.id.0);
801        w.write_var(self.payload_len as u64);
802        w.put_slice(&self.payload[..self.payload_len]);
803    }
804
805    /// Generates a random reserved identifier of the form `31 * N + 27`, as required by RFC 9000.
806    /// Reserved transport parameter identifiers are used to test compliance with the requirement
807    /// that unknown transport parameters must be ignored by peers.
808    /// See: <https://www.rfc-editor.org/rfc/rfc9000.html#section-18.1> and <https://www.rfc-editor.org/rfc/rfc9000.html#section-22.3>
809    fn generate_reserved_id(rng: &mut impl RngCore) -> VarInt {
810        let id = {
811            let rand = rng.gen_range(0u64..(1 << 62) - 27);
812            let n = rand / 31;
813            31 * n + 27
814        };
815        debug_assert!(
816            id % 31 == 27,
817            "generated id does not have the form of 31 * N + 27"
818        );
819        VarInt::from_u64(id).expect(
820            "generated id does fit into range of allowed transport parameter IDs: [0; 2^62)",
821        )
822    }
823
824    /// The maximum length of the payload to include as the parameter payload.
825    /// This value is not a specification-imposed limit but is chosen to match
826    /// the limit used by other implementations of QUIC, e.g., quic-go and quiche.
827    const MAX_PAYLOAD_LEN: usize = 16;
828}
829
830#[repr(u64)]
831#[derive(Debug, Clone, Copy, PartialEq, Eq)]
832pub(crate) enum TransportParameterId {
833    // https://www.rfc-editor.org/rfc/rfc9000.html#iana-tp-table
834    OriginalDestinationConnectionId = 0x00,
835    MaxIdleTimeout = 0x01,
836    StatelessResetToken = 0x02,
837    MaxUdpPayloadSize = 0x03,
838    InitialMaxData = 0x04,
839    InitialMaxStreamDataBidiLocal = 0x05,
840    InitialMaxStreamDataBidiRemote = 0x06,
841    InitialMaxStreamDataUni = 0x07,
842    InitialMaxStreamsBidi = 0x08,
843    InitialMaxStreamsUni = 0x09,
844    AckDelayExponent = 0x0A,
845    MaxAckDelay = 0x0B,
846    DisableActiveMigration = 0x0C,
847    PreferredAddress = 0x0D,
848    ActiveConnectionIdLimit = 0x0E,
849    InitialSourceConnectionId = 0x0F,
850    RetrySourceConnectionId = 0x10,
851
852    // Smallest possible ID of reserved transport parameter https://datatracker.ietf.org/doc/html/rfc9000#section-22.3
853    ReservedTransportParameter = 0x1B,
854
855    // https://www.rfc-editor.org/rfc/rfc9221.html#section-3
856    MaxDatagramFrameSize = 0x20,
857
858    // https://www.rfc-editor.org/rfc/rfc9287.html#section-3
859    GreaseQuicBit = 0x2AB2,
860
861    // https://datatracker.ietf.org/doc/html/draft-ietf-quic-ack-frequency#section-10.1
862    MinAckDelayDraft07 = 0xFF04DE1B,
863
864    // NAT Traversal Extension - draft-seemann-quic-nat-traversal-01
865    // Transport parameter ID from the IETF draft specification
866    NatTraversal = 0x3d7e9f0bca12fea6,
867}
868
869impl TransportParameterId {
870    /// Array with all supported transport parameter IDs
871    const SUPPORTED: [Self; 22] = [
872        Self::MaxIdleTimeout,
873        Self::MaxUdpPayloadSize,
874        Self::InitialMaxData,
875        Self::InitialMaxStreamDataBidiLocal,
876        Self::InitialMaxStreamDataBidiRemote,
877        Self::InitialMaxStreamDataUni,
878        Self::InitialMaxStreamsBidi,
879        Self::InitialMaxStreamsUni,
880        Self::AckDelayExponent,
881        Self::MaxAckDelay,
882        Self::ActiveConnectionIdLimit,
883        Self::ReservedTransportParameter,
884        Self::StatelessResetToken,
885        Self::DisableActiveMigration,
886        Self::MaxDatagramFrameSize,
887        Self::PreferredAddress,
888        Self::OriginalDestinationConnectionId,
889        Self::InitialSourceConnectionId,
890        Self::RetrySourceConnectionId,
891        Self::GreaseQuicBit,
892        Self::MinAckDelayDraft07,
893        Self::NatTraversal,
894    ];
895}
896
897impl std::cmp::PartialEq<u64> for TransportParameterId {
898    fn eq(&self, other: &u64) -> bool {
899        *other == (*self as u64)
900    }
901}
902
903impl TryFrom<u64> for TransportParameterId {
904    type Error = ();
905
906    fn try_from(value: u64) -> Result<Self, Self::Error> {
907        let param = match value {
908            id if Self::MaxIdleTimeout == id => Self::MaxIdleTimeout,
909            id if Self::MaxUdpPayloadSize == id => Self::MaxUdpPayloadSize,
910            id if Self::InitialMaxData == id => Self::InitialMaxData,
911            id if Self::InitialMaxStreamDataBidiLocal == id => Self::InitialMaxStreamDataBidiLocal,
912            id if Self::InitialMaxStreamDataBidiRemote == id => {
913                Self::InitialMaxStreamDataBidiRemote
914            }
915            id if Self::InitialMaxStreamDataUni == id => Self::InitialMaxStreamDataUni,
916            id if Self::InitialMaxStreamsBidi == id => Self::InitialMaxStreamsBidi,
917            id if Self::InitialMaxStreamsUni == id => Self::InitialMaxStreamsUni,
918            id if Self::AckDelayExponent == id => Self::AckDelayExponent,
919            id if Self::MaxAckDelay == id => Self::MaxAckDelay,
920            id if Self::ActiveConnectionIdLimit == id => Self::ActiveConnectionIdLimit,
921            id if Self::ReservedTransportParameter == id => Self::ReservedTransportParameter,
922            id if Self::StatelessResetToken == id => Self::StatelessResetToken,
923            id if Self::DisableActiveMigration == id => Self::DisableActiveMigration,
924            id if Self::MaxDatagramFrameSize == id => Self::MaxDatagramFrameSize,
925            id if Self::PreferredAddress == id => Self::PreferredAddress,
926            id if Self::OriginalDestinationConnectionId == id => {
927                Self::OriginalDestinationConnectionId
928            }
929            id if Self::InitialSourceConnectionId == id => Self::InitialSourceConnectionId,
930            id if Self::RetrySourceConnectionId == id => Self::RetrySourceConnectionId,
931            id if Self::GreaseQuicBit == id => Self::GreaseQuicBit,
932            id if Self::MinAckDelayDraft07 == id => Self::MinAckDelayDraft07,
933            id if Self::NatTraversal == id => Self::NatTraversal,
934            _ => return Err(()),
935        };
936        Ok(param)
937    }
938}
939
940fn decode_cid(len: usize, value: &mut Option<ConnectionId>, r: &mut impl Buf) -> Result<(), Error> {
941    if len > MAX_CID_SIZE || value.is_some() || r.remaining() < len {
942        return Err(Error::Malformed);
943    }
944
945    *value = Some(ConnectionId::from_buf(r, len));
946    Ok(())
947}
948
949#[cfg(test)]
950mod test {
951    use super::*;
952
953    #[test]
954    fn test_nat_traversal_transport_parameter_encoding_decoding() {
955        // Test draft-compliant NAT traversal parameter encoding/decoding
956        
957        // Test 1: Client sends empty value, server reads it
958        let client_config = NatTraversalConfig {
959            role: NatTraversalRole::Client,
960            max_candidates: VarInt::from_u32(8),
961            coordination_timeout: VarInt::from_u32(5000),
962            max_concurrent_attempts: VarInt::from_u32(3),
963            peer_id: None,
964        };
965        
966        let mut client_params = TransportParameters::default();
967        client_params.nat_traversal = Some(client_config);
968        
969        let mut encoded = Vec::new();
970        client_params.write(&mut encoded);
971        
972        // Server reads client params
973        let server_decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
974            .expect("Failed to decode client transport parameters");
975        
976        // Server should see that client supports NAT traversal
977        assert!(server_decoded.nat_traversal.is_some());
978        let server_view = server_decoded.nat_traversal.unwrap();
979        assert!(matches!(server_view.role, NatTraversalRole::Client));
980        
981        // Test 2: Server sends concurrency limit, client reads it
982        let server_config = NatTraversalConfig {
983            role: NatTraversalRole::Server { can_relay: false },
984            max_candidates: VarInt::from_u32(16),
985            coordination_timeout: VarInt::from_u32(10000),
986            max_concurrent_attempts: VarInt::from_u32(5),
987            peer_id: None,
988        };
989        
990        let mut server_params = TransportParameters::default();
991        server_params.nat_traversal = Some(server_config);
992        
993        let mut encoded = Vec::new();
994        server_params.write(&mut encoded);
995        
996        // Client reads server params
997        let client_decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
998            .expect("Failed to decode server transport parameters");
999        
1000        // Client should see server's concurrency limit
1001        assert!(client_decoded.nat_traversal.is_some());
1002        let client_view = client_decoded.nat_traversal.unwrap();
1003        assert!(matches!(client_view.role, NatTraversalRole::Server { .. }));
1004        assert_eq!(client_view.max_concurrent_attempts, VarInt::from_u32(5));
1005    }
1006
1007    #[test]
1008    fn test_nat_traversal_parameter_without_peer_id() {
1009        // Test client-side NAT traversal config (sends empty value)
1010        let config = NatTraversalConfig {
1011            role: NatTraversalRole::Client,
1012            max_candidates: VarInt::from_u32(4),
1013            coordination_timeout: VarInt::from_u32(3000),
1014            max_concurrent_attempts: VarInt::from_u32(2),
1015            peer_id: None,
1016        };
1017        
1018        let mut params = TransportParameters::default();
1019        params.nat_traversal = Some(config);
1020        
1021        let mut encoded = Vec::new();
1022        params.write(&mut encoded);
1023        
1024        // Server reads client's parameters
1025        let decoded_params = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1026            .expect("Failed to decode transport parameters");
1027        
1028        let decoded_config = decoded_params.nat_traversal
1029            .expect("NAT traversal config should be present");
1030        
1031        assert_eq!(decoded_config.role, NatTraversalRole::Client);
1032        assert!(decoded_config.peer_id.is_none());
1033        
1034        // Test server-side NAT traversal config (sends concurrency limit)
1035        let server_config = NatTraversalConfig {
1036            role: NatTraversalRole::Server { can_relay: true },
1037            max_candidates: VarInt::from_u32(8),
1038            coordination_timeout: VarInt::from_u32(5000),
1039            max_concurrent_attempts: VarInt::from_u32(4),
1040            peer_id: None,
1041        };
1042        
1043        let mut server_params = TransportParameters::default();
1044        server_params.nat_traversal = Some(server_config);
1045        
1046        let mut server_encoded = Vec::new();
1047        server_params.write(&mut server_encoded);
1048        
1049        // Client reads server's parameters
1050        let decoded_server_params = TransportParameters::read(Side::Client, &mut server_encoded.as_slice())
1051            .expect("Failed to decode server transport parameters");
1052        
1053        let decoded_server_config = decoded_server_params.nat_traversal
1054            .expect("Server NAT traversal config should be present");
1055        
1056        match decoded_server_config.role {
1057            NatTraversalRole::Server { can_relay } => {
1058                // The protocol doesn't encode can_relay, so it's always false when decoded
1059                assert!(!can_relay);
1060            },
1061            _ => panic!("Expected server role"),
1062        }
1063        assert_eq!(decoded_server_config.max_concurrent_attempts, VarInt::from_u32(4));
1064    }
1065
1066    #[test]
1067    fn test_transport_parameters_without_nat_traversal() {
1068        // Test that transport parameters work without NAT traversal config
1069        let mut params = TransportParameters::default();
1070        params.nat_traversal = None;
1071        
1072        let mut encoded = Vec::new();
1073        params.write(&mut encoded);
1074        
1075        let decoded_params = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1076            .expect("Failed to decode transport parameters");
1077        
1078        assert!(decoded_params.nat_traversal.is_none());
1079    }
1080
1081    #[test]
1082    fn test_nat_traversal_draft_compliant_encoding() {
1083        // Test draft-seemann-quic-nat-traversal-01 compliant encoding
1084        
1085        // Test 1: Client sends empty value
1086        let client_config = NatTraversalConfig {
1087            role: NatTraversalRole::Client,
1088            max_candidates: VarInt::from_u32(8),
1089            coordination_timeout: VarInt::from_u32(10000),
1090            max_concurrent_attempts: VarInt::from_u32(3),
1091            peer_id: None,
1092        };
1093        
1094        let mut client_params = TransportParameters::default();
1095        client_params.nat_traversal = Some(client_config);
1096        
1097        let mut encoded = Vec::new();
1098        client_params.write(&mut encoded);
1099        
1100        // Verify the encoded data contains empty value for client
1101        // Find the NAT traversal parameter in the encoded data
1102        use bytes::Buf;
1103        let mut cursor = &encoded[..];
1104        while cursor.has_remaining() {
1105            let id = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1106            let len = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1107            if id.0 == 0x3d7e9f0bca12fea6 {
1108                // Found NAT traversal parameter
1109                assert_eq!(len.0, 0, "Client should send empty value");
1110                break;
1111            }
1112            // Skip this parameter
1113            cursor.advance(len.0 as usize);
1114        }
1115        
1116        // Test 2: Server sends 1-byte concurrency limit
1117        let server_config = NatTraversalConfig {
1118            role: NatTraversalRole::Server { can_relay: true },
1119            max_candidates: VarInt::from_u32(16),
1120            coordination_timeout: VarInt::from_u32(10000),
1121            max_concurrent_attempts: VarInt::from_u32(5),
1122            peer_id: None,
1123        };
1124        
1125        let mut server_params = TransportParameters::default();
1126        server_params.nat_traversal = Some(server_config);
1127        
1128        let mut encoded = Vec::new();
1129        server_params.write(&mut encoded);
1130        
1131        // Verify the encoded data contains 1-byte value for server
1132        let mut cursor = &encoded[..];
1133        while cursor.has_remaining() {
1134            let id = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1135            let len = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1136            if id.0 == 0x3d7e9f0bca12fea6 {
1137                // Found NAT traversal parameter
1138                assert_eq!(len.0, 1, "Server should send 1-byte value");
1139                let limit = cursor.chunk()[0];
1140                assert_eq!(limit, 5, "Server should send concurrency limit");
1141                break;
1142            }
1143            // Skip this parameter
1144            cursor.advance(len.0 as usize);
1145        }
1146    }
1147
1148    #[test]
1149    fn test_nat_traversal_draft_compliant_decoding() {
1150        use bytes::BufMut;
1151        
1152        // Test 1: Decode empty value from client
1153        let mut buf = Vec::new();
1154        buf.write_var(0x3d7e9f0bca12fea6); // NAT traversal parameter ID
1155        buf.write_var(0); // Empty value
1156        
1157        let params = TransportParameters::read(Side::Server, &mut buf.as_slice())
1158            .expect("Failed to decode transport parameters");
1159        
1160        let config = params.nat_traversal.expect("NAT traversal should be present");
1161        assert_eq!(config.role, NatTraversalRole::Client);
1162        assert_eq!(config.max_candidates, VarInt::from_u32(8)); // Default value
1163        assert_eq!(config.coordination_timeout, VarInt::from_u32(10000)); // Default value
1164        assert_eq!(config.max_concurrent_attempts, VarInt::from_u32(3)); // Default value
1165        
1166        // Test 2: Decode 1-byte concurrency limit from server
1167        let mut buf = Vec::new();
1168        buf.write_var(0x3d7e9f0bca12fea6); // NAT traversal parameter ID
1169        buf.write_var(1); // 1-byte value
1170        buf.put_u8(7); // Concurrency limit of 7
1171        
1172        let params = TransportParameters::read(Side::Client, &mut buf.as_slice())
1173            .expect("Failed to decode transport parameters");
1174        
1175        let config = params.nat_traversal.expect("NAT traversal should be present");
1176        match config.role {
1177            NatTraversalRole::Server { can_relay } => {
1178                assert!(!can_relay); // Default to false
1179            }
1180            _ => panic!("Expected Server role"),
1181        }
1182        assert_eq!(config.max_concurrent_attempts, VarInt::from_u32(7));
1183        
1184        // Test 3: Invalid length should fail
1185        let mut buf = Vec::new();
1186        buf.write_var(0x3d7e9f0bca12fea6); // NAT traversal parameter ID
1187        buf.write_var(2); // Invalid 2-byte value
1188        buf.put_u8(7);
1189        buf.put_u8(8);
1190        
1191        let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1192        assert!(result.is_err(), "Should fail with invalid length");
1193    }
1194
1195    #[test]
1196    fn test_nat_traversal_parameter_id() {
1197        // Verify the correct parameter ID is used
1198        assert_eq!(TransportParameterId::NatTraversal as u64, 0x3d7e9f0bca12fea6);
1199    }
1200
1201    #[test]
1202    fn test_nat_traversal_config_validation() {
1203        // Test valid configuration
1204        let valid_config = NatTraversalConfig {
1205            role: NatTraversalRole::Client,
1206            max_candidates: VarInt::from_u32(8),
1207            coordination_timeout: VarInt::from_u32(5000),
1208            max_concurrent_attempts: VarInt::from_u32(3),
1209            peer_id: None,
1210        };
1211        assert!(valid_config.validate().is_ok());
1212
1213        // Test invalid max_candidates (too low)
1214        let invalid_config = NatTraversalConfig {
1215            max_candidates: VarInt::from_u32(0),
1216            ..valid_config
1217        };
1218        assert!(invalid_config.validate().is_err());
1219
1220        // Test invalid max_candidates (too high)
1221        let invalid_config = NatTraversalConfig {
1222            max_candidates: VarInt::from_u32(101),
1223            ..valid_config
1224        };
1225        assert!(invalid_config.validate().is_err());
1226
1227        // Test invalid coordination_timeout (too low)
1228        let invalid_config = NatTraversalConfig {
1229            coordination_timeout: VarInt::from_u32(500),
1230            ..valid_config
1231        };
1232        assert!(invalid_config.validate().is_err());
1233
1234        // Test invalid coordination_timeout (too high)
1235        let invalid_config = NatTraversalConfig {
1236            coordination_timeout: VarInt::from_u32(70000),
1237            ..valid_config
1238        };
1239        assert!(invalid_config.validate().is_err());
1240
1241        // Test invalid max_concurrent_attempts (too low)
1242        let invalid_config = NatTraversalConfig {
1243            max_concurrent_attempts: VarInt::from_u32(0),
1244            ..valid_config
1245        };
1246        assert!(invalid_config.validate().is_err());
1247
1248        // Test invalid max_concurrent_attempts (too high)
1249        let invalid_config = NatTraversalConfig {
1250            max_concurrent_attempts: VarInt::from_u32(11),
1251            ..valid_config
1252        };
1253        assert!(invalid_config.validate().is_err());
1254    }
1255
1256    #[test]
1257    fn test_nat_traversal_role_validation() {
1258        use bytes::BufMut;
1259        
1260        // Test client role validation - should fail when received by client
1261        let mut buf = Vec::new();
1262        buf.write_var(0x3d7e9f0bca12fea6); // NAT traversal parameter ID
1263        buf.write_var(0); // Empty value (client role)
1264        
1265        // Client receiving client role should fail
1266        let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1267        assert!(result.is_err(), "Client should not accept client role from peer");
1268        
1269        // Server receiving client role should succeed
1270        let result = TransportParameters::read(Side::Server, &mut buf.as_slice());
1271        assert!(result.is_ok(), "Server should accept client role from peer");
1272        
1273        // Test server role validation - should fail when received by server
1274        let mut buf = Vec::new();
1275        buf.write_var(0x3d7e9f0bca12fea6); // NAT traversal parameter ID
1276        buf.write_var(1); // 1-byte value (server role)
1277        buf.put_u8(5); // Concurrency limit
1278        
1279        // Server receiving server role should fail
1280        let result = TransportParameters::read(Side::Server, &mut buf.as_slice());
1281        assert!(result.is_err(), "Server should not accept server role from peer");
1282        
1283        // Client receiving server role should succeed
1284        let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1285        assert!(result.is_ok(), "Client should accept server role from peer");
1286    }
1287
1288    #[test]
1289    fn test_nat_traversal_parameter_combinations() {
1290        // Test that NAT traversal works with other transport parameters
1291        let nat_config = NatTraversalConfig {
1292            role: NatTraversalRole::Client,
1293            max_candidates: VarInt::from_u32(10),
1294            coordination_timeout: VarInt::from_u32(8000),
1295            max_concurrent_attempts: VarInt::from_u32(4),
1296            peer_id: Some([42u8; 32]),
1297        };
1298        
1299        let mut params = TransportParameters::default();
1300        params.nat_traversal = Some(nat_config);
1301        params.max_idle_timeout = VarInt::from_u32(30000);
1302        params.initial_max_data = VarInt::from_u32(1048576);
1303        params.grease_quic_bit = true;
1304        
1305        // Test encoding
1306        let mut encoded = Vec::new();
1307        params.write(&mut encoded);
1308        assert!(!encoded.is_empty());
1309        
1310        // Test decoding
1311        let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1312            .expect("Should decode successfully");
1313        
1314        // Verify NAT traversal config is preserved
1315        let decoded_config = decoded.nat_traversal.expect("NAT traversal should be present");
1316        assert_eq!(decoded_config.role, NatTraversalRole::Client);
1317        assert_eq!(decoded_config.max_candidates, VarInt::from_u32(8)); // Default value
1318        
1319        // Verify other parameters are preserved
1320        assert_eq!(decoded.max_idle_timeout, VarInt::from_u32(30000));
1321        assert_eq!(decoded.initial_max_data, VarInt::from_u32(1048576));
1322        assert!(decoded.grease_quic_bit);
1323    }
1324
1325    #[test]
1326    fn test_nat_traversal_default_config() {
1327        let default_config = NatTraversalConfig::default();
1328        
1329        assert_eq!(default_config.role, NatTraversalRole::Client);
1330        assert_eq!(default_config.max_candidates, VarInt::from_u32(8));
1331        assert_eq!(default_config.coordination_timeout, VarInt::from_u32(10000));
1332        assert_eq!(default_config.max_concurrent_attempts, VarInt::from_u32(3));
1333        assert!(default_config.peer_id.is_none());
1334        
1335        // Default config should be valid
1336        assert!(default_config.validate().is_ok());
1337    }
1338
1339    #[test]
1340    fn test_nat_traversal_endpoint_role_negotiation() {
1341        // Test complete client-server negotiation
1342        
1343        // 1. Client creates parameters with NAT traversal support
1344        let client_config = NatTraversalConfig {
1345            role: NatTraversalRole::Client,
1346            max_candidates: VarInt::from_u32(12),
1347            coordination_timeout: VarInt::from_u32(7000),
1348            max_concurrent_attempts: VarInt::from_u32(5),
1349            peer_id: None,
1350        };
1351        
1352        let mut client_params = TransportParameters::default();
1353        client_params.nat_traversal = Some(client_config);
1354        
1355        // 2. Client encodes and sends to server
1356        let mut client_encoded = Vec::new();
1357        client_params.write(&mut client_encoded);
1358        
1359        // 3. Server receives and decodes client parameters
1360        let server_received = TransportParameters::read(Side::Server, &mut client_encoded.as_slice())
1361            .expect("Server should decode client params");
1362        
1363        // Server should see client role
1364        let server_view = server_received.nat_traversal.expect("NAT traversal should be present");
1365        assert_eq!(server_view.role, NatTraversalRole::Client);
1366        
1367        // 4. Server creates response with server role
1368        let server_config = NatTraversalConfig {
1369            role: NatTraversalRole::Server { can_relay: true },
1370            max_candidates: VarInt::from_u32(16),
1371            coordination_timeout: VarInt::from_u32(12000),
1372            max_concurrent_attempts: VarInt::from_u32(8),
1373            peer_id: Some([123u8; 32]),
1374        };
1375        
1376        let mut server_params = TransportParameters::default();
1377        server_params.nat_traversal = Some(server_config);
1378        
1379        // 5. Server encodes and sends to client
1380        let mut server_encoded = Vec::new();
1381        server_params.write(&mut server_encoded);
1382        
1383        // 6. Client receives and decodes server parameters
1384        let client_received = TransportParameters::read(Side::Client, &mut server_encoded.as_slice())
1385            .expect("Client should decode server params");
1386        
1387        // Client should see server role with concurrency limit
1388        let client_view = client_received.nat_traversal.expect("NAT traversal should be present");
1389        match client_view.role {
1390            NatTraversalRole::Server { can_relay } => {
1391                assert!(!can_relay); // Default to false in decoded params
1392            }
1393            _ => panic!("Expected server role"),
1394        }
1395        assert_eq!(client_view.max_concurrent_attempts, VarInt::from_u32(8));
1396    }
1397
1398    #[test]
1399    fn coding() {
1400        let mut buf = Vec::new();
1401        let params = TransportParameters {
1402            initial_src_cid: Some(ConnectionId::new(&[])),
1403            original_dst_cid: Some(ConnectionId::new(&[])),
1404            initial_max_streams_bidi: 16u32.into(),
1405            initial_max_streams_uni: 16u32.into(),
1406            ack_delay_exponent: 2u32.into(),
1407            max_udp_payload_size: 1200u32.into(),
1408            preferred_address: Some(PreferredAddress {
1409                address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
1410                address_v6: Some(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 24, 0, 0)),
1411                connection_id: ConnectionId::new(&[0x42]),
1412                stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
1413            }),
1414            grease_quic_bit: true,
1415            min_ack_delay: Some(2_000u32.into()),
1416            ..TransportParameters::default()
1417        };
1418        params.write(&mut buf);
1419        assert_eq!(
1420            TransportParameters::read(Side::Client, &mut buf.as_slice()).unwrap(),
1421            params
1422        );
1423    }
1424
1425    #[test]
1426    fn reserved_transport_parameter_generate_reserved_id() {
1427        use rand::rngs::mock::StepRng;
1428        let mut rngs = [
1429            StepRng::new(0, 1),
1430            StepRng::new(1, 1),
1431            StepRng::new(27, 1),
1432            StepRng::new(31, 1),
1433            StepRng::new(u32::MAX as u64, 1),
1434            StepRng::new(u32::MAX as u64 - 1, 1),
1435            StepRng::new(u32::MAX as u64 + 1, 1),
1436            StepRng::new(u32::MAX as u64 - 27, 1),
1437            StepRng::new(u32::MAX as u64 + 27, 1),
1438            StepRng::new(u32::MAX as u64 - 31, 1),
1439            StepRng::new(u32::MAX as u64 + 31, 1),
1440            StepRng::new(u64::MAX, 1),
1441            StepRng::new(u64::MAX - 1, 1),
1442            StepRng::new(u64::MAX - 27, 1),
1443            StepRng::new(u64::MAX - 31, 1),
1444            StepRng::new(1 << 62, 1),
1445            StepRng::new((1 << 62) - 1, 1),
1446            StepRng::new((1 << 62) + 1, 1),
1447            StepRng::new((1 << 62) - 27, 1),
1448            StepRng::new((1 << 62) + 27, 1),
1449            StepRng::new((1 << 62) - 31, 1),
1450            StepRng::new((1 << 62) + 31, 1),
1451        ];
1452        for rng in &mut rngs {
1453            let id = ReservedTransportParameter::generate_reserved_id(rng);
1454            assert!(id.0 % 31 == 27)
1455        }
1456    }
1457
1458    #[test]
1459    fn reserved_transport_parameter_ignored_when_read() {
1460        let mut buf = Vec::new();
1461        let reserved_parameter = ReservedTransportParameter::random(&mut rand::thread_rng());
1462        assert!(reserved_parameter.payload_len < ReservedTransportParameter::MAX_PAYLOAD_LEN);
1463        assert!(reserved_parameter.id.0 % 31 == 27);
1464
1465        reserved_parameter.write(&mut buf);
1466        assert!(!buf.is_empty());
1467        let read_params = TransportParameters::read(Side::Server, &mut buf.as_slice()).unwrap();
1468        assert_eq!(read_params, TransportParameters::default());
1469    }
1470
1471    #[test]
1472    fn read_semantic_validation() {
1473        #[allow(clippy::type_complexity)]
1474        let illegal_params_builders: Vec<Box<dyn FnMut(&mut TransportParameters)>> = vec![
1475            Box::new(|t| {
1476                // This min_ack_delay is bigger than max_ack_delay!
1477                let min_ack_delay = t.max_ack_delay.0 * 1_000 + 1;
1478                t.min_ack_delay = Some(VarInt::from_u64(min_ack_delay).unwrap())
1479            }),
1480            Box::new(|t| {
1481                // Preferred address can only be sent by senders (and we are reading the transport
1482                // params as a client)
1483                t.preferred_address = Some(PreferredAddress {
1484                    address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
1485                    address_v6: None,
1486                    connection_id: ConnectionId::new(&[]),
1487                    stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
1488                })
1489            }),
1490        ];
1491
1492        for mut builder in illegal_params_builders {
1493            let mut buf = Vec::new();
1494            let mut params = TransportParameters::default();
1495            builder(&mut params);
1496            params.write(&mut buf);
1497
1498            assert_eq!(
1499                TransportParameters::read(Side::Server, &mut buf.as_slice()),
1500                Err(Error::IllegalValue)
1501            );
1502        }
1503    }
1504
1505    #[test]
1506    fn resumption_params_validation() {
1507        let high_limit = TransportParameters {
1508            initial_max_streams_uni: 32u32.into(),
1509            ..TransportParameters::default()
1510        };
1511        let low_limit = TransportParameters {
1512            initial_max_streams_uni: 16u32.into(),
1513            ..TransportParameters::default()
1514        };
1515        high_limit.validate_resumption_from(&low_limit).unwrap();
1516        low_limit.validate_resumption_from(&high_limit).unwrap_err();
1517    }
1518}