s2n_quic_core/transport/parameters/
mod.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    ack, connection, endpoint, event,
6    event::IntoEvent,
7    inet::{SocketAddressV4, SocketAddressV6, Unspecified},
8    stateless_reset,
9    stream::{StreamId, StreamType},
10    varint::VarInt,
11};
12use core::{mem::size_of, time::Duration};
13use s2n_codec::{
14    decoder_invariant, decoder_value, DecoderBuffer, DecoderBufferMut, DecoderBufferMutResult,
15    DecoderBufferResult, DecoderError, DecoderValue, DecoderValueMut, Encoder, EncoderValue,
16};
17
18#[cfg(test)]
19mod tests;
20
21/// Trait for an transport parameter value
22pub trait TransportParameter: Sized {
23    /// The ID or tag for the TransportParameter
24    const ID: TransportParameterId;
25
26    /// Enables/disables the TransportParameter in a certain context
27    const ENABLED: bool = true;
28
29    /// Associated type for decoding/encoding the TransportParameter
30    type CodecValue: EncoderValue;
31
32    /// Create a `TransportParameter` from the CodecValue
33    fn from_codec_value(value: Self::CodecValue) -> Self;
34
35    /// Attempts to convert the `TransportParameter` into the `CodecValue`
36    fn try_into_codec_value(&self) -> Option<&Self::CodecValue>;
37
38    /// Returns the default value for the TransportParameter
39    /// This is used instead of `Default::default` so it is
40    /// easily overridable
41    fn default_value() -> Self;
42
43    /// Appends this `TransportParameter` to the given buffer containing
44    /// already encoded TransportParameters
45    #[cfg(feature = "alloc")]
46    fn append_to_buffer(&self, buffer: &mut alloc::vec::Vec<u8>) {
47        let original_size = buffer.len();
48        let new_parameter_size = TransportParameterCodec(self).encoding_size();
49        buffer.resize(original_size + new_parameter_size, 0);
50        let mut buffer = s2n_codec::EncoderBuffer::new(buffer);
51        buffer.set_position(original_size);
52        buffer.encode(&TransportParameterCodec(self));
53    }
54}
55
56/// Trait for validating transport parameter values
57pub trait TransportParameterValidator: Sized {
58    /// Validates that the transport parameter is in a valid state
59    fn validate(self) -> Result<Self, DecoderError> {
60        Ok(self)
61    }
62}
63
64//= https://www.rfc-editor.org/rfc/rfc9000#section-7.4.1
65//# To enable 0-RTT, endpoints store the values of the server transport
66//# parameters with any session tickets it receives on the connection.
67
68//= https://www.rfc-editor.org/rfc/rfc9000#section-7.4.1
69//# *  active_connection_id_limit
70//# *  initial_max_data
71//# *  initial_max_stream_data_bidi_local
72//# *  initial_max_stream_data_bidi_remote
73//# *  initial_max_stream_data_uni
74//# *  initial_max_streams_bidi
75//# *  initial_max_streams_uni
76
77//= https://www.rfc-editor.org/rfc/rfc9000#section-7.4.1
78//# A client MUST NOT use remembered values for the following parameters:
79//# ack_delay_exponent, max_ack_delay, initial_source_connection_id,
80//# original_destination_connection_id, preferred_address,
81//# retry_source_connection_id, and stateless_reset_token.
82
83#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
84pub struct ZeroRttParameters {
85    pub active_connection_id_limit: VarInt,
86    pub initial_max_data: VarInt,
87    pub initial_max_stream_data_bidi_local: VarInt,
88    pub initial_max_stream_data_bidi_remote: VarInt,
89    pub initial_max_stream_data_uni: VarInt,
90    pub initial_max_streams_bidi: VarInt,
91    pub initial_max_streams_uni: VarInt,
92    //= https://www.rfc-editor.org/rfc/rfc9221#section-3
93    //# When clients use 0-RTT, they MAY store the value of the server's
94    //# max_datagram_frame_size transport parameter. Doing so allows the
95    //# client to send DATAGRAM frames in 0-RTT packets.
96    pub max_datagram_frame_size: VarInt,
97}
98
99impl<
100        OriginalDestinationConnectionId,
101        StatelessResetToken,
102        PreferredAddress,
103        RetrySourceConnectionId,
104    >
105    TransportParameters<
106        OriginalDestinationConnectionId,
107        StatelessResetToken,
108        PreferredAddress,
109        RetrySourceConnectionId,
110    >
111{
112    /// Returns the ZeroRTTParameters to be saved between connections
113    pub fn zero_rtt_parameters(&self) -> ZeroRttParameters {
114        let Self {
115            active_connection_id_limit,
116            initial_max_data,
117            initial_max_stream_data_bidi_local,
118            initial_max_stream_data_bidi_remote,
119            initial_max_stream_data_uni,
120            initial_max_streams_bidi,
121            initial_max_streams_uni,
122            max_datagram_frame_size,
123            ..
124        } = self;
125        ZeroRttParameters {
126            active_connection_id_limit: **active_connection_id_limit,
127            initial_max_data: **initial_max_data,
128            initial_max_stream_data_bidi_local: **initial_max_stream_data_bidi_local,
129            initial_max_stream_data_bidi_remote: **initial_max_stream_data_bidi_remote,
130            initial_max_stream_data_uni: **initial_max_stream_data_uni,
131            initial_max_streams_bidi: **initial_max_streams_bidi,
132            initial_max_streams_uni: **initial_max_streams_uni,
133            max_datagram_frame_size: **max_datagram_frame_size,
134        }
135    }
136}
137
138//= https://www.rfc-editor.org/rfc/rfc9000#section-18
139//# The extension_data field of the quic_transport_parameters extension
140//# defined in [QUIC-TLS] contains the QUIC transport parameters.  They
141//# are encoded as a sequence of transport parameters, as shown in
142//# Figure 20:
143//#
144//# Transport Parameters {
145//#   Transport Parameter (..) ...,
146//# }
147//#
148//#              Figure 20: Sequence of Transport Parameters
149
150decoder_value!(
151    impl<'a> ClientTransportParameters {
152        fn decode(buffer: Buffer) -> Result<Self> {
153            let len = buffer.len();
154            let (slice, buffer) = buffer.decode_slice(len)?;
155            let parameters = Self::decode_parameters(slice.peek())?;
156            Ok((parameters, buffer))
157        }
158    }
159);
160
161decoder_value!(
162    impl<'a> ServerTransportParameters {
163        fn decode(buffer: Buffer) -> Result<Self> {
164            let len = buffer.len();
165            let (slice, buffer) = buffer.decode_slice(len)?;
166            let parameters = Self::decode_parameters(slice.peek())?;
167            Ok((parameters, buffer))
168        }
169    }
170);
171
172//= https://www.rfc-editor.org/rfc/rfc9000#section-18
173//# Transport Parameter {
174//#    Transport Parameter ID (i),
175//#    Transport Parameter Length (i),
176//#    Transport Parameter Value (..),
177//# }
178//#
179//# Figure 21: Transport Parameter Encoding
180//#
181//# The Transport Parameter Length field contains the length of the
182//# Transport Parameter Value field in bytes.
183//#
184//# QUIC encodes transport parameters into a sequence of bytes, which is
185//# then included in the cryptographic handshake.
186
187type TransportParameterId = VarInt;
188type TransportParameterLength = VarInt;
189
190/// Utility struct for encoding and decoding transport parameters
191struct TransportParameterCodec<T>(T);
192
193impl<'a, T: TransportParameter> DecoderValue<'a> for TransportParameterCodec<T>
194where
195    T::CodecValue: DecoderValue<'a>,
196{
197    fn decode(buffer: DecoderBuffer<'a>) -> DecoderBufferResult<'a, Self> {
198        let (value, buffer) = buffer.decode_with_len_prefix::<TransportParameterLength, _>()?;
199        Ok((Self(T::from_codec_value(value)), buffer))
200    }
201}
202
203impl<'a, T: TransportParameter> DecoderValueMut<'a> for TransportParameterCodec<T>
204where
205    T::CodecValue: DecoderValueMut<'a>,
206{
207    fn decode_mut(buffer: DecoderBufferMut<'a>) -> DecoderBufferMutResult<'a, Self> {
208        let (value, buffer) = buffer.decode_with_len_prefix::<TransportParameterLength, _>()?;
209        Ok((Self(T::from_codec_value(value)), buffer))
210    }
211}
212
213impl<T: TransportParameter> EncoderValue for TransportParameterCodec<&T>
214where
215    T::CodecValue: EncoderValue,
216{
217    fn encode<E: Encoder>(&self, buffer: &mut E) {
218        if let Some(value) = self.0.try_into_codec_value() {
219            buffer.encode(&T::ID);
220            buffer.encode_with_len_prefix::<TransportParameterLength, _>(value);
221        }
222    }
223}
224
225#[derive(Copy, Clone, Debug, PartialEq)]
226pub struct ValidationError(pub(crate) &'static str);
227
228const MAX_ENCODABLE_VALUE: ValidationError =
229    ValidationError("provided value exceeds maximum encodable value");
230
231impl core::fmt::Display for ValidationError {
232    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
233        write!(f, "{}", self.0)
234    }
235}
236
237impl From<DecoderError> for ValidationError {
238    fn from(error: DecoderError) -> Self {
239        ValidationError(error.into())
240    }
241}
242
243impl From<crate::varint::VarIntError> for ValidationError {
244    fn from(_: crate::varint::VarIntError) -> Self {
245        MAX_ENCODABLE_VALUE
246    }
247}
248
249impl From<core::num::TryFromIntError> for ValidationError {
250    fn from(_: core::num::TryFromIntError) -> Self {
251        MAX_ENCODABLE_VALUE
252    }
253}
254
255impl From<core::convert::Infallible> for ValidationError {
256    fn from(_: core::convert::Infallible) -> Self {
257        // this won't ever happen since Infallible can't actually be created
258        MAX_ENCODABLE_VALUE
259    }
260}
261
262impl core::error::Error for ValidationError {}
263
264/// Creates a transport parameter struct with the inner codec type
265macro_rules! transport_parameter {
266    ($name:ident($encodable_type:ty), $tag:expr) => {
267        transport_parameter!(
268            $name($encodable_type),
269            $tag,
270            <$encodable_type as Default>::default()
271        );
272    };
273    ($name:ident($encodable_type:ty), $tag:expr, $default:expr) => {
274        #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
275        pub struct $name($encodable_type);
276
277        impl Default for $name {
278            fn default() -> Self {
279                Self($default)
280            }
281        }
282
283        impl $name {
284            // Create a transport parameter with the given value
285            pub fn new<T: TryInto<$encodable_type>>(value: T) -> Option<Self> {
286                value
287                    .try_into()
288                    .ok()
289                    .map(Self)
290                    .and_then(|value| value.validate().ok())
291            }
292        }
293
294        impl TryFrom<$encodable_type> for $name {
295            type Error = ValidationError;
296
297            fn try_from(value: $encodable_type) -> Result<Self, Self::Error> {
298                Self(value).validate().map_err(|err| err.into())
299            }
300        }
301
302        impl TransportParameter for $name {
303            type CodecValue = $encodable_type;
304
305            const ID: TransportParameterId = TransportParameterId::from_u8($tag);
306
307            fn from_codec_value(value: Self::CodecValue) -> Self {
308                Self(value)
309            }
310
311            fn try_into_codec_value(&self) -> Option<&Self::CodecValue> {
312                // To save bytes on the wire, don't send the value if it matches the default value
313                if self.0 == $default {
314                    None
315                } else {
316                    Some(&self.0)
317                }
318            }
319
320            fn default_value() -> Self {
321                Self($default)
322            }
323        }
324
325        impl core::ops::Deref for $name {
326            type Target = $encodable_type;
327
328            fn deref(&self) -> &Self::Target {
329                &self.0
330            }
331        }
332
333        impl PartialEq<$encodable_type> for $name {
334            fn eq(&self, value: &$encodable_type) -> bool {
335                self.0.eq(value)
336            }
337        }
338
339        impl PartialOrd<$encodable_type> for $name {
340            fn partial_cmp(&self, value: &$encodable_type) -> Option<core::cmp::Ordering> {
341                self.0.partial_cmp(value)
342            }
343        }
344    };
345}
346
347macro_rules! varint_transport_parameter {
348    ($name:ident, $tag:expr $(, $default:expr)?) => {
349        transport_parameter!($name(VarInt), $tag $(, $default)?);
350
351        impl TryFrom<u64> for $name {
352            type Error = ValidationError;
353
354            fn try_from(value: u64) -> Result<Self, Self::Error> {
355                let value = VarInt::new(value)?;
356                Self::try_from(value)
357            }
358        }
359
360        impl $name {
361            pub const fn as_varint(self) -> VarInt {
362                self.0
363            }
364        }
365    };
366}
367
368macro_rules! duration_transport_parameter {
369    ($name:ident, $tag:expr $(, $default:expr)?) => {
370        transport_parameter!($name(VarInt), $tag $(, $default)?);
371
372        impl $name {
373            /// Convert idle_timeout into a `core::time::Duration`
374            pub const fn as_duration(self) -> Duration {
375                Duration::from_millis(self.0.as_u64())
376            }
377        }
378
379        impl TryFrom<Duration> for $name {
380            type Error = ValidationError;
381
382            fn try_from(value: Duration) -> Result<Self, Self::Error> {
383                let value: VarInt = value.as_millis().try_into()?;
384                value.try_into()
385            }
386        }
387
388        impl From<$name> for Duration {
389            fn from(value: $name) -> Self {
390                value.as_duration()
391            }
392        }
393    };
394}
395
396/// Implements an optional transport parameter. Used for transport parameters
397/// that don't have a good default, like an IP address.
398macro_rules! optional_transport_parameter {
399    ($ty:ty) => {
400        impl TransportParameter for Option<$ty> {
401            type CodecValue = $ty;
402
403            const ID: TransportParameterId = <$ty as TransportParameter>::ID;
404
405            fn from_codec_value(value: Self::CodecValue) -> Self {
406                Some(value)
407            }
408
409            fn try_into_codec_value(&self) -> Option<&Self::CodecValue> {
410                self.as_ref()
411            }
412
413            fn default_value() -> Self {
414                None
415            }
416        }
417
418        impl TransportParameterValidator for Option<$ty> {
419            fn validate(self) -> Result<Self, DecoderError> {
420                if let Some(value) = self {
421                    Ok(Some(value.validate()?))
422                } else {
423                    Ok(None)
424                }
425            }
426        }
427    };
428}
429
430macro_rules! connection_id_parameter {
431    ($name:ident, $id_type:ident, $tag:expr) => {
432        transport_parameter!($name(connection::$id_type), $tag);
433
434        // The inner connection_id handles validation
435        impl TransportParameterValidator for $name {}
436
437        impl TryFrom<&[u8]> for $name {
438            type Error = crate::connection::id::Error;
439
440            fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
441                Ok(Self(connection::$id_type::try_from(value)?))
442            }
443        }
444
445        decoder_value!(
446            impl<'a> $name {
447                fn decode(buffer: Buffer) -> Result<Self> {
448                    let (connection_id, buffer) = buffer.decode()?;
449                    Ok((Self(connection_id), buffer))
450                }
451            }
452        );
453
454        impl EncoderValue for $name {
455            fn encode<E: Encoder>(&self, encoder: &mut E) {
456                self.0.encode(encoder)
457            }
458        }
459    };
460}
461
462//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
463//# original_destination_connection_id (0x00): This parameter is the value of the
464//#    Destination Connection ID field from the first Initial packet sent
465//#    by the client; see Section 7.3.  This transport parameter is only
466//#    sent by a server.
467
468connection_id_parameter!(OriginalDestinationConnectionId, InitialId, 0x00);
469optional_transport_parameter!(OriginalDestinationConnectionId);
470
471//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
472//# max_idle_timeout (0x01):  The maximum idle timeout is a value in
473//#    milliseconds that is encoded as an integer; see (Section 10.1).
474//#    Idle timeout is disabled when both endpoints omit this transport
475//#    parameter or specify a value of 0.
476
477transport_parameter!(MaxIdleTimeout(VarInt), 0x01, VarInt::from_u8(0));
478
479impl MaxIdleTimeout {
480    /// Defaults to 30 seconds
481    pub const RECOMMENDED: Self = Self(VarInt::from_u32(30_000));
482
483    /// Loads a value setting from a peer's transport parameter
484    pub fn load_peer(&mut self, peer: &Self) {
485        //= https://www.rfc-editor.org/rfc/rfc9000#section-10.1
486        //# Each endpoint advertises a max_idle_timeout, but the effective value
487        //# at an endpoint is computed as the minimum of the two advertised
488        //# values.
489
490        match (self.as_duration(), peer.as_duration()) {
491            (Some(current_duration), Some(peer_duration)) => {
492                // take the peer's value if less
493                if current_duration > peer_duration {
494                    *self = *peer;
495                }
496            }
497            (Some(_), None) => {
498                // keep self
499            }
500            (None, Some(_)) => {
501                *self = *peer;
502            }
503            (None, None) => {
504                // keep self
505            }
506        }
507    }
508
509    /// Returns the `max_idle_timeout` if set
510    pub fn as_duration(&self) -> Option<Duration> {
511        let duration = Duration::from_millis(self.0.as_u64());
512
513        //= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
514        //# Idle timeout is disabled when both endpoints omit this transport
515        //# parameter or specify a value of 0.
516        if duration == Duration::from_secs(0) {
517            None
518        } else {
519            Some(duration)
520        }
521    }
522}
523
524impl TransportParameterValidator for MaxIdleTimeout {}
525
526impl TryFrom<Duration> for MaxIdleTimeout {
527    type Error = ValidationError;
528
529    fn try_from(value: Duration) -> Result<Self, Self::Error> {
530        let value: VarInt = value.as_millis().try_into()?;
531        value.try_into()
532    }
533}
534
535impl From<MaxIdleTimeout> for Duration {
536    fn from(value: MaxIdleTimeout) -> Self {
537        value.as_duration().unwrap_or_default()
538    }
539}
540
541//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
542//# stateless_reset_token (0x02):  A stateless reset token is used in
543//#    verifying a stateless reset; see Section 10.3.  This parameter is
544//#    a sequence of 16 bytes.  This transport parameter MUST NOT be sent
545//#    by a client, but MAY be sent by a server.  A server that does not
546//#    send this transport parameter cannot use stateless reset
547//#    (Section 10.3) for the connection ID negotiated during the
548//#    handshake.
549
550optional_transport_parameter!(stateless_reset::Token);
551
552impl TransportParameter for stateless_reset::Token {
553    type CodecValue = Self;
554
555    const ID: TransportParameterId = TransportParameterId::from_u8(0x02);
556
557    fn from_codec_value(value: Self) -> Self {
558        value
559    }
560
561    fn try_into_codec_value(&self) -> Option<&Self> {
562        Some(self)
563    }
564
565    fn default_value() -> Self {
566        Self::ZEROED
567    }
568}
569
570impl TransportParameterValidator for stateless_reset::Token {}
571
572//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
573//# max_udp_payload_size (0x03):  The maximum UDP payload size parameter
574//#    is an integer value that limits the size of UDP payloads that the
575//#    endpoint is willing to receive.  UDP datagrams with payloads
576//#    larger than this limit are not likely to be processed by the
577//#    receiver.
578//#
579//#    The default for this parameter is the maximum permitted UDP
580//#    payload of 65527.  Values below 1200 are invalid.
581//#
582//#    This limit does act as an additional constraint on datagram size
583//#    in the same way as the path MTU, but it is a property of the
584//#    endpoint and not the path; see Section 14.  It is expected that
585//#    this is the space an endpoint dedicates to holding incoming
586//#    packets.
587
588transport_parameter!(MaxUdpPayloadSize(VarInt), 0x03, VarInt::from_u16(65527));
589
590impl TransportParameterValidator for MaxUdpPayloadSize {
591    fn validate(self) -> Result<Self, DecoderError> {
592        decoder_invariant!(
593            (1200..=65527).contains(&*self.0),
594            "max_udp_payload_size should be within 1200 and 65527 bytes"
595        );
596        Ok(self)
597    }
598}
599
600impl TryFrom<u16> for MaxUdpPayloadSize {
601    type Error = ValidationError;
602
603    fn try_from(value: u16) -> Result<Self, Self::Error> {
604        let value: VarInt = value.into();
605        value.try_into()
606    }
607}
608
609//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
610//# initial_max_data (0x04):  The initial maximum data parameter is an
611//#    integer value that contains the initial value for the maximum
612//#    amount of data that can be sent on the connection.  This is
613//#    equivalent to sending a MAX_DATA (Section 19.9) for the connection
614//#    immediately after completing the handshake.
615
616varint_transport_parameter!(InitialMaxData, 0x04);
617
618/// Computes a data window with the given configuration
619pub const fn compute_data_window(mbps: u64, rtt: Duration, rtt_count: u64) -> VarInt {
620    // ideal throughput in Mbps
621    let mut window = mbps;
622    // Mbit/sec * 125 -> bytes/ms
623    window *= 125;
624    // bytes/ms * ms/RTT -> bytes/RTT
625    window *= rtt.as_millis() as u64;
626    // bytes/RTT * rtt_count -> N * bytes/RTT
627    window *= rtt_count;
628
629    VarInt::from_u32(window as u32)
630}
631
632impl InitialMaxData {
633    /// Tuned for 150Mbps with a 100ms RTT
634    pub const RECOMMENDED: Self = Self(compute_data_window(150, Duration::from_millis(100), 2));
635}
636
637impl TransportParameterValidator for InitialMaxData {}
638
639//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
640//# initial_max_stream_data_bidi_local (0x05):  This parameter is an
641//#    integer value specifying the initial flow control limit for
642//#    locally-initiated bidirectional streams.  This limit applies to
643//#    newly created bidirectional streams opened by the endpoint that
644//#    sends the transport parameter.  In client transport parameters,
645//#    this applies to streams with an identifier with the least
646//#    significant two bits set to 0x00; in server transport parameters,
647//#    this applies to streams with the least significant two bits set to
648//#    0x01.
649
650varint_transport_parameter!(InitialMaxStreamDataBidiLocal, 0x05);
651
652impl InitialMaxStreamDataBidiLocal {
653    /// Tuned for 150Mbps throughput with a 100ms RTT
654    pub const RECOMMENDED: Self = Self(InitialMaxData::RECOMMENDED.0);
655}
656
657impl TransportParameterValidator for InitialMaxStreamDataBidiLocal {}
658
659//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
660//# initial_max_stream_data_bidi_remote (0x06):  This parameter is an
661//#    integer value specifying the initial flow control limit for peer-
662//#    initiated bidirectional streams.  This limit applies to newly
663//#    created bidirectional streams opened by the endpoint that receives
664//#    the transport parameter.  In client transport parameters, this
665//#    applies to streams with an identifier with the least significant
666//#    two bits set to 0x01; in server transport parameters, this applies
667//#    to streams with the least significant two bits set to 0x00.
668
669varint_transport_parameter!(InitialMaxStreamDataBidiRemote, 0x06);
670
671impl InitialMaxStreamDataBidiRemote {
672    /// Tuned for 150Mbps throughput with a 100ms RTT
673    pub const RECOMMENDED: Self = Self(InitialMaxData::RECOMMENDED.0);
674}
675
676impl TransportParameterValidator for InitialMaxStreamDataBidiRemote {}
677
678//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
679//# initial_max_stream_data_uni (0x07):  This parameter is an integer
680//#    value specifying the initial flow control limit for unidirectional
681//#    streams.  This limit applies to newly created unidirectional
682//#    streams opened by the endpoint that receives the transport
683//#    parameter.  In client transport parameters, this applies to
684//#    streams with an identifier with the least significant two bits set
685//#    to 0x03; in server transport parameters, this applies to streams
686//#    with the least significant two bits set to 0x02.
687
688varint_transport_parameter!(InitialMaxStreamDataUni, 0x07);
689
690impl InitialMaxStreamDataUni {
691    /// Tuned for 150Mbps throughput with a 100ms RTT
692    pub const RECOMMENDED: Self = Self(InitialMaxData::RECOMMENDED.0);
693}
694
695impl TransportParameterValidator for InitialMaxStreamDataUni {}
696
697//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
698//# initial_max_streams_bidi (0x08):  The initial maximum bidirectional
699//#    streams parameter is an integer value that contains the initial
700//#    maximum number of bidirectional streams the endpoint that receives
701//#    this transport parameter is permitted to initiate.  If this
702//#    parameter is absent or zero, the peer cannot open bidirectional
703//#    streams until a MAX_STREAMS frame is sent.  Setting this parameter
704//#    is equivalent to sending a MAX_STREAMS (Section 19.11) of the
705//#    corresponding type with the same value.
706
707varint_transport_parameter!(InitialMaxStreamsBidi, 0x08);
708
709impl InitialMaxStreamsBidi {
710    /// Allow up to 100 concurrent streams at any time
711    pub const RECOMMENDED: Self = Self(VarInt::from_u8(100));
712}
713
714impl TransportParameterValidator for InitialMaxStreamsBidi {
715    fn validate(self) -> Result<Self, DecoderError> {
716        //= https://www.rfc-editor.org/rfc/rfc9000#section-4.6
717        //# If a max_streams transport parameter or a MAX_STREAMS frame is
718        //# received with a value greater than 2^60, this would allow a maximum
719        //# stream ID that cannot be expressed as a variable-length integer; see
720        //# Section 16.  If either is received, the connection MUST be closed
721        //# immediately with a connection error of type TRANSPORT_PARAMETER_ERROR
722        //# if the offending value was received in a transport parameter or of
723        //# type FRAME_ENCODING_ERROR if it was received in a frame; see
724        //# Section 10.2.
725        decoder_invariant!(
726            *self <= 2u64.pow(60),
727            "initial_max_streams_bidi cannot be greater than 2^60"
728        );
729
730        Ok(self)
731    }
732}
733
734//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
735//# initial_max_streams_uni (0x09):  The initial maximum unidirectional
736//#    streams parameter is an integer value that contains the initial
737//#    maximum number of unidirectional streams the endpoint that
738//#    receives this transport parameter is permitted to initiate.  If
739//#    this parameter is absent or zero, the peer cannot open
740//#    unidirectional streams until a MAX_STREAMS frame is sent.  Setting
741//#    this parameter is equivalent to sending a MAX_STREAMS
742//#    (Section 19.11) of the corresponding type with the same value.
743
744varint_transport_parameter!(InitialMaxStreamsUni, 0x09);
745
746impl InitialMaxStreamsUni {
747    /// Allow up to 100 concurrent streams at any time
748    pub const RECOMMENDED: Self = Self(VarInt::from_u8(100));
749}
750
751impl TransportParameterValidator for InitialMaxStreamsUni {
752    fn validate(self) -> Result<Self, DecoderError> {
753        //= https://www.rfc-editor.org/rfc/rfc9000#section-4.6
754        //# If a max_streams transport parameter or a MAX_STREAMS frame is
755        //# received with a value greater than 2^60, this would allow a maximum
756        //# stream ID that cannot be expressed as a variable-length integer; see
757        //# Section 16.  If either is received, the connection MUST be closed
758        //# immediately with a connection error of type TRANSPORT_PARAMETER_ERROR
759        //# if the offending value was received in a transport parameter or of
760        //# type FRAME_ENCODING_ERROR if it was received in a frame; see
761        //# Section 10.2.
762        decoder_invariant!(
763            *self <= 2u64.pow(60),
764            "initial_max_streams_uni cannot be greater than 2^60"
765        );
766
767        Ok(self)
768    }
769}
770
771//= https://www.rfc-editor.org/rfc/rfc9221#section-3
772//# Support for receiving the DATAGRAM frame types is advertised by means
773//# of a QUIC transport parameter (name=max_datagram_frame_size, value=0x20).
774//# The max_datagram_frame_size transport parameter is an integer value
775//# (represented as a variable-length integer) that represents the maximum
776//# size of a DATAGRAM frame (including the frame type, length, and
777//# payload) the endpoint is willing to receive, in bytes.
778transport_parameter!(MaxDatagramFrameSize(VarInt), 0x20, VarInt::from_u16(0));
779
780impl MaxDatagramFrameSize {
781    //= https://www.rfc-editor.org/rfc/rfc9221#section-3
782    //# For most uses of DATAGRAM frames, it is RECOMMENDED to send a value of
783    //# 65535 in the max_datagram_frame_size transport parameter to indicate that
784    //# this endpoint will accept any DATAGRAM frame that fits inside a QUIC packet.
785    pub const RECOMMENDED: u64 = 65535;
786    //= https://www.rfc-editor.org/rfc/rfc9221#section-3
787    //# The default for this parameter is 0, which indicates that the
788    //# endpoint does not support DATAGRAM frames.  A value greater than 0
789    //# indicates that the endpoint supports the DATAGRAM frame types and is
790    //# willing to receive such frames on this connection.
791    pub const DEFAULT: Self = Self(VarInt::from_u16(0));
792}
793
794impl TransportParameterValidator for MaxDatagramFrameSize {
795    fn validate(self) -> Result<Self, DecoderError> {
796        Ok(self)
797    }
798}
799
800impl TryFrom<u64> for MaxDatagramFrameSize {
801    type Error = ValidationError;
802
803    fn try_from(value: u64) -> Result<Self, Self::Error> {
804        let value = VarInt::new(value)?;
805        Self::try_from(value)
806    }
807}
808
809//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
810//# ack_delay_exponent (0x0a):  The acknowledgement delay exponent is an
811//#    integer value indicating an exponent used to decode the ACK Delay
812//#    field in the ACK frame (Section 19.3).  If this value is absent, a
813//#    default value of 3 is assumed (indicating a multiplier of 8).
814//#    Values above 20 are invalid.
815
816transport_parameter!(AckDelayExponent(u8), 0x0a, 3);
817
818impl AckDelayExponent {
819    /// The recommended value comes from the default of 3
820    pub const RECOMMENDED: Self = Self(3);
821
822    pub const fn as_u8(self) -> u8 {
823        self.0
824    }
825}
826
827impl TransportParameterValidator for AckDelayExponent {
828    fn validate(self) -> Result<Self, DecoderError> {
829        decoder_invariant!(self.0 <= 20, "ack_delay_exponent cannot be greater than 20");
830        Ok(self)
831    }
832}
833
834//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
835//# max_ack_delay (0x0b):  The maximum acknowledgment delay is an integer
836//#    value indicating the maximum amount of time in milliseconds by
837//#    which the endpoint will delay sending acknowledgments.  This value
838//#    SHOULD include the receiver's expected delays in alarms firing.
839//#    For example, if a receiver sets a timer for 5ms and alarms
840//#    commonly fire up to 1ms late, then it should send a max_ack_delay
841//#    of 6ms.  If this value is absent, a default of 25 milliseconds is
842//#    assumed.  Values of 2^14 or greater are invalid.
843
844duration_transport_parameter!(MaxAckDelay, 0x0b, VarInt::from_u8(25));
845
846impl MaxAckDelay {
847    /// The recommended value comes from the default of 25ms
848    pub const RECOMMENDED: Self = Self(VarInt::from_u8(25));
849}
850
851impl TransportParameterValidator for MaxAckDelay {
852    fn validate(self) -> Result<Self, DecoderError> {
853        decoder_invariant!(
854            *self.0 <= 2u64.pow(14),
855            "max_ack_delay cannot be greater than 2^14"
856        );
857        Ok(self)
858    }
859}
860
861//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
862//# disable_active_migration (0x0c): The disable active migration
863//#    transport parameter is included if the endpoint does not support
864//#    active connection migration (Section 9) on the address being used
865//#    during the handshake.
866
867#[derive(Clone, Copy, Debug, Default, PartialEq)]
868pub enum MigrationSupport {
869    #[default]
870    Enabled,
871    Disabled,
872}
873
874impl MigrationSupport {
875    pub const RECOMMENDED: Self = Self::Enabled;
876}
877
878impl TransportParameter for MigrationSupport {
879    type CodecValue = ();
880
881    const ID: TransportParameterId = TransportParameterId::from_u8(0x0c);
882
883    fn from_codec_value(_value: ()) -> Self {
884        MigrationSupport::Disabled
885    }
886
887    fn try_into_codec_value(&self) -> Option<&()> {
888        if let MigrationSupport::Disabled = self {
889            Some(&())
890        } else {
891            None
892        }
893    }
894
895    fn default_value() -> Self {
896        Self::default()
897    }
898}
899
900impl TransportParameterValidator for MigrationSupport {}
901
902//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
903//# preferred_address (0x0d):  The server's preferred address is used to
904//#    effect a change in server address at the end of the handshake, as
905//#    described in Section 9.6.  This transport parameter is only sent
906//#    by a server.  Servers MAY choose to only send a preferred address
907//#    of one address family by sending an all-zero address and port
908//#    (0.0.0.0:0 or [::]:0) for the other family.  IP addresses are
909//#    encoded in network byte order.
910
911optional_transport_parameter!(PreferredAddress);
912
913//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
914//# Preferred Address {
915//#   IPv4 Address (32),
916//#   IPv4 Port (16),
917//#   IPv6 Address (128),
918//#   IPv6 Port (16),
919//#   Connection ID Length (8),
920//#   Connection ID (..),
921//#   Stateless Reset Token (128),
922//# }
923
924type CidLength = u8;
925
926#[derive(Clone, Copy, Debug, PartialEq)]
927pub struct PreferredAddress {
928    pub ipv4_address: Option<SocketAddressV4>,
929    pub ipv6_address: Option<SocketAddressV6>,
930    pub connection_id: crate::connection::UnboundedId,
931    pub stateless_reset_token: crate::stateless_reset::Token,
932}
933
934impl Unspecified for PreferredAddress {
935    fn is_unspecified(&self) -> bool {
936        self.ipv4_address
937            .as_ref()
938            .map(Unspecified::is_unspecified)
939            .unwrap_or(true)
940            && self
941                .ipv6_address
942                .as_ref()
943                .map(Unspecified::is_unspecified)
944                .unwrap_or(true)
945    }
946}
947
948impl TransportParameter for PreferredAddress {
949    type CodecValue = Self;
950
951    const ID: TransportParameterId = TransportParameterId::from_u8(0x0d);
952
953    fn from_codec_value(value: Self) -> Self {
954        value
955    }
956
957    fn try_into_codec_value(&self) -> Option<&Self> {
958        Some(self)
959    }
960
961    fn default_value() -> Self {
962        unimplemented!(
963            "PreferredAddress is an optional transport parameter, so the default is None"
964        )
965    }
966}
967
968impl TransportParameterValidator for PreferredAddress {
969    fn validate(self) -> Result<Self, DecoderError> {
970        decoder_invariant!(
971            !self.is_unspecified(),
972            "at least one address needs to be specified"
973        );
974        Ok(self)
975    }
976}
977
978decoder_value!(
979    impl<'a> PreferredAddress {
980        fn decode(buffer: Buffer) -> Result<Self> {
981            let (ipv4_address, buffer) = buffer.decode::<SocketAddressV4>()?;
982            let ipv4_address = ipv4_address.filter_unspecified();
983            let (ipv6_address, buffer) = buffer.decode::<SocketAddressV6>()?;
984            let ipv6_address = ipv6_address.filter_unspecified();
985            let (connection_id, buffer) = buffer.decode_with_len_prefix::<CidLength, _>()?;
986            let (stateless_reset_token, buffer) = buffer.decode()?;
987            let preferred_address = Self {
988                ipv4_address,
989                ipv6_address,
990                connection_id,
991                stateless_reset_token,
992            };
993            Ok((preferred_address, buffer))
994        }
995    }
996);
997
998impl EncoderValue for PreferredAddress {
999    fn encode<E: Encoder>(&self, buffer: &mut E) {
1000        if let Some(ip) = self.ipv4_address.as_ref() {
1001            buffer.encode(ip);
1002        } else {
1003            buffer.write_repeated(size_of::<SocketAddressV4>(), 0);
1004        }
1005
1006        if let Some(ip) = self.ipv6_address.as_ref() {
1007            buffer.encode(ip);
1008        } else {
1009            buffer.write_repeated(size_of::<SocketAddressV6>(), 0);
1010        }
1011        buffer.encode_with_len_prefix::<CidLength, _>(&self.connection_id);
1012        buffer.encode(&self.stateless_reset_token);
1013    }
1014}
1015
1016//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
1017//# active_connection_id_limit (0x0e):  This is an integer value
1018//#   specifying the maximum number of connection IDs from the peer that
1019//#   an endpoint is willing to store.  This value includes the
1020//#   connection ID received during the handshake, that received in the
1021//#   preferred_address transport parameter, and those received in
1022//#   NEW_CONNECTION_ID frames.  The value of the
1023//#   active_connection_id_limit parameter MUST be at least 2.  An
1024//#   endpoint that receives a value less than 2 MUST close the
1025//#   connection with an error of type TRANSPORT_PARAMETER_ERROR.  If
1026//#   this transport parameter is absent, a default of 2 is assumed.  If
1027//#   an endpoint issues a zero-length connection ID, it will never send
1028//#   a NEW_CONNECTION_ID frame and therefore ignores the
1029//#   active_connection_id_limit value received from its peer.
1030
1031varint_transport_parameter!(ActiveConnectionIdLimit, 0x0e, VarInt::from_u8(2));
1032
1033impl ActiveConnectionIdLimit {
1034    /// The recommended value comes from the default of 2
1035    pub const RECOMMENDED: Self = Self(VarInt::from_u8(2));
1036}
1037
1038impl TransportParameterValidator for ActiveConnectionIdLimit {
1039    fn validate(self) -> Result<Self, DecoderError> {
1040        decoder_invariant!(
1041            *self.0 >= 2,
1042            "active_connection_id_limit must be at least 2"
1043        );
1044        Ok(self)
1045    }
1046}
1047
1048impl ActiveConnectionIdLimit {
1049    /// Returns true if the specified value is the default
1050    pub fn is_default(self) -> bool {
1051        self == Self::default_value()
1052    }
1053}
1054
1055//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
1056//# initial_source_connection_id (0x0f):  This is the value that the
1057//# endpoint included in the Source Connection ID field of the first
1058//# Initial packet it sends for the connection; see Section 7.3.
1059
1060connection_id_parameter!(InitialSourceConnectionId, UnboundedId, 0x0f);
1061optional_transport_parameter!(InitialSourceConnectionId);
1062
1063impl From<connection::id::LocalId> for InitialSourceConnectionId {
1064    fn from(id: connection::id::LocalId) -> Self {
1065        InitialSourceConnectionId(id.into())
1066    }
1067}
1068
1069//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
1070//# retry_source_connection_id (0x10):  This is the value that the server
1071//#    included in the Source Connection ID field of a Retry packet; see
1072//#    Section 7.3.  This transport parameter is only sent by a server.
1073
1074connection_id_parameter!(RetrySourceConnectionId, LocalId, 0x10);
1075optional_transport_parameter!(RetrySourceConnectionId);
1076
1077/// Used by the client to indicate which versions of s2n-quic-dc it supports
1078/// and by the server to indicate which version it is using
1079#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd, Eq, Ord)]
1080pub struct DcSupportedVersions {
1081    len: u8,
1082    versions: [u32; DC_SUPPORTED_VERSIONS_MAX_LEN as usize],
1083}
1084// The maximum number of supported versions that may be transmitted using
1085// the `DcSupportedVersions` transport parameter
1086const DC_SUPPORTED_VERSIONS_MAX_LEN: u8 = 4;
1087
1088impl DcSupportedVersions {
1089    /// Create a `DcSupportedVersions` for the given `supported_versions` the client supports
1090    pub fn for_client<I: IntoIterator<Item = u32>>(supported_versions: I) -> Self {
1091        let mut versions = [0; DC_SUPPORTED_VERSIONS_MAX_LEN as usize];
1092        let mut len = 0;
1093
1094        for (index, version) in supported_versions.into_iter().enumerate() {
1095            versions[index] = version;
1096            len += 1;
1097
1098            debug_assert!(
1099                len <= DC_SUPPORTED_VERSIONS_MAX_LEN,
1100                "Only {DC_SUPPORTED_VERSIONS_MAX_LEN} supported versions are supported"
1101            );
1102            ensure!(len <= DC_SUPPORTED_VERSIONS_MAX_LEN, break);
1103        }
1104
1105        DcSupportedVersions { len, versions }
1106    }
1107
1108    /// Create a `DcSupportedVersions` for the `supported_version` the server has selected
1109    pub fn for_server(supported_version: u32) -> Self {
1110        DcSupportedVersions {
1111            len: 1,
1112            versions: [supported_version, 0, 0, 0],
1113        }
1114    }
1115
1116    /// The version the server has selected
1117    ///
1118    /// Returns `None` if no version was selected
1119    pub fn selected_version(&self) -> Result<Option<u32>, DecoderError> {
1120        match self.len {
1121            0 => Ok(None),
1122            1 => Ok(Some(self.versions[0])),
1123            _ => Err(DecoderError::InvariantViolation(
1124                "multiple versions selected by the server",
1125            )),
1126        }
1127    }
1128}
1129
1130impl TransportParameter for DcSupportedVersions {
1131    const ID: TransportParameterId = TransportParameterId::from_u32(0xdc0000);
1132    type CodecValue = Self;
1133
1134    fn from_codec_value(value: Self::CodecValue) -> Self {
1135        value
1136    }
1137
1138    fn try_into_codec_value(&self) -> Option<&Self::CodecValue> {
1139        if *self == Self::default_value() {
1140            None
1141        } else {
1142            Some(self)
1143        }
1144    }
1145
1146    fn default_value() -> Self {
1147        Self::default()
1148    }
1149}
1150
1151impl EncoderValue for DcSupportedVersions {
1152    fn encode<E: Encoder>(&self, buffer: &mut E) {
1153        for &version in self.versions.iter().take(self.len as usize) {
1154            VarInt::from_u32(version).encode(buffer);
1155        }
1156    }
1157}
1158
1159decoder_value!(
1160    impl<'a> DcSupportedVersions {
1161        fn decode(buffer: Buffer) -> Result<Self> {
1162            let mut versions = [0; DC_SUPPORTED_VERSIONS_MAX_LEN as usize];
1163            let mut len = 0;
1164            let mut buffer = buffer;
1165            while !buffer.is_empty() {
1166                let (version, remaining) = buffer.decode::<VarInt>()?;
1167                buffer = remaining;
1168
1169                decoder_invariant!(
1170                    version.as_u64() <= u32::MAX as u64,
1171                    "the largest supported version is u32::MAX"
1172                );
1173                versions[len] = version.as_u64() as u32;
1174                len += 1;
1175                ensure!(len < DC_SUPPORTED_VERSIONS_MAX_LEN as usize, break);
1176            }
1177
1178            // Skip the rest of the buffer to allow for future versions of
1179            // `DcSupportedVersions` that may support more than 4 versions
1180            let remaining_capacity = buffer.len();
1181            let buffer = buffer.skip(remaining_capacity)?;
1182            Ok((
1183                Self {
1184                    len: len as u8,
1185                    versions,
1186                },
1187                buffer,
1188            ))
1189        }
1190    }
1191);
1192
1193impl TransportParameterValidator for DcSupportedVersions {}
1194
1195impl<'a> IntoIterator for &'a DcSupportedVersions {
1196    type Item = &'a u32;
1197    type IntoIter = core::slice::Iter<'a, u32>;
1198
1199    fn into_iter(self) -> Self::IntoIter {
1200        self.versions[..self.len as usize].iter()
1201    }
1202}
1203
1204impl<'a> IntoEvent<&'a [u32]> for &'a DcSupportedVersions {
1205    fn into_event(self) -> &'a [u32] {
1206        &self.versions[..self.len as usize]
1207    }
1208}
1209
1210//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
1211//# If present, transport parameters that set initial per-stream flow
1212//# control limits (initial_max_stream_data_bidi_local,
1213//# initial_max_stream_data_bidi_remote, and initial_max_stream_data_uni)
1214//# are equivalent to sending a MAX_STREAM_DATA frame (Section 19.10) on
1215//# every stream of the corresponding type immediately after opening.  If
1216//# the transport parameter is absent, streams of that type start with a
1217//# flow control limit of 0.
1218
1219#[derive(Clone, Copy, Debug, Default, PartialEq)]
1220pub struct InitialFlowControlLimits {
1221    pub stream_limits: InitialStreamLimits,
1222    pub max_data: VarInt,
1223    pub max_open_remote_bidirectional_streams: VarInt,
1224    pub max_open_remote_unidirectional_streams: VarInt,
1225}
1226
1227/// Associated flow control limits from a set of TransportParameters
1228#[derive(Clone, Copy, Debug, Default, PartialEq)]
1229pub struct InitialStreamLimits {
1230    pub max_data_bidi_local: VarInt,
1231    pub max_data_bidi_remote: VarInt,
1232    pub max_data_uni: VarInt,
1233}
1234
1235impl InitialStreamLimits {
1236    /// Returns the initial maximum data limit for a Stream based on its Stream ID
1237    /// and the information whether the "local" endpoint is referring to the Client
1238    /// or the Server.
1239    pub fn max_data(&self, local_endpoint_type: endpoint::Type, stream_id: StreamId) -> VarInt {
1240        match (stream_id.initiator(), stream_id.stream_type()) {
1241            (endpoint_type, StreamType::Bidirectional) if endpoint_type == local_endpoint_type => {
1242                self.max_data_bidi_local
1243            }
1244            (_, StreamType::Bidirectional) => self.max_data_bidi_remote,
1245            (_, StreamType::Unidirectional) => self.max_data_uni,
1246        }
1247    }
1248}
1249
1250pub struct DatagramLimits {
1251    pub max_datagram_payload: u64,
1252}
1253
1254impl<
1255        OriginalDestinationConnectionId,
1256        StatelessResetToken,
1257        PreferredAddress,
1258        RetrySourceConnectionId,
1259    >
1260    TransportParameters<
1261        OriginalDestinationConnectionId,
1262        StatelessResetToken,
1263        PreferredAddress,
1264        RetrySourceConnectionId,
1265    >
1266{
1267    /// Returns the flow control limits from a set of TransportParameters
1268    pub fn flow_control_limits(&self) -> InitialFlowControlLimits {
1269        let Self {
1270            initial_max_data,
1271            initial_max_streams_bidi,
1272            initial_max_streams_uni,
1273            ..
1274        } = self;
1275        InitialFlowControlLimits {
1276            stream_limits: self.stream_limits(),
1277            max_data: **initial_max_data,
1278            max_open_remote_bidirectional_streams: **initial_max_streams_bidi,
1279            max_open_remote_unidirectional_streams: **initial_max_streams_uni,
1280        }
1281    }
1282
1283    /// Returns the flow control limits from a set of TransportParameters
1284    pub fn stream_limits(&self) -> InitialStreamLimits {
1285        let Self {
1286            initial_max_stream_data_bidi_local,
1287            initial_max_stream_data_bidi_remote,
1288            initial_max_stream_data_uni,
1289            ..
1290        } = self;
1291        InitialStreamLimits {
1292            max_data_bidi_local: **initial_max_stream_data_bidi_local,
1293            max_data_bidi_remote: **initial_max_stream_data_bidi_remote,
1294            max_data_uni: **initial_max_stream_data_uni,
1295        }
1296    }
1297
1298    // Returns the AckSettings from a set of TransportParameters
1299    pub fn ack_settings(&self) -> ack::Settings {
1300        let Self {
1301            max_ack_delay,
1302            ack_delay_exponent,
1303            ..
1304        } = self;
1305
1306        ack::Settings {
1307            max_ack_delay: max_ack_delay.as_duration(),
1308            ack_delay_exponent: **ack_delay_exponent,
1309            ..Default::default()
1310        }
1311    }
1312
1313    // Calculates the maximum datagram payload size
1314    pub fn datagram_limits(&self) -> DatagramLimits {
1315        let max_datagram_payload = self.max_datagram_frame_size.as_u64();
1316
1317        // We factor in the received max_udp_payload_size since technically it
1318        // can be smaller than the received max_datagram_frame_size.
1319        let max_udp_payload = self.max_udp_payload_size.as_u64();
1320        DatagramLimits {
1321            max_datagram_payload: max_datagram_payload.min(max_udp_payload),
1322        }
1323    }
1324}
1325
1326//= https://www.rfc-editor.org/rfc/rfc9000#section-18.2
1327//# A client MUST NOT include any server-only transport parameter:
1328//# original_destination_connection_id, preferred_address,
1329//# retry_source_connection_id, or stateless_reset_token.  A server MUST
1330//# treat receipt of any of these transport parameters as a connection
1331//# error of type TRANSPORT_PARAMETER_ERROR.
1332
1333mod disabled_parameter;
1334pub use disabled_parameter::DisabledParameter;
1335
1336/// Specific TransportParameters sent by the client endpoint
1337pub type ClientTransportParameters = TransportParameters<
1338    DisabledParameter<OriginalDestinationConnectionId>,
1339    DisabledParameter<stateless_reset::Token>,
1340    DisabledParameter<PreferredAddress>,
1341    DisabledParameter<RetrySourceConnectionId>,
1342>;
1343
1344/// Specific TransportParameters sent by the server endpoint
1345pub type ServerTransportParameters = TransportParameters<
1346    Option<OriginalDestinationConnectionId>,
1347    Option<stateless_reset::Token>,
1348    Option<PreferredAddress>,
1349    Option<RetrySourceConnectionId>,
1350>;
1351
1352impl<'a> IntoEvent<event::builder::TransportParameters<'a>> for &'a ServerTransportParameters {
1353    fn into_event(self) -> event::builder::TransportParameters<'a> {
1354        event::builder::TransportParameters {
1355            original_destination_connection_id: self
1356                .original_destination_connection_id
1357                .as_ref()
1358                .map(|cid| cid.into_event()),
1359            initial_source_connection_id: self
1360                .initial_source_connection_id
1361                .as_ref()
1362                .map(|cid| cid.into_event()),
1363            retry_source_connection_id: self
1364                .retry_source_connection_id
1365                .as_ref()
1366                .map(|cid| cid.into_event()),
1367            stateless_reset_token: self
1368                .stateless_reset_token
1369                .as_ref()
1370                .map(|token| token.as_ref()),
1371            preferred_address: self
1372                .preferred_address
1373                .as_ref()
1374                .map(|addr| addr.into_event()),
1375            migration_support: self.migration_support.into_event(),
1376            max_idle_timeout: Duration::from(self.max_idle_timeout),
1377            max_udp_payload_size: self.max_udp_payload_size.into_event(),
1378            ack_delay_exponent: self.ack_delay_exponent.into_event(),
1379            max_ack_delay: Duration::from(self.max_ack_delay),
1380            active_connection_id_limit: self.active_connection_id_limit.into_event(),
1381            initial_max_stream_data_bidi_local: self
1382                .initial_max_stream_data_bidi_local
1383                .into_event(),
1384            initial_max_stream_data_bidi_remote: self
1385                .initial_max_stream_data_bidi_remote
1386                .into_event(),
1387            initial_max_stream_data_uni: self.initial_max_stream_data_uni.into_event(),
1388            initial_max_streams_bidi: self.initial_max_streams_bidi.into_event(),
1389            initial_max_streams_uni: self.initial_max_streams_uni.into_event(),
1390            max_datagram_frame_size: self.max_datagram_frame_size.into_event(),
1391            dc_supported_versions: self.dc_supported_versions.into_event(),
1392        }
1393    }
1394}
1395
1396impl<'a> IntoEvent<event::builder::TransportParameters<'a>> for &'a ClientTransportParameters {
1397    fn into_event(self) -> event::builder::TransportParameters<'a> {
1398        event::builder::TransportParameters {
1399            original_destination_connection_id: None,
1400            initial_source_connection_id: self
1401                .initial_source_connection_id
1402                .as_ref()
1403                .map(|cid| cid.into_event()),
1404            retry_source_connection_id: None,
1405            stateless_reset_token: None,
1406            preferred_address: None,
1407            migration_support: self.migration_support.into_event(),
1408            max_idle_timeout: Duration::from(self.max_idle_timeout),
1409            max_udp_payload_size: self.max_udp_payload_size.into_event(),
1410            ack_delay_exponent: self.ack_delay_exponent.into_event(),
1411            max_ack_delay: Duration::from(self.max_ack_delay),
1412            active_connection_id_limit: self.active_connection_id_limit.into_event(),
1413            initial_max_stream_data_bidi_local: self
1414                .initial_max_stream_data_bidi_local
1415                .into_event(),
1416            initial_max_stream_data_bidi_remote: self
1417                .initial_max_stream_data_bidi_remote
1418                .into_event(),
1419            initial_max_stream_data_uni: self.initial_max_stream_data_uni.into_event(),
1420            initial_max_streams_bidi: self.initial_max_streams_bidi.into_event(),
1421            initial_max_streams_uni: self.initial_max_streams_uni.into_event(),
1422            max_datagram_frame_size: self.max_datagram_frame_size.into_event(),
1423            dc_supported_versions: self.dc_supported_versions.into_event(),
1424        }
1425    }
1426}
1427
1428macro_rules! impl_transport_parameters {
1429    (
1430        pub struct TransportParameters <
1431        $($server_param:ident),* $(,)? >
1432        { $($field:ident : $field_ty:ty),* $(,)? }
1433    ) => {
1434        #[derive(Clone, Copy, Debug, PartialEq)]
1435        pub struct TransportParameters<$($server_param),*> {
1436            $(
1437                pub $field: $field_ty
1438            ),*
1439        }
1440
1441        impl<$($server_param),*> Default for TransportParameters<$($server_param),*>
1442        where
1443            $(
1444                $server_param: TransportParameter,
1445            )*
1446        {
1447            fn default() -> Self {
1448                Self {
1449                    $(
1450                        $field: TransportParameter::default_value(),
1451                    )*
1452                }
1453            }
1454        }
1455
1456        impl<$($server_param),*> EncoderValue for TransportParameters<$($server_param),*>
1457        where
1458            $(
1459                $server_param: TransportParameter,
1460                $server_param::CodecValue: EncoderValue,
1461            )*
1462        {
1463            fn encode<E: Encoder>(&self, buffer: &mut E) {
1464                $(
1465                    buffer.encode(&TransportParameterCodec(&self.$field));
1466                )*
1467            }
1468        }
1469
1470        impl<'a, $($server_param),*> TransportParameters<$($server_param),*>
1471        where
1472            $(
1473                $server_param: TransportParameter + TransportParameterValidator,
1474                $server_param::CodecValue: DecoderValue<'a>,
1475            )*
1476        {
1477            fn decode_parameters(
1478                mut buffer: DecoderBuffer<'a>
1479            ) -> Result<TransportParameters<$($server_param),*>, DecoderError> {
1480                let mut parameters = Self::default();
1481
1482                /// Tracks the fields for duplicates
1483                #[derive(Default)]
1484                struct UsedFields {
1485                    $(
1486                        $field: bool,
1487                    )*
1488                }
1489
1490                let mut used_fields = UsedFields::default();
1491
1492                while !buffer.is_empty() {
1493                    let (tag, inner_buffer) = buffer.decode::<TransportParameterId>()?;
1494
1495                    buffer = match tag {
1496                        $(
1497                            tag if tag == <$field_ty>::ID => {
1498                                // ensure the field is enabled in this context
1499                                s2n_codec::decoder_invariant!(
1500                                    <$field_ty>::ENABLED,
1501                                    concat!(stringify!($field), " is not allowed in this context")
1502                                );
1503
1504                                //= https://www.rfc-editor.org/rfc/rfc9000#section-7.4
1505                                //# An endpoint MUST NOT send a parameter more than once in a given
1506                                //# transport parameters extension.
1507                                s2n_codec::decoder_invariant!(
1508                                    core::mem::replace(&mut used_fields.$field, true) == false,
1509                                    concat!("duplicate value for ", stringify!($field))
1510                                );
1511
1512                                let (value, inner_buffer) =
1513                                    inner_buffer.decode::<TransportParameterCodec<$field_ty>>()?;
1514
1515                                //= https://www.rfc-editor.org/rfc/rfc9000#section-7.4
1516                                //# An endpoint MUST treat receipt of a transport parameter with an
1517                                //# invalid value as a connection error of type
1518                                //# TRANSPORT_PARAMETER_ERROR.
1519                                parameters.$field = value.0.validate()?;
1520
1521                                inner_buffer
1522                            }
1523                        )*
1524                        _ => {
1525                            //= https://www.rfc-editor.org/rfc/rfc9000#section-7.4.2
1526                            //# An endpoint MUST ignore transport parameters that it does
1527                            //# not support.
1528
1529                            // ignore transport parameters with unknown tags
1530                            // We need to skip the actual content of the parameters, which
1531                            // consists of a VarInt length field plus payload
1532                            inner_buffer.skip_with_len_prefix::<TransportParameterLength>()?
1533                        }
1534                    }
1535                }
1536
1537                Ok(parameters)
1538            }
1539        }
1540    };
1541}
1542
1543impl_transport_parameters!(
1544    pub struct TransportParameters<
1545        OriginalDestinationConnectionId,
1546        StatelessResetToken,
1547        PreferredAddress,
1548        RetrySourceConnectionId,
1549    > {
1550        max_idle_timeout: MaxIdleTimeout,
1551        max_udp_payload_size: MaxUdpPayloadSize,
1552        initial_max_data: InitialMaxData,
1553        initial_max_stream_data_bidi_local: InitialMaxStreamDataBidiLocal,
1554        initial_max_stream_data_bidi_remote: InitialMaxStreamDataBidiRemote,
1555        initial_max_stream_data_uni: InitialMaxStreamDataUni,
1556        initial_max_streams_bidi: InitialMaxStreamsBidi,
1557        initial_max_streams_uni: InitialMaxStreamsUni,
1558        max_datagram_frame_size: MaxDatagramFrameSize,
1559        ack_delay_exponent: AckDelayExponent,
1560        max_ack_delay: MaxAckDelay,
1561        migration_support: MigrationSupport,
1562        active_connection_id_limit: ActiveConnectionIdLimit,
1563        original_destination_connection_id: OriginalDestinationConnectionId,
1564        stateless_reset_token: StatelessResetToken,
1565        preferred_address: PreferredAddress,
1566        initial_source_connection_id: Option<InitialSourceConnectionId>,
1567        retry_source_connection_id: RetrySourceConnectionId,
1568        dc_supported_versions: DcSupportedVersions,
1569    }
1570);
1571
1572impl<
1573        OriginalDestinationConnectionId,
1574        StatelessResetToken,
1575        PreferredAddress,
1576        RetrySourceConnectionId,
1577    >
1578    TransportParameters<
1579        OriginalDestinationConnectionId,
1580        StatelessResetToken,
1581        PreferredAddress,
1582        RetrySourceConnectionId,
1583    >
1584{
1585    pub fn load_limits(&mut self, limits: &crate::connection::limits::Limits) {
1586        macro_rules! load {
1587            ($from:ident, $to:ident) => {
1588                self.$to = limits.$from;
1589            };
1590        }
1591
1592        load!(max_idle_timeout, max_idle_timeout);
1593        load!(data_window, initial_max_data);
1594        load!(
1595            bidirectional_local_data_window,
1596            initial_max_stream_data_bidi_local
1597        );
1598        load!(
1599            bidirectional_remote_data_window,
1600            initial_max_stream_data_bidi_remote
1601        );
1602        load!(unidirectional_data_window, initial_max_stream_data_uni);
1603        load!(
1604            max_open_remote_bidirectional_streams,
1605            initial_max_streams_bidi
1606        );
1607
1608        load!(
1609            max_open_remote_unidirectional_streams,
1610            initial_max_streams_uni
1611        );
1612        load!(max_ack_delay, max_ack_delay);
1613        load!(ack_delay_exponent, ack_delay_exponent);
1614        load!(max_active_connection_ids, active_connection_id_limit);
1615        load!(max_datagram_frame_size, max_datagram_frame_size);
1616        load!(migration_support, migration_support);
1617    }
1618}