1use 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
28mod error_handling;
29#[cfg(test)]
30mod error_tests;
31#[cfg(test)]
32mod integration_tests;
33
34use error_handling::*;
35
36macro_rules! apply_params {
42 ($macro:ident) => {
43 $macro! {
44 max_idle_timeout(MaxIdleTimeout) = 0,
47 max_udp_payload_size(MaxUdpPayloadSize) = 65527,
49
50 initial_max_data(InitialMaxData) = 0,
52 initial_max_stream_data_bidi_local(InitialMaxStreamDataBidiLocal) = 0,
54 initial_max_stream_data_bidi_remote(InitialMaxStreamDataBidiRemote) = 0,
56 initial_max_stream_data_uni(InitialMaxStreamDataUni) = 0,
58
59 initial_max_streams_bidi(InitialMaxStreamsBidi) = 0,
61 initial_max_streams_uni(InitialMaxStreamsUni) = 0,
63
64 ack_delay_exponent(AckDelayExponent) = 3,
66 max_ack_delay(MaxAckDelay) = 25,
69 active_connection_id_limit(ActiveConnectionIdLimit) = 2,
71 }
72 };
73}
74
75macro_rules! make_struct {
76 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {
77 #[derive(Debug, Clone, Eq, PartialEq)]
79 pub struct TransportParameters {
80 $($(#[$doc])* pub(crate) $name : VarInt,)*
81
82 pub(crate) disable_active_migration: bool,
84 pub(crate) max_datagram_frame_size: Option<VarInt>,
86 pub(crate) initial_src_cid: Option<ConnectionId>,
89 pub(crate) grease_quic_bit: bool,
92
93 pub(crate) min_ack_delay: Option<VarInt>,
99
100 pub(crate) nat_traversal: Option<NatTraversalConfig>,
106
107 pub(crate) rfc_nat_traversal: bool,
111
112 pub(crate) address_discovery: Option<AddressDiscoveryConfig>,
116
117 pub(crate) pqc_algorithms: Option<PqcAlgorithms>,
121
122 pub(crate) original_dst_cid: Option<ConnectionId>,
126 pub(crate) retry_src_cid: Option<ConnectionId>,
129 pub(crate) stateless_reset_token: Option<ResetToken>,
131 pub(crate) preferred_address: Option<PreferredAddress>,
133 pub(crate) grease_transport_parameter: Option<ReservedTransportParameter>,
137
138 pub(crate) write_order: Option<[u8; TransportParameterId::SUPPORTED.len()]>,
143 }
144
145 impl TransportParameters {
149 pub(crate) fn default() -> Self {
151 Self {
152 $($name: VarInt::from_u32($default),)*
153
154 disable_active_migration: false,
155 max_datagram_frame_size: None,
156 initial_src_cid: None,
157 grease_quic_bit: false,
158 min_ack_delay: None,
159 nat_traversal: None,
160 rfc_nat_traversal: false,
161 address_discovery: None,
162 pqc_algorithms: None,
163
164 original_dst_cid: None,
165 retry_src_cid: None,
166 stateless_reset_token: None,
167 preferred_address: None,
168 grease_transport_parameter: None,
169 write_order: None,
170 }
171 }
172 }
173 }
174}
175
176apply_params!(make_struct);
177
178impl TransportParameters {
179 pub(crate) fn new(
180 config: &TransportConfig,
181 endpoint_config: &EndpointConfig,
182 cid_gen: &dyn ConnectionIdGenerator,
183 initial_src_cid: ConnectionId,
184 server_config: Option<&ServerConfig>,
185 rng: &mut impl RngCore,
186 ) -> Self {
187 Self {
188 initial_src_cid: Some(initial_src_cid),
189 initial_max_streams_bidi: config.max_concurrent_bidi_streams,
190 initial_max_streams_uni: config.max_concurrent_uni_streams,
191 initial_max_data: config.receive_window,
192 initial_max_stream_data_bidi_local: config.stream_receive_window,
193 initial_max_stream_data_bidi_remote: config.stream_receive_window,
194 initial_max_stream_data_uni: config.stream_receive_window,
195 max_udp_payload_size: endpoint_config.max_udp_payload_size,
196 max_idle_timeout: config.max_idle_timeout.unwrap_or(VarInt(0)),
197 disable_active_migration: server_config.is_some_and(|c| !c.migration),
198 active_connection_id_limit: if cid_gen.cid_len() == 0 {
199 2 } else {
201 CidQueue::LEN as u32
202 }
203 .into(),
204 max_datagram_frame_size: config
205 .datagram_receive_buffer_size
206 .map(|x| (x.min(u16::MAX.into()) as u16).into()),
207 grease_quic_bit: endpoint_config.grease_quic_bit,
208 min_ack_delay: Some({
209 let micros = TIMER_GRANULARITY.as_micros();
210 let micros_u64 = u64::try_from(micros).unwrap_or_else(|_| {
212 tracing::error!("Timer granularity {} micros exceeds u64::MAX", micros);
213 1_000_000 });
215 VarInt::from_u64_bounded(micros_u64)
216 }),
217 grease_transport_parameter: Some(ReservedTransportParameter::random(rng)),
218 write_order: Some({
219 let mut order = std::array::from_fn(|i| i as u8);
220 order.shuffle(rng);
221 order
222 }),
223 nat_traversal: config.nat_traversal_config.clone(),
224 rfc_nat_traversal: config.nat_traversal_config.is_some(), address_discovery: config.address_discovery_config,
226 pqc_algorithms: config.pqc_algorithms.clone(),
227 ..Self::default()
228 }
229 }
230
231 pub(crate) fn validate_resumption_from(&self, cached: &Self) -> Result<(), TransportError> {
234 if cached.active_connection_id_limit > self.active_connection_id_limit
235 || cached.initial_max_data > self.initial_max_data
236 || cached.initial_max_stream_data_bidi_local > self.initial_max_stream_data_bidi_local
237 || cached.initial_max_stream_data_bidi_remote > self.initial_max_stream_data_bidi_remote
238 || cached.initial_max_stream_data_uni > self.initial_max_stream_data_uni
239 || cached.initial_max_streams_bidi > self.initial_max_streams_bidi
240 || cached.initial_max_streams_uni > self.initial_max_streams_uni
241 || cached.max_datagram_frame_size > self.max_datagram_frame_size
242 || cached.grease_quic_bit && !self.grease_quic_bit
243 {
244 return Err(TransportError::PROTOCOL_VIOLATION(
245 "0-RTT accepted with incompatible transport parameters",
246 ));
247 }
248 Ok(())
249 }
250
251 pub(crate) fn issue_cids_limit(&self) -> u64 {
256 self.active_connection_id_limit.0.min(LOC_CID_COUNT)
257 }
258
259 pub fn nat_traversal_config(&self) -> Option<&NatTraversalConfig> {
264 self.nat_traversal.as_ref()
265 }
266
267 pub fn supports_rfc_nat_traversal(&self) -> bool {
271 self.rfc_nat_traversal
272 }
273
274 pub fn pqc_algorithms(&self) -> Option<&PqcAlgorithms> {
279 self.pqc_algorithms.as_ref()
280 }
281}
282
283#[derive(Debug, Clone, Eq, PartialEq)]
288pub enum NatTraversalConfig {
289 ClientSupport,
291 ServerSupport {
293 concurrency_limit: VarInt,
295 },
296}
297
298impl NatTraversalConfig {
302 pub fn client() -> Self {
304 Self::ClientSupport
305 }
306
307 pub fn server(concurrency_limit: VarInt) -> Result<Self, TransportError> {
309 if concurrency_limit.0 == 0 {
310 return Err(TransportError::TRANSPORT_PARAMETER_ERROR(
311 "concurrency_limit must be greater than 0",
312 ));
313 }
314 if concurrency_limit.0 > 100 {
315 return Err(TransportError::TRANSPORT_PARAMETER_ERROR(
316 "concurrency_limit must not exceed 100",
317 ));
318 }
319 Ok(Self::ServerSupport { concurrency_limit })
320 }
321
322 pub fn concurrency_limit(&self) -> Option<VarInt> {
324 match self {
325 Self::ClientSupport => None,
326 Self::ServerSupport { concurrency_limit } => Some(*concurrency_limit),
327 }
328 }
329
330 pub fn is_client(&self) -> bool {
332 matches!(self, Self::ClientSupport)
333 }
334
335 pub fn is_server(&self) -> bool {
337 matches!(self, Self::ServerSupport { .. })
338 }
339}
340
341impl Default for NatTraversalConfig {
342 fn default() -> Self {
343 Self::ClientSupport
344 }
345}
346
347#[derive(Debug, Clone, Copy, PartialEq, Eq)]
349pub enum AddressDiscoveryConfig {
350 SendOnly,
353 ReceiveOnly,
356 SendAndReceive,
359}
360
361#[derive(Debug, Clone, Eq, PartialEq, Default)]
366pub struct PqcAlgorithms {
367 pub ml_kem_768: bool,
369 pub ml_dsa_65: bool,
371 pub hybrid_x25519_ml_kem: bool,
373 pub hybrid_ed25519_ml_dsa: bool,
375}
376
377impl AddressDiscoveryConfig {
378 pub fn to_value(&self) -> VarInt {
380 match self {
381 Self::SendOnly => VarInt::from_u32(0),
382 Self::ReceiveOnly => VarInt::from_u32(1),
383 Self::SendAndReceive => VarInt::from_u32(2),
384 }
385 }
386
387 pub fn from_value(value: VarInt) -> Result<Self, Error> {
389 match value.into_inner() {
390 0 => Ok(Self::SendOnly),
391 1 => Ok(Self::ReceiveOnly),
392 2 => Ok(Self::SendAndReceive),
393 _ => Err(Error::Malformed),
394 }
395 }
396}
397
398impl Default for AddressDiscoveryConfig {
399 fn default() -> Self {
400 Self::SendAndReceive
402 }
403}
404
405#[derive(Debug, Copy, Clone, Eq, PartialEq)]
407pub enum NatTraversalRole {
408 Client,
410 Server {
412 can_relay: bool,
414 },
415 Bootstrap,
417}
418
419#[derive(Debug, Copy, Clone, Eq, PartialEq)]
423pub(crate) struct PreferredAddress {
424 pub(crate) address_v4: Option<SocketAddrV4>,
425 pub(crate) address_v6: Option<SocketAddrV6>,
426 pub(crate) connection_id: ConnectionId,
427 pub(crate) stateless_reset_token: ResetToken,
428}
429
430impl PreferredAddress {
431 fn wire_size(&self) -> u16 {
432 4 + 2 + 16 + 2 + 1 + self.connection_id.len() as u16 + 16
433 }
434
435 fn write<W: BufMut>(&self, w: &mut W) {
436 w.write(self.address_v4.map_or(Ipv4Addr::UNSPECIFIED, |x| *x.ip()));
437 w.write::<u16>(self.address_v4.map_or(0, |x| x.port()));
438 w.write(self.address_v6.map_or(Ipv6Addr::UNSPECIFIED, |x| *x.ip()));
439 w.write::<u16>(self.address_v6.map_or(0, |x| x.port()));
440 w.write::<u8>(self.connection_id.len() as u8);
441 w.put_slice(&self.connection_id);
442 w.put_slice(&self.stateless_reset_token);
443 }
444
445 fn read<R: Buf>(r: &mut R) -> Result<Self, Error> {
446 let ip_v4 = r.get::<Ipv4Addr>()?;
447 let port_v4 = r.get::<u16>()?;
448 let ip_v6 = r.get::<Ipv6Addr>()?;
449 let port_v6 = r.get::<u16>()?;
450 let cid_len = r.get::<u8>()?;
451 if r.remaining() < cid_len as usize || cid_len > MAX_CID_SIZE as u8 {
452 return Err(Error::Malformed);
453 }
454 let mut stage = [0; MAX_CID_SIZE];
455 r.copy_to_slice(&mut stage[0..cid_len as usize]);
456 let cid = ConnectionId::new(&stage[0..cid_len as usize]);
457 if r.remaining() < 16 {
458 return Err(Error::Malformed);
459 }
460 let mut token = [0; RESET_TOKEN_SIZE];
461 r.copy_to_slice(&mut token);
462 let address_v4 = if ip_v4.is_unspecified() && port_v4 == 0 {
463 None
464 } else {
465 Some(SocketAddrV4::new(ip_v4, port_v4))
466 };
467 let address_v6 = if ip_v6.is_unspecified() && port_v6 == 0 {
468 None
469 } else {
470 Some(SocketAddrV6::new(ip_v6, port_v6, 0, 0))
471 };
472 if address_v4.is_none() && address_v6.is_none() {
473 return Err(Error::IllegalValue);
474 }
475 Ok(Self {
476 address_v4,
477 address_v6,
478 connection_id: cid,
479 stateless_reset_token: token.into(),
480 })
481 }
482}
483
484#[derive(Debug, Copy, Clone, Eq, PartialEq, Error)]
486pub enum Error {
487 #[error("parameter had illegal value")]
489 IllegalValue,
490 #[error("parameters were malformed")]
492 Malformed,
493}
494
495impl From<Error> for TransportError {
496 fn from(e: Error) -> Self {
497 match e {
498 Error::IllegalValue => Self::TRANSPORT_PARAMETER_ERROR("illegal value"),
499 Error::Malformed => Self::TRANSPORT_PARAMETER_ERROR("malformed"),
500 }
501 }
502}
503
504impl From<UnexpectedEnd> for Error {
505 fn from(_: UnexpectedEnd) -> Self {
506 Self::Malformed
507 }
508}
509
510impl TransportParameters {
511 pub fn write<W: BufMut>(&self, w: &mut W) {
513 for idx in self
514 .write_order
515 .as_ref()
516 .unwrap_or(&std::array::from_fn(|i| i as u8))
517 {
518 let id = TransportParameterId::SUPPORTED[*idx as usize];
519 match id {
520 TransportParameterId::ReservedTransportParameter => {
521 if let Some(param) = self.grease_transport_parameter {
522 param.write(w);
523 }
524 }
525 TransportParameterId::StatelessResetToken => {
526 if let Some(ref x) = self.stateless_reset_token {
527 w.write_var(id as u64);
528 w.write_var(16);
529 w.put_slice(x);
530 }
531 }
532 TransportParameterId::DisableActiveMigration => {
533 if self.disable_active_migration {
534 w.write_var(id as u64);
535 w.write_var(0);
536 }
537 }
538 TransportParameterId::MaxDatagramFrameSize => {
539 if let Some(x) = self.max_datagram_frame_size {
540 w.write_var(id as u64);
541 w.write_var(x.size() as u64);
542 w.write(x);
543 }
544 }
545 TransportParameterId::PreferredAddress => {
546 if let Some(ref x) = self.preferred_address {
547 w.write_var(id as u64);
548 w.write_var(x.wire_size() as u64);
549 x.write(w);
550 }
551 }
552 TransportParameterId::OriginalDestinationConnectionId => {
553 if let Some(ref cid) = self.original_dst_cid {
554 w.write_var(id as u64);
555 w.write_var(cid.len() as u64);
556 w.put_slice(cid);
557 }
558 }
559 TransportParameterId::InitialSourceConnectionId => {
560 if let Some(ref cid) = self.initial_src_cid {
561 w.write_var(id as u64);
562 w.write_var(cid.len() as u64);
563 w.put_slice(cid);
564 }
565 }
566 TransportParameterId::RetrySourceConnectionId => {
567 if let Some(ref cid) = self.retry_src_cid {
568 w.write_var(id as u64);
569 w.write_var(cid.len() as u64);
570 w.put_slice(cid);
571 }
572 }
573 TransportParameterId::GreaseQuicBit => {
574 if self.grease_quic_bit {
575 w.write_var(id as u64);
576 w.write_var(0);
577 }
578 }
579 TransportParameterId::MinAckDelayDraft07 => {
580 if let Some(x) = self.min_ack_delay {
581 w.write_var(id as u64);
582 w.write_var(x.size() as u64);
583 w.write(x);
584 }
585 }
586 TransportParameterId::NatTraversal => {
587 if let Some(ref config) = self.nat_traversal {
588 match config {
592 NatTraversalConfig::ClientSupport => {
593 w.write_var(id as u64);
595 w.write_var(0); }
597 NatTraversalConfig::ServerSupport { concurrency_limit } => {
598 w.write_var(id as u64);
600 w.write_var(concurrency_limit.size() as u64);
601 w.write_var(concurrency_limit.0);
602 }
603 }
604 }
605 }
606 TransportParameterId::AddressDiscovery => {
607 if let Some(ref config) = self.address_discovery {
608 w.write_var(id as u64);
609 let value = config.to_value();
610 w.write_var(value.size() as u64);
611 w.write_var(value.into_inner());
612 }
613 }
614 TransportParameterId::RfcNatTraversal => {
615 if self.rfc_nat_traversal {
616 w.write_var(id as u64);
618 w.write_var(0); }
620 }
621 TransportParameterId::PqcAlgorithms => {
622 if let Some(ref algorithms) = self.pqc_algorithms {
623 w.write_var(id as u64);
624 let mut value = 0u8;
626 if algorithms.ml_kem_768 {
627 value |= 1 << 0;
628 }
629 if algorithms.ml_dsa_65 {
630 value |= 1 << 1;
631 }
632 if algorithms.hybrid_x25519_ml_kem {
633 value |= 1 << 2;
634 }
635 if algorithms.hybrid_ed25519_ml_dsa {
636 value |= 1 << 3;
637 }
638 w.write_var(1u64); w.write(value);
640 }
641 }
642 id => {
643 macro_rules! write_params {
644 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {
645 match id {
646 $(TransportParameterId::$id => {
647 if self.$name.0 != $default {
648 w.write_var(id as u64);
649 w.write(VarInt::try_from(self.$name.size()).unwrap());
650 w.write(self.$name);
651 }
652 })*,
653 _ => {
654 panic!("Unsupported transport parameter reached write implementation: {id:?}");
657 }
658 }
659 }
660 }
661 apply_params!(write_params);
662 }
663 }
664 }
665 }
666
667 pub fn read<R: Buf>(side: Side, r: &mut R) -> Result<Self, Error> {
669 let mut params = Self::default();
671
672 macro_rules! param_state {
674 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {{
675 struct ParamState {
676 $($name: bool,)*
677 }
678
679 ParamState {
680 $($name: false,)*
681 }
682 }}
683 }
684 let mut got = apply_params!(param_state);
685
686 while r.has_remaining() {
687 let id = r.get_var()?;
688 let len = r.get_var()?;
689 if (r.remaining() as u64) < len {
690 return Err(Error::Malformed);
691 }
692 let len = len as usize;
693 let Ok(id) = TransportParameterId::try_from(id) else {
694 r.advance(len);
696 continue;
697 };
698
699 match id {
700 TransportParameterId::OriginalDestinationConnectionId => {
701 decode_cid(len, &mut params.original_dst_cid, r)?
702 }
703 TransportParameterId::StatelessResetToken => {
704 if len != 16 || params.stateless_reset_token.is_some() {
705 return Err(Error::Malformed);
706 }
707 let mut tok = [0; RESET_TOKEN_SIZE];
708 r.copy_to_slice(&mut tok);
709 params.stateless_reset_token = Some(tok.into());
710 }
711 TransportParameterId::DisableActiveMigration => {
712 if len != 0 || params.disable_active_migration {
713 return Err(Error::Malformed);
714 }
715 params.disable_active_migration = true;
716 }
717 TransportParameterId::PreferredAddress => {
718 if params.preferred_address.is_some() {
719 return Err(Error::Malformed);
720 }
721 params.preferred_address = Some(PreferredAddress::read(&mut r.take(len))?);
722 }
723 TransportParameterId::InitialSourceConnectionId => {
724 decode_cid(len, &mut params.initial_src_cid, r)?
725 }
726 TransportParameterId::RetrySourceConnectionId => {
727 decode_cid(len, &mut params.retry_src_cid, r)?
728 }
729 TransportParameterId::MaxDatagramFrameSize => {
730 if len > 8 || params.max_datagram_frame_size.is_some() {
731 return Err(Error::Malformed);
732 }
733 params.max_datagram_frame_size = Some(r.get().unwrap());
734 }
735 TransportParameterId::GreaseQuicBit => match len {
736 0 => params.grease_quic_bit = true,
737 _ => return Err(Error::Malformed),
738 },
739 TransportParameterId::MinAckDelayDraft07 => {
740 params.min_ack_delay = Some(r.get().unwrap())
741 }
742 TransportParameterId::NatTraversal => {
743 if params.nat_traversal.is_some() {
744 return Err(Error::Malformed);
745 }
746 match (side, len) {
750 (Side::Server, 0) => {
751 params.nat_traversal = Some(NatTraversalConfig::ClientSupport);
753 }
754 (Side::Client, _) if len > 0 => {
755 let limit = r.get_var()?;
757 if limit == 0 {
758 return Err(Error::IllegalValue);
759 }
760 params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
761 concurrency_limit: VarInt::from_u64(limit)
762 .map_err(|_| Error::IllegalValue)?,
763 });
764 }
765 _ => {
766 return Err(Error::IllegalValue);
768 }
769 }
770 }
771 TransportParameterId::AddressDiscovery => {
772 if params.address_discovery.is_some() {
773 return Err(Error::Malformed);
774 }
775 let value = r.get_var()?;
776 let varint = VarInt::from_u64(value).map_err(|_| Error::Malformed)?;
777 params.address_discovery = Some(AddressDiscoveryConfig::from_value(varint)?);
778 }
779 TransportParameterId::RfcNatTraversal => {
780 if params.rfc_nat_traversal {
781 return Err(Error::Malformed);
782 }
783 if len != 0 {
784 return Err(Error::Malformed);
786 }
787 params.rfc_nat_traversal = true;
788 }
789 TransportParameterId::PqcAlgorithms => {
790 if params.pqc_algorithms.is_some() {
791 return Err(Error::Malformed);
792 }
793 if len != 1 {
794 return Err(Error::Malformed);
795 }
796 let value = r.get::<u8>()?;
797 params.pqc_algorithms = Some(PqcAlgorithms {
798 ml_kem_768: (value & (1 << 0)) != 0,
799 ml_dsa_65: (value & (1 << 1)) != 0,
800 hybrid_x25519_ml_kem: (value & (1 << 2)) != 0,
801 hybrid_ed25519_ml_dsa: (value & (1 << 3)) != 0,
802 });
803 }
804 _ => {
805 macro_rules! parse {
806 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {
807 match id {
808 $(TransportParameterId::$id => {
809 let value = r.get::<VarInt>()?;
810 if len != value.size() || got.$name { return Err(Error::Malformed); }
811 params.$name = value.into();
812 got.$name = true;
813 })*
814 _ => r.advance(len),
815 }
816 }
817 }
818 apply_params!(parse);
819 }
820 }
821 }
822
823 validate_ack_delay_exponent(params.ack_delay_exponent.0 as u8)
827 .map_err(|_| Error::IllegalValue)?;
828
829 validate_max_ack_delay(params.max_ack_delay).map_err(|_| Error::IllegalValue)?;
830
831 validate_active_connection_id_limit(params.active_connection_id_limit)
832 .map_err(|_| Error::IllegalValue)?;
833
834 validate_max_udp_payload_size(params.max_udp_payload_size)
835 .map_err(|_| Error::IllegalValue)?;
836
837 if params.initial_max_streams_bidi.0 > MAX_STREAM_COUNT {
839 TransportParameterErrorHandler::log_validation_failure(
840 "initial_max_streams_bidi",
841 params.initial_max_streams_bidi.0,
842 &format!("must be <= {MAX_STREAM_COUNT}"),
843 "RFC 9000 Section 4.6-2",
844 );
845 return Err(Error::IllegalValue);
846 }
847 if params.initial_max_streams_uni.0 > MAX_STREAM_COUNT {
848 TransportParameterErrorHandler::log_validation_failure(
849 "initial_max_streams_uni",
850 params.initial_max_streams_uni.0,
851 &format!("must be <= {MAX_STREAM_COUNT}"),
852 "RFC 9000 Section 4.6-2",
853 );
854 return Err(Error::IllegalValue);
855 }
856
857 validate_min_ack_delay(params.min_ack_delay, params.max_ack_delay)
859 .map_err(|_| Error::IllegalValue)?;
860
861 validate_server_only_params(side, ¶ms).map_err(|_| Error::IllegalValue)?;
863
864 if let Some(ref pref_addr) = params.preferred_address {
866 if pref_addr.connection_id.is_empty() {
867 TransportParameterErrorHandler::log_semantic_error(
868 "preferred_address with empty connection_id",
869 "RFC 9000 Section 18.2-4.38.1",
870 );
871 return Err(Error::IllegalValue);
872 }
873 }
874
875 if let Some(ref nat_config) = params.nat_traversal {
877 match (side, nat_config) {
879 (Side::Server, NatTraversalConfig::ClientSupport) => {
881 tracing::debug!("Server received valid ClientSupport NAT traversal parameter");
883 }
884 (Side::Client, NatTraversalConfig::ServerSupport { concurrency_limit }) => {
886 tracing::debug!(
888 "Client received valid ServerSupport with concurrency_limit: {}",
889 concurrency_limit
890 );
891 }
892 (Side::Server, NatTraversalConfig::ServerSupport { .. }) => {
894 TransportParameterErrorHandler::log_nat_traversal_error(
895 side,
896 "ServerSupport",
897 "ClientSupport",
898 );
899 return Err(Error::IllegalValue);
900 }
901 (Side::Client, NatTraversalConfig::ClientSupport) => {
902 TransportParameterErrorHandler::log_nat_traversal_error(
903 side,
904 "ClientSupport",
905 "ServerSupport",
906 );
907 return Err(Error::IllegalValue);
908 }
909 }
910 }
911
912 Ok(params)
913 }
914}
915
916#[derive(Debug, Copy, Clone, Eq, PartialEq)]
925pub(crate) struct ReservedTransportParameter {
926 id: VarInt,
928
929 payload: [u8; Self::MAX_PAYLOAD_LEN],
931
932 payload_len: usize,
934}
935
936impl ReservedTransportParameter {
937 fn random(rng: &mut impl RngCore) -> Self {
943 let id = Self::generate_reserved_id(rng);
944
945 let payload_len = rng.gen_range(0..Self::MAX_PAYLOAD_LEN);
946
947 let payload = {
948 let mut slice = [0u8; Self::MAX_PAYLOAD_LEN];
949 rng.fill_bytes(&mut slice[..payload_len]);
950 slice
951 };
952
953 Self {
954 id,
955 payload,
956 payload_len,
957 }
958 }
959
960 fn write(&self, w: &mut impl BufMut) {
961 w.write_var(self.id.0);
962 w.write_var(self.payload_len as u64);
963 w.put_slice(&self.payload[..self.payload_len]);
964 }
965
966 fn generate_reserved_id(rng: &mut impl RngCore) -> VarInt {
971 let id = {
972 let rand = rng.gen_range(0u64..(1 << 62) - 27);
973 let n = rand / 31;
974 31 * n + 27
975 };
976 debug_assert!(
977 id % 31 == 27,
978 "generated id does not have the form of 31 * N + 27"
979 );
980 VarInt::from_u64(id).expect(
981 "generated id does fit into range of allowed transport parameter IDs: [0; 2^62)",
982 )
983 }
984
985 const MAX_PAYLOAD_LEN: usize = 16;
989}
990
991#[repr(u64)]
992#[derive(Debug, Clone, Copy, PartialEq, Eq)]
993pub(crate) enum TransportParameterId {
994 OriginalDestinationConnectionId = 0x00,
996 MaxIdleTimeout = 0x01,
997 StatelessResetToken = 0x02,
998 MaxUdpPayloadSize = 0x03,
999 InitialMaxData = 0x04,
1000 InitialMaxStreamDataBidiLocal = 0x05,
1001 InitialMaxStreamDataBidiRemote = 0x06,
1002 InitialMaxStreamDataUni = 0x07,
1003 InitialMaxStreamsBidi = 0x08,
1004 InitialMaxStreamsUni = 0x09,
1005 AckDelayExponent = 0x0A,
1006 MaxAckDelay = 0x0B,
1007 DisableActiveMigration = 0x0C,
1008 PreferredAddress = 0x0D,
1009 ActiveConnectionIdLimit = 0x0E,
1010 InitialSourceConnectionId = 0x0F,
1011 RetrySourceConnectionId = 0x10,
1012
1013 ReservedTransportParameter = 0x1B,
1015
1016 MaxDatagramFrameSize = 0x20,
1018
1019 GreaseQuicBit = 0x2AB2,
1021
1022 MinAckDelayDraft07 = 0xFF04DE1B,
1024
1025 NatTraversal = 0x3d7e9f0bca12fea6,
1028
1029 RfcNatTraversal = 0x3d7e9f0bca12fea8,
1032
1033 AddressDiscovery = 0x9f81a176,
1036 PqcAlgorithms = 0x50C0,
1039}
1040
1041impl TransportParameterId {
1042 const SUPPORTED: [Self; 25] = [
1044 Self::MaxIdleTimeout,
1045 Self::MaxUdpPayloadSize,
1046 Self::InitialMaxData,
1047 Self::InitialMaxStreamDataBidiLocal,
1048 Self::InitialMaxStreamDataBidiRemote,
1049 Self::InitialMaxStreamDataUni,
1050 Self::InitialMaxStreamsBidi,
1051 Self::InitialMaxStreamsUni,
1052 Self::AckDelayExponent,
1053 Self::MaxAckDelay,
1054 Self::ActiveConnectionIdLimit,
1055 Self::ReservedTransportParameter,
1056 Self::StatelessResetToken,
1057 Self::DisableActiveMigration,
1058 Self::MaxDatagramFrameSize,
1059 Self::PreferredAddress,
1060 Self::OriginalDestinationConnectionId,
1061 Self::InitialSourceConnectionId,
1062 Self::RetrySourceConnectionId,
1063 Self::GreaseQuicBit,
1064 Self::MinAckDelayDraft07,
1065 Self::NatTraversal,
1066 Self::RfcNatTraversal,
1067 Self::AddressDiscovery,
1068 Self::PqcAlgorithms,
1069 ];
1070}
1071
1072impl std::cmp::PartialEq<u64> for TransportParameterId {
1073 fn eq(&self, other: &u64) -> bool {
1074 *other == (*self as u64)
1075 }
1076}
1077
1078impl TryFrom<u64> for TransportParameterId {
1079 type Error = ();
1080
1081 fn try_from(value: u64) -> Result<Self, Self::Error> {
1082 let param = match value {
1083 id if Self::MaxIdleTimeout == id => Self::MaxIdleTimeout,
1084 id if Self::MaxUdpPayloadSize == id => Self::MaxUdpPayloadSize,
1085 id if Self::InitialMaxData == id => Self::InitialMaxData,
1086 id if Self::InitialMaxStreamDataBidiLocal == id => Self::InitialMaxStreamDataBidiLocal,
1087 id if Self::InitialMaxStreamDataBidiRemote == id => {
1088 Self::InitialMaxStreamDataBidiRemote
1089 }
1090 id if Self::InitialMaxStreamDataUni == id => Self::InitialMaxStreamDataUni,
1091 id if Self::InitialMaxStreamsBidi == id => Self::InitialMaxStreamsBidi,
1092 id if Self::InitialMaxStreamsUni == id => Self::InitialMaxStreamsUni,
1093 id if Self::AckDelayExponent == id => Self::AckDelayExponent,
1094 id if Self::MaxAckDelay == id => Self::MaxAckDelay,
1095 id if Self::ActiveConnectionIdLimit == id => Self::ActiveConnectionIdLimit,
1096 id if Self::ReservedTransportParameter == id => Self::ReservedTransportParameter,
1097 id if Self::StatelessResetToken == id => Self::StatelessResetToken,
1098 id if Self::DisableActiveMigration == id => Self::DisableActiveMigration,
1099 id if Self::MaxDatagramFrameSize == id => Self::MaxDatagramFrameSize,
1100 id if Self::PreferredAddress == id => Self::PreferredAddress,
1101 id if Self::OriginalDestinationConnectionId == id => {
1102 Self::OriginalDestinationConnectionId
1103 }
1104 id if Self::InitialSourceConnectionId == id => Self::InitialSourceConnectionId,
1105 id if Self::RetrySourceConnectionId == id => Self::RetrySourceConnectionId,
1106 id if Self::GreaseQuicBit == id => Self::GreaseQuicBit,
1107 id if Self::MinAckDelayDraft07 == id => Self::MinAckDelayDraft07,
1108 id if Self::NatTraversal == id => Self::NatTraversal,
1109 id if Self::RfcNatTraversal == id => Self::RfcNatTraversal,
1110 id if Self::AddressDiscovery == id => Self::AddressDiscovery,
1111 id if Self::PqcAlgorithms == id => Self::PqcAlgorithms,
1112 _ => return Err(()),
1113 };
1114 Ok(param)
1115 }
1116}
1117
1118fn decode_cid(len: usize, value: &mut Option<ConnectionId>, r: &mut impl Buf) -> Result<(), Error> {
1119 if len > MAX_CID_SIZE || value.is_some() || r.remaining() < len {
1120 return Err(Error::Malformed);
1121 }
1122
1123 *value = Some(ConnectionId::from_buf(r, len));
1124 Ok(())
1125}
1126
1127#[cfg(test)]
1128mod test {
1129 use super::*;
1130
1131 #[test]
1132 fn test_nat_traversal_transport_parameter_encoding_decoding() {
1133 let client_config = NatTraversalConfig::ClientSupport;
1137
1138 let mut client_params = TransportParameters::default();
1139 client_params.nat_traversal = Some(client_config);
1140
1141 let mut encoded = Vec::new();
1142 client_params.write(&mut encoded);
1143
1144 let server_decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1146 .expect("Failed to decode client transport parameters");
1147
1148 assert!(server_decoded.nat_traversal.is_some());
1150 let server_view = server_decoded.nat_traversal.unwrap();
1151 assert!(matches!(server_view, NatTraversalConfig::ClientSupport));
1152
1153 let server_config = NatTraversalConfig::ServerSupport {
1155 concurrency_limit: VarInt::from_u32(5),
1156 };
1157
1158 let mut server_params = TransportParameters::default();
1159 server_params.nat_traversal = Some(server_config);
1160
1161 let mut encoded = Vec::new();
1162 server_params.write(&mut encoded);
1163
1164 let client_decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1166 .expect("Failed to decode server transport parameters");
1167
1168 assert!(client_decoded.nat_traversal.is_some());
1170 let client_view = client_decoded.nat_traversal.unwrap();
1171 assert!(matches!(
1172 client_view,
1173 NatTraversalConfig::ServerSupport { .. }
1174 ));
1175 assert_eq!(client_view.concurrency_limit(), Some(VarInt::from_u32(5)));
1176 }
1177
1178 #[test]
1179 fn test_nat_traversal_parameter_without_peer_id() {
1180 let config = NatTraversalConfig::ClientSupport;
1182
1183 let mut params = TransportParameters::default();
1184 params.nat_traversal = Some(config);
1185
1186 let mut encoded = Vec::new();
1187 params.write(&mut encoded);
1188
1189 let decoded_params = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1191 .expect("Failed to decode transport parameters");
1192
1193 let decoded_config = decoded_params
1194 .nat_traversal
1195 .expect("NAT traversal config should be present");
1196
1197 assert!(matches!(decoded_config, NatTraversalConfig::ClientSupport));
1198
1199 let server_config = NatTraversalConfig::ServerSupport {
1201 concurrency_limit: VarInt::from_u32(4),
1202 };
1203
1204 let mut server_params = TransportParameters::default();
1205 server_params.nat_traversal = Some(server_config);
1206
1207 let mut server_encoded = Vec::new();
1208 server_params.write(&mut server_encoded);
1209
1210 let decoded_server_params =
1212 TransportParameters::read(Side::Client, &mut server_encoded.as_slice())
1213 .expect("Failed to decode server transport parameters");
1214
1215 let decoded_server_config = decoded_server_params
1216 .nat_traversal
1217 .expect("Server NAT traversal config should be present");
1218
1219 assert!(matches!(
1220 decoded_server_config,
1221 NatTraversalConfig::ServerSupport { concurrency_limit } if concurrency_limit == VarInt::from_u32(4)
1222 ));
1223 }
1224
1225 #[test]
1226 fn test_transport_parameters_without_nat_traversal() {
1227 let mut params = TransportParameters::default();
1229 params.nat_traversal = None;
1230
1231 let mut encoded = Vec::new();
1232 params.write(&mut encoded);
1233
1234 let decoded_params = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1235 .expect("Failed to decode transport parameters");
1236
1237 assert!(decoded_params.nat_traversal.is_none());
1238 }
1239
1240 #[test]
1241 fn test_nat_traversal_draft_compliant_encoding() {
1242 let client_config = NatTraversalConfig::ClientSupport;
1246
1247 let mut client_params = TransportParameters::default();
1248 client_params.nat_traversal = Some(client_config);
1249
1250 let mut encoded = Vec::new();
1251 client_params.write(&mut encoded);
1252
1253 use bytes::Buf;
1256 let mut cursor = &encoded[..];
1257 while cursor.has_remaining() {
1258 let id = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1259 let len = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1260 if id.0 == 0x3d7e9f0bca12fea6 {
1261 assert_eq!(len.0, 0, "Client should send empty value");
1263 break;
1264 }
1265 cursor.advance(len.0 as usize);
1267 }
1268
1269 let server_config = NatTraversalConfig::ServerSupport {
1271 concurrency_limit: VarInt::from_u32(5),
1272 };
1273
1274 let mut server_params = TransportParameters::default();
1275 server_params.nat_traversal = Some(server_config);
1276
1277 let mut encoded = Vec::new();
1278 server_params.write(&mut encoded);
1279
1280 let mut cursor = &encoded[..];
1282 while cursor.has_remaining() {
1283 let id = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1284 let len = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1285 if id.0 == 0x3d7e9f0bca12fea6 {
1286 assert_eq!(len.0, 1, "Server should send 1-byte value");
1288 let limit = cursor.chunk()[0];
1289 assert_eq!(limit, 5, "Server should send concurrency limit");
1290 break;
1291 }
1292 cursor.advance(len.0 as usize);
1294 }
1295 }
1296
1297 #[test]
1298 fn test_nat_traversal_draft_compliant_decoding() {
1299 let mut buf = Vec::new();
1301 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(0); let params = TransportParameters::read(Side::Server, &mut buf.as_slice())
1305 .expect("Failed to decode transport parameters");
1306
1307 let config = params
1308 .nat_traversal
1309 .expect("NAT traversal should be present");
1310 assert!(matches!(config, NatTraversalConfig::ClientSupport));
1311
1312 let mut buf = Vec::new();
1314 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(1); buf.put_u8(7); let params = TransportParameters::read(Side::Client, &mut buf.as_slice())
1319 .expect("Failed to decode transport parameters");
1320
1321 let config = params
1322 .nat_traversal
1323 .expect("NAT traversal should be present");
1324 assert!(matches!(
1325 config,
1326 NatTraversalConfig::ServerSupport { concurrency_limit } if concurrency_limit == VarInt::from_u32(7)
1327 ));
1328
1329 let mut buf = Vec::new();
1331 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(2); buf.put_u8(7);
1334 buf.put_u8(8);
1335
1336 let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1337 assert!(result.is_err(), "Should fail with invalid length");
1338 }
1339
1340 #[test]
1341 fn test_nat_traversal_parameter_id() {
1342 assert_eq!(
1344 TransportParameterId::NatTraversal as u64,
1345 0x3d7e9f0bca12fea6
1346 );
1347 }
1348
1349 #[test]
1350 fn test_nat_traversal_simple_encoding() {
1351 let mut client_params = TransportParameters::default();
1355 client_params.nat_traversal = Some(NatTraversalConfig::ClientSupport);
1356
1357 let mut encoded = Vec::new();
1358 client_params.write(&mut encoded);
1359
1360 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1362 .expect("Should decode client params");
1363 assert!(matches!(
1364 decoded.nat_traversal,
1365 Some(NatTraversalConfig::ClientSupport)
1366 ));
1367
1368 let mut server_params = TransportParameters::default();
1370 server_params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1371 concurrency_limit: VarInt::from_u32(10),
1372 });
1373
1374 let mut encoded = Vec::new();
1375 server_params.write(&mut encoded);
1376
1377 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1379 .expect("Should decode server params");
1380
1381 match decoded.nat_traversal {
1382 Some(NatTraversalConfig::ServerSupport { concurrency_limit }) => {
1383 assert_eq!(concurrency_limit, VarInt::from_u32(10));
1384 }
1385 _ => panic!("Expected ServerSupport variant"),
1386 }
1387 }
1388
1389 #[test]
1390 fn test_nat_traversal_config_validation() {
1391 let client_config = NatTraversalConfig::ClientSupport;
1393 assert!(client_config.is_client());
1394 assert_eq!(client_config.concurrency_limit(), None);
1395
1396 let server_config = NatTraversalConfig::server(VarInt::from_u32(5)).unwrap();
1398 assert!(server_config.is_server());
1399 assert_eq!(server_config.concurrency_limit(), Some(VarInt::from_u32(5)));
1400
1401 let result = NatTraversalConfig::server(VarInt::from_u32(0));
1403 assert!(result.is_err());
1404
1405 let result = NatTraversalConfig::server(VarInt::from_u32(101));
1407 assert!(result.is_err());
1408
1409 let min_server = NatTraversalConfig::server(VarInt::from_u32(1)).unwrap();
1411 assert_eq!(min_server.concurrency_limit(), Some(VarInt::from_u32(1)));
1412
1413 let max_server = NatTraversalConfig::server(VarInt::from_u32(100)).unwrap();
1414 assert_eq!(max_server.concurrency_limit(), Some(VarInt::from_u32(100)));
1415 }
1416
1417 #[test]
1418 fn test_nat_traversal_role_validation() {
1419 let mut buf = Vec::new();
1421 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(0); let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1426 assert!(
1427 result.is_err(),
1428 "Client should not accept client role from peer"
1429 );
1430
1431 let result = TransportParameters::read(Side::Server, &mut buf.as_slice());
1433 assert!(result.is_ok(), "Server should accept client role from peer");
1434
1435 let mut buf = Vec::new();
1437 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(1); buf.put_u8(5); let result = TransportParameters::read(Side::Server, &mut buf.as_slice());
1443 assert!(
1444 result.is_err(),
1445 "Server should not accept server role from peer"
1446 );
1447
1448 let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1450 assert!(result.is_ok(), "Client should accept server role from peer");
1451 }
1452
1453 #[test]
1454 fn test_nat_traversal_parameter_combinations() {
1455 let nat_config = NatTraversalConfig::ClientSupport;
1457
1458 let mut params = TransportParameters::default();
1459 params.nat_traversal = Some(nat_config);
1460 params.max_idle_timeout = VarInt::from_u32(30000);
1461 params.initial_max_data = VarInt::from_u32(1048576);
1462 params.grease_quic_bit = true;
1463
1464 let mut encoded = Vec::new();
1466 params.write(&mut encoded);
1467 assert!(!encoded.is_empty());
1468
1469 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1471 .expect("Should decode successfully");
1472
1473 let decoded_config = decoded
1475 .nat_traversal
1476 .expect("NAT traversal should be present");
1477 assert!(matches!(decoded_config, NatTraversalConfig::ClientSupport));
1478
1479 assert_eq!(decoded.max_idle_timeout, VarInt::from_u32(30000));
1481 assert_eq!(decoded.initial_max_data, VarInt::from_u32(1048576));
1482 assert!(decoded.grease_quic_bit);
1483 }
1484
1485 #[test]
1486 fn test_nat_traversal_default_config() {
1487 let default_config = NatTraversalConfig::default();
1488
1489 assert!(matches!(default_config, NatTraversalConfig::ClientSupport));
1490 assert!(default_config.is_client());
1491 assert_eq!(default_config.concurrency_limit(), None);
1492 }
1493
1494 #[test]
1495 fn test_nat_traversal_endpoint_role_negotiation() {
1496 let client_config = NatTraversalConfig::ClientSupport;
1500
1501 let mut client_params = TransportParameters::default();
1502 client_params.nat_traversal = Some(client_config);
1503
1504 let mut client_encoded = Vec::new();
1506 client_params.write(&mut client_encoded);
1507
1508 let server_received =
1510 TransportParameters::read(Side::Server, &mut client_encoded.as_slice())
1511 .expect("Server should decode client params");
1512
1513 let server_view = server_received
1515 .nat_traversal
1516 .expect("NAT traversal should be present");
1517 assert!(matches!(server_view, NatTraversalConfig::ClientSupport));
1518
1519 let server_config = NatTraversalConfig::ServerSupport {
1521 concurrency_limit: VarInt::from_u32(8),
1522 };
1523
1524 let mut server_params = TransportParameters::default();
1525 server_params.nat_traversal = Some(server_config);
1526
1527 let mut server_encoded = Vec::new();
1529 server_params.write(&mut server_encoded);
1530
1531 let client_received =
1533 TransportParameters::read(Side::Client, &mut server_encoded.as_slice())
1534 .expect("Client should decode server params");
1535
1536 let client_view = client_received
1538 .nat_traversal
1539 .expect("NAT traversal should be present");
1540 assert!(matches!(
1541 client_view,
1542 NatTraversalConfig::ServerSupport { concurrency_limit } if concurrency_limit == VarInt::from_u32(8)
1543 ));
1544 }
1545
1546 #[test]
1547 fn coding() {
1548 let mut buf = Vec::new();
1549 let params = TransportParameters {
1550 initial_src_cid: Some(ConnectionId::new(&[])),
1551 original_dst_cid: Some(ConnectionId::new(&[])),
1552 initial_max_streams_bidi: 16u32.into(),
1553 initial_max_streams_uni: 16u32.into(),
1554 ack_delay_exponent: 2u32.into(),
1555 max_udp_payload_size: 1200u32.into(),
1556 preferred_address: Some(PreferredAddress {
1557 address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
1558 address_v6: Some(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 24, 0, 0)),
1559 connection_id: ConnectionId::new(&[0x42]),
1560 stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
1561 }),
1562 grease_quic_bit: true,
1563 min_ack_delay: Some(2_000u32.into()),
1564 ..TransportParameters::default()
1565 };
1566 params.write(&mut buf);
1567 assert_eq!(
1568 TransportParameters::read(Side::Client, &mut buf.as_slice()).unwrap(),
1569 params
1570 );
1571 }
1572
1573 #[test]
1574 fn reserved_transport_parameter_generate_reserved_id() {
1575 use rand::rngs::mock::StepRng;
1576 let mut rngs = [
1577 StepRng::new(0, 1),
1578 StepRng::new(1, 1),
1579 StepRng::new(27, 1),
1580 StepRng::new(31, 1),
1581 StepRng::new(u32::MAX as u64, 1),
1582 StepRng::new(u32::MAX as u64 - 1, 1),
1583 StepRng::new(u32::MAX as u64 + 1, 1),
1584 StepRng::new(u32::MAX as u64 - 27, 1),
1585 StepRng::new(u32::MAX as u64 + 27, 1),
1586 StepRng::new(u32::MAX as u64 - 31, 1),
1587 StepRng::new(u32::MAX as u64 + 31, 1),
1588 StepRng::new(u64::MAX, 1),
1589 StepRng::new(u64::MAX - 1, 1),
1590 StepRng::new(u64::MAX - 27, 1),
1591 StepRng::new(u64::MAX - 31, 1),
1592 StepRng::new(1 << 62, 1),
1593 StepRng::new((1 << 62) - 1, 1),
1594 StepRng::new((1 << 62) + 1, 1),
1595 StepRng::new((1 << 62) - 27, 1),
1596 StepRng::new((1 << 62) + 27, 1),
1597 StepRng::new((1 << 62) - 31, 1),
1598 StepRng::new((1 << 62) + 31, 1),
1599 ];
1600 for rng in &mut rngs {
1601 let id = ReservedTransportParameter::generate_reserved_id(rng);
1602 assert!(id.0 % 31 == 27)
1603 }
1604 }
1605
1606 #[test]
1607 fn reserved_transport_parameter_ignored_when_read() {
1608 let mut buf = Vec::new();
1609 let reserved_parameter = ReservedTransportParameter::random(&mut rand::thread_rng());
1610 assert!(reserved_parameter.payload_len < ReservedTransportParameter::MAX_PAYLOAD_LEN);
1611 assert!(reserved_parameter.id.0 % 31 == 27);
1612
1613 reserved_parameter.write(&mut buf);
1614 assert!(!buf.is_empty());
1615 let read_params = TransportParameters::read(Side::Server, &mut buf.as_slice()).unwrap();
1616 assert_eq!(read_params, TransportParameters::default());
1617 }
1618
1619 #[test]
1620 fn read_semantic_validation() {
1621 #[allow(clippy::type_complexity)]
1622 let illegal_params_builders: Vec<Box<dyn FnMut(&mut TransportParameters)>> = vec![
1623 Box::new(|t| {
1624 let min_ack_delay = t.max_ack_delay.0 * 1_000 + 1;
1626 t.min_ack_delay = Some(VarInt::from_u64(min_ack_delay).unwrap())
1627 }),
1628 Box::new(|t| {
1629 t.preferred_address = Some(PreferredAddress {
1632 address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
1633 address_v6: None,
1634 connection_id: ConnectionId::new(&[]),
1635 stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
1636 })
1637 }),
1638 ];
1639
1640 for mut builder in illegal_params_builders {
1641 let mut buf = Vec::new();
1642 let mut params = TransportParameters::default();
1643 builder(&mut params);
1644 params.write(&mut buf);
1645
1646 assert_eq!(
1647 TransportParameters::read(Side::Server, &mut buf.as_slice()),
1648 Err(Error::IllegalValue)
1649 );
1650 }
1651 }
1652
1653 #[test]
1654 fn resumption_params_validation() {
1655 let high_limit = TransportParameters {
1656 initial_max_streams_uni: 32u32.into(),
1657 ..TransportParameters::default()
1658 };
1659 let low_limit = TransportParameters {
1660 initial_max_streams_uni: 16u32.into(),
1661 ..TransportParameters::default()
1662 };
1663 high_limit.validate_resumption_from(&low_limit).unwrap();
1664 low_limit.validate_resumption_from(&high_limit).unwrap_err();
1665 }
1666
1667 #[test]
1668 fn test_address_discovery_parameter_id() {
1669 assert_eq!(TransportParameterId::AddressDiscovery as u64, 0x9f81a176);
1671 }
1672
1673 #[test]
1674 fn test_address_discovery_config_struct() {
1675 let send_only = AddressDiscoveryConfig::SendOnly;
1677 let receive_only = AddressDiscoveryConfig::ReceiveOnly;
1678 let send_receive = AddressDiscoveryConfig::SendAndReceive;
1679
1680 assert_eq!(send_only.to_value(), VarInt::from_u32(0));
1681 assert_eq!(receive_only.to_value(), VarInt::from_u32(1));
1682 assert_eq!(send_receive.to_value(), VarInt::from_u32(2));
1683 }
1684
1685 #[test]
1686 fn test_address_discovery_config_from_value() {
1687 assert_eq!(
1689 AddressDiscoveryConfig::from_value(VarInt::from_u32(0)).unwrap(),
1690 AddressDiscoveryConfig::SendOnly
1691 );
1692 assert_eq!(
1693 AddressDiscoveryConfig::from_value(VarInt::from_u32(1)).unwrap(),
1694 AddressDiscoveryConfig::ReceiveOnly
1695 );
1696 assert_eq!(
1697 AddressDiscoveryConfig::from_value(VarInt::from_u32(2)).unwrap(),
1698 AddressDiscoveryConfig::SendAndReceive
1699 );
1700 assert!(AddressDiscoveryConfig::from_value(VarInt::from_u32(3)).is_err());
1701 }
1702
1703 #[test]
1704 fn test_transport_parameters_with_address_discovery() {
1705 let mut params = TransportParameters::default();
1707 assert!(params.address_discovery.is_none());
1708
1709 let config = AddressDiscoveryConfig::SendAndReceive;
1710
1711 params.address_discovery = Some(config);
1712 assert!(params.address_discovery.is_some());
1713
1714 let stored_config = params.address_discovery.as_ref().unwrap();
1715 assert_eq!(*stored_config, AddressDiscoveryConfig::SendAndReceive);
1716 }
1717
1718 #[test]
1719 fn test_address_discovery_parameter_encoding() {
1720 let config = AddressDiscoveryConfig::SendAndReceive;
1722
1723 let mut params = TransportParameters::default();
1724 params.address_discovery = Some(config);
1725
1726 let mut encoded = Vec::new();
1727 params.write(&mut encoded);
1728
1729 assert!(!encoded.is_empty());
1731 }
1732
1733 #[test]
1734 fn test_address_discovery_parameter_roundtrip() {
1735 let config = AddressDiscoveryConfig::ReceiveOnly;
1737
1738 let mut params = TransportParameters::default();
1739 params.address_discovery = Some(config);
1740
1741 let mut encoded = Vec::new();
1742 params.write(&mut encoded);
1743
1744 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1746 .expect("Failed to decode transport parameters");
1747
1748 assert!(decoded.address_discovery.is_some());
1749 let decoded_config = decoded.address_discovery.as_ref().unwrap();
1750 assert_eq!(*decoded_config, AddressDiscoveryConfig::ReceiveOnly);
1751 }
1752
1753 #[test]
1754 fn test_address_discovery_disabled_by_default() {
1755 let params = TransportParameters::default();
1757 assert!(params.address_discovery.is_none());
1758 }
1759
1760 #[test]
1761 fn test_address_discovery_all_variants() {
1762 for variant in [
1764 AddressDiscoveryConfig::SendOnly,
1765 AddressDiscoveryConfig::ReceiveOnly,
1766 AddressDiscoveryConfig::SendAndReceive,
1767 ] {
1768 let mut params = TransportParameters::default();
1769 params.address_discovery = Some(variant);
1770
1771 let mut encoded = Vec::new();
1772 params.write(&mut encoded);
1773
1774 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1775 .expect("Failed to decode");
1776
1777 assert_eq!(decoded.address_discovery, Some(variant));
1778 }
1779 }
1780
1781 #[test]
1782 fn test_address_discovery_none_not_encoded() {
1783 let mut params = TransportParameters::default();
1785 params.address_discovery = None;
1786
1787 let mut encoded = Vec::new();
1788 params.write(&mut encoded);
1789
1790 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1791 .expect("Failed to decode");
1792 assert!(decoded.address_discovery.is_none());
1793 }
1794
1795 #[test]
1796 fn test_address_discovery_serialization_roundtrip() {
1797 let config = AddressDiscoveryConfig::SendOnly;
1798
1799 let mut params = TransportParameters::default();
1800 params.address_discovery = Some(config);
1801 params.initial_max_data = VarInt::from_u32(1_000_000);
1802
1803 let mut encoded = Vec::new();
1804 params.write(&mut encoded);
1805
1806 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1807 .expect("Failed to decode");
1808
1809 assert_eq!(
1810 decoded.address_discovery,
1811 Some(AddressDiscoveryConfig::SendOnly)
1812 );
1813 assert_eq!(decoded.initial_max_data, VarInt::from_u32(1_000_000));
1814 }
1815
1816 #[test]
1817 fn test_address_discovery_invalid_value() {
1818 let mut encoded = Vec::new();
1821 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
1822 encoded.write_var(1); encoded.write_var(3); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
1826 assert!(result.is_err());
1827 }
1828
1829 #[test]
1830 fn test_address_discovery_edge_cases() {
1831 let mut encoded = Vec::new();
1835 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
1836 encoded.write_var(0); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
1839 assert!(result.is_err());
1840
1841 let mut encoded = Vec::new();
1843 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
1844 encoded.write_var(1); encoded.put_u8(255); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
1848 assert!(result.is_err());
1849 }
1850
1851 #[test]
1852 fn test_address_discovery_malformed_length() {
1853 let mut encoded = Vec::new();
1855 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
1856 encoded.write_var(1); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
1859 assert!(result.is_err());
1860 assert!(matches!(result.unwrap_err(), Error::Malformed));
1861 }
1862
1863 #[test]
1864 fn test_address_discovery_duplicate_parameter() {
1865 let mut encoded = Vec::new();
1867
1868 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
1870 encoded.write_var(1);
1871 encoded.put_u8(0x80); encoded.write_var(TransportParameterId::AddressDiscovery as u64);
1875 encoded.write_var(1);
1876 encoded.put_u8(0xC0); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
1879 assert!(result.is_err());
1880 assert!(matches!(result.unwrap_err(), Error::Malformed));
1881 }
1882
1883 #[test]
1884 fn test_address_discovery_with_other_parameters() {
1885 let mut params = TransportParameters::default();
1887 params.max_idle_timeout = VarInt::from_u32(30000);
1888 params.initial_max_data = VarInt::from_u32(1_000_000);
1889 params.address_discovery = Some(AddressDiscoveryConfig::SendAndReceive);
1890
1891 let mut encoded = Vec::new();
1892 params.write(&mut encoded);
1893
1894 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1895 .expect("Failed to decode");
1896
1897 assert_eq!(decoded.max_idle_timeout, params.max_idle_timeout);
1899 assert_eq!(decoded.initial_max_data, params.initial_max_data);
1900 assert_eq!(
1901 decoded.address_discovery,
1902 Some(AddressDiscoveryConfig::SendAndReceive)
1903 );
1904 }
1905
1906 #[test]
1907 fn test_pqc_algorithms_transport_parameter() {
1908 let mut params = TransportParameters::default();
1910 params.pqc_algorithms = Some(PqcAlgorithms {
1911 ml_kem_768: true,
1912 ml_dsa_65: false,
1913 hybrid_x25519_ml_kem: true,
1914 hybrid_ed25519_ml_dsa: true,
1915 });
1916
1917 let mut encoded = Vec::new();
1919 params.write(&mut encoded);
1920
1921 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1923 .expect("Failed to decode");
1924
1925 assert!(decoded.pqc_algorithms.is_some());
1927 let pqc = decoded.pqc_algorithms.unwrap();
1928 assert!(pqc.ml_kem_768);
1929 assert!(!pqc.ml_dsa_65);
1930 assert!(pqc.hybrid_x25519_ml_kem);
1931 assert!(pqc.hybrid_ed25519_ml_dsa);
1932 }
1933
1934 #[test]
1935 fn test_pqc_algorithms_all_combinations() {
1936 for ml_kem in [false, true] {
1938 for ml_dsa in [false, true] {
1939 for hybrid_kex in [false, true] {
1940 for hybrid_sig in [false, true] {
1941 let mut params = TransportParameters::default();
1942 params.pqc_algorithms = Some(PqcAlgorithms {
1943 ml_kem_768: ml_kem,
1944 ml_dsa_65: ml_dsa,
1945 hybrid_x25519_ml_kem: hybrid_kex,
1946 hybrid_ed25519_ml_dsa: hybrid_sig,
1947 });
1948
1949 let mut encoded = Vec::new();
1951 params.write(&mut encoded);
1952 let decoded =
1953 TransportParameters::read(Side::Client, &mut encoded.as_slice())
1954 .expect("Failed to decode");
1955
1956 let pqc = decoded.pqc_algorithms.unwrap();
1958 assert_eq!(pqc.ml_kem_768, ml_kem);
1959 assert_eq!(pqc.ml_dsa_65, ml_dsa);
1960 assert_eq!(pqc.hybrid_x25519_ml_kem, hybrid_kex);
1961 assert_eq!(pqc.hybrid_ed25519_ml_dsa, hybrid_sig);
1962 }
1963 }
1964 }
1965 }
1966 }
1967
1968 #[test]
1969 fn test_pqc_algorithms_not_sent_when_none() {
1970 let mut params = TransportParameters::default();
1972 params.pqc_algorithms = None;
1973
1974 let mut encoded = Vec::new();
1975 params.write(&mut encoded);
1976
1977 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1980 .expect("Failed to decode");
1981 assert!(decoded.pqc_algorithms.is_none());
1982 }
1983
1984 #[test]
1985 fn test_pqc_algorithms_duplicate_parameter() {
1986 let mut encoded = Vec::new();
1988
1989 encoded.write_var(TransportParameterId::PqcAlgorithms as u64);
1991 encoded.write_var(1u64); encoded.write(0b1111u8); encoded.write_var(TransportParameterId::PqcAlgorithms as u64);
1996 encoded.write_var(1u64);
1997 encoded.write(0b0000u8);
1998
1999 let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2001 assert!(result.is_err());
2002 assert!(matches!(result.unwrap_err(), Error::Malformed));
2003 }
2004
2005 mod comprehensive_tests {
2007 include!("transport_parameters/tests.rs");
2008 }
2009}