1use std::{
17 convert::TryFrom,
18 net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6},
19};
20
21use bytes::{Buf, BufMut};
22use rand::{Rng as _, RngCore, seq::SliceRandom as _};
23use thiserror::Error;
24
25use crate::{
26 LOC_CID_COUNT, MAX_CID_SIZE, MAX_STREAM_COUNT, RESET_TOKEN_SIZE, ResetToken, Side,
27 TIMER_GRANULARITY, TransportError, TransportErrorCode, VarInt,
28 cid_generator::ConnectionIdGenerator,
29 cid_queue::CidQueue,
30 coding::{BufExt, BufMutExt, UnexpectedEnd},
31 config::{EndpointConfig, ServerConfig, TransportConfig},
32 shared::ConnectionId,
33};
34
35mod error_handling;
36#[cfg(test)]
37mod error_tests;
38#[cfg(test)]
39mod integration_tests;
40
41use error_handling::*;
42
43macro_rules! apply_params {
49 ($macro:ident) => {
50 $macro! {
51 max_idle_timeout(MaxIdleTimeout) = 0,
54 max_udp_payload_size(MaxUdpPayloadSize) = 65527,
56
57 initial_max_data(InitialMaxData) = 0,
59 initial_max_stream_data_bidi_local(InitialMaxStreamDataBidiLocal) = 0,
61 initial_max_stream_data_bidi_remote(InitialMaxStreamDataBidiRemote) = 0,
63 initial_max_stream_data_uni(InitialMaxStreamDataUni) = 0,
65
66 initial_max_streams_bidi(InitialMaxStreamsBidi) = 0,
68 initial_max_streams_uni(InitialMaxStreamsUni) = 0,
70
71 ack_delay_exponent(AckDelayExponent) = 3,
73 max_ack_delay(MaxAckDelay) = 25,
76 active_connection_id_limit(ActiveConnectionIdLimit) = 2,
78 }
79 };
80}
81
82macro_rules! make_struct {
83 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {
84 #[derive(Debug, Clone, Eq, PartialEq)]
86 pub struct TransportParameters {
87 $($(#[$doc])* pub(crate) $name : VarInt,)*
88
89 pub(crate) disable_active_migration: bool,
91 pub(crate) max_datagram_frame_size: Option<VarInt>,
93 pub(crate) initial_src_cid: Option<ConnectionId>,
96 pub(crate) grease_quic_bit: bool,
99
100 pub(crate) min_ack_delay: Option<VarInt>,
106
107 pub(crate) nat_traversal: Option<NatTraversalConfig>,
113
114 pub(crate) rfc_nat_traversal: bool,
118
119 pub(crate) address_discovery: Option<AddressDiscoveryConfig>,
123
124 pub(crate) pqc_algorithms: Option<PqcAlgorithms>,
128
129 pub(crate) original_dst_cid: Option<ConnectionId>,
133 pub(crate) retry_src_cid: Option<ConnectionId>,
136 pub(crate) stateless_reset_token: Option<ResetToken>,
138 pub(crate) preferred_address: Option<PreferredAddress>,
140 pub(crate) grease_transport_parameter: Option<ReservedTransportParameter>,
144
145 pub(crate) write_order: Option<[u8; TransportParameterId::SUPPORTED.len()]>,
150 }
151
152 impl TransportParameters {
156 pub(crate) fn default() -> Self {
158 Self {
159 $($name: VarInt::from_u32($default),)*
160
161 disable_active_migration: false,
162 max_datagram_frame_size: None,
163 initial_src_cid: None,
164 grease_quic_bit: false,
165 min_ack_delay: None,
166 nat_traversal: None,
167 rfc_nat_traversal: false,
168 address_discovery: None,
169 pqc_algorithms: None,
170
171 original_dst_cid: None,
172 retry_src_cid: None,
173 stateless_reset_token: None,
174 preferred_address: None,
175 grease_transport_parameter: None,
176 write_order: None,
177 }
178 }
179 }
180 }
181}
182
183apply_params!(make_struct);
184
185impl TransportParameters {
186 pub(crate) fn new(
187 config: &TransportConfig,
188 endpoint_config: &EndpointConfig,
189 cid_gen: &dyn ConnectionIdGenerator,
190 initial_src_cid: ConnectionId,
191 server_config: Option<&ServerConfig>,
192 rng: &mut impl RngCore,
193 ) -> Result<Self, TransportError> {
194 Ok(Self {
195 initial_src_cid: Some(initial_src_cid),
196 initial_max_streams_bidi: config.max_concurrent_bidi_streams,
197 initial_max_streams_uni: config.max_concurrent_uni_streams,
198 initial_max_data: config.receive_window,
199 initial_max_stream_data_bidi_local: config.stream_receive_window,
200 initial_max_stream_data_bidi_remote: config.stream_receive_window,
201 initial_max_stream_data_uni: config.stream_receive_window,
202 max_udp_payload_size: endpoint_config.max_udp_payload_size,
203 max_idle_timeout: config.max_idle_timeout.unwrap_or(VarInt(0)),
204 disable_active_migration: server_config.is_some_and(|c| !c.migration),
205 active_connection_id_limit: if cid_gen.cid_len() == 0 {
206 2 } else {
208 CidQueue::LEN as u32
209 }
210 .into(),
211 max_datagram_frame_size: config
212 .datagram_receive_buffer_size
213 .map(|x| (x.min(u16::MAX.into()) as u16).into()),
214 grease_quic_bit: endpoint_config.grease_quic_bit,
215 min_ack_delay: Some({
216 let micros = TIMER_GRANULARITY.as_micros();
217 let micros_u64 = u64::try_from(micros).unwrap_or_else(|_| {
219 tracing::error!("Timer granularity {} micros exceeds u64::MAX", micros);
220 1_000_000 });
222 VarInt::from_u64_bounded(micros_u64)
223 }),
224 grease_transport_parameter: Some(ReservedTransportParameter::random(rng)?),
225 write_order: Some({
226 let mut order = std::array::from_fn(|i| i as u8);
227 order.shuffle(rng);
228 order
229 }),
230 nat_traversal: config.nat_traversal_config.clone(),
231 rfc_nat_traversal: config.nat_traversal_config.is_some(), address_discovery: config.address_discovery_config,
233 pqc_algorithms: config.pqc_algorithms.clone(),
234 ..Self::default()
235 })
236 }
237
238 pub(crate) fn validate_resumption_from(&self, cached: &Self) -> Result<(), TransportError> {
241 if cached.active_connection_id_limit > self.active_connection_id_limit
242 || cached.initial_max_data > self.initial_max_data
243 || cached.initial_max_stream_data_bidi_local > self.initial_max_stream_data_bidi_local
244 || cached.initial_max_stream_data_bidi_remote > self.initial_max_stream_data_bidi_remote
245 || cached.initial_max_stream_data_uni > self.initial_max_stream_data_uni
246 || cached.initial_max_streams_bidi > self.initial_max_streams_bidi
247 || cached.initial_max_streams_uni > self.initial_max_streams_uni
248 || cached.max_datagram_frame_size > self.max_datagram_frame_size
249 || cached.grease_quic_bit && !self.grease_quic_bit
250 {
251 return Err(TransportError::PROTOCOL_VIOLATION(
252 "0-RTT accepted with incompatible transport parameters",
253 ));
254 }
255 Ok(())
256 }
257
258 pub(crate) fn issue_cids_limit(&self) -> u64 {
263 self.active_connection_id_limit.0.min(LOC_CID_COUNT)
264 }
265
266 pub fn nat_traversal_config(&self) -> Option<&NatTraversalConfig> {
271 self.nat_traversal.as_ref()
272 }
273
274 pub fn supports_rfc_nat_traversal(&self) -> bool {
278 self.rfc_nat_traversal
279 }
280
281 pub fn pqc_algorithms(&self) -> Option<&PqcAlgorithms> {
286 self.pqc_algorithms.as_ref()
287 }
288}
289
290#[derive(Debug, Clone, Eq, PartialEq, Default)]
295pub enum NatTraversalConfig {
296 #[default]
298 ClientSupport,
299 ServerSupport {
301 concurrency_limit: VarInt,
303 },
304}
305
306impl NatTraversalConfig {
310 pub fn client() -> Self {
312 Self::ClientSupport
313 }
314
315 pub fn server(concurrency_limit: VarInt) -> Result<Self, TransportError> {
317 if concurrency_limit.0 == 0 {
318 return Err(TransportError::TRANSPORT_PARAMETER_ERROR(
319 "concurrency_limit must be greater than 0",
320 ));
321 }
322 if concurrency_limit.0 > 100 {
323 return Err(TransportError::TRANSPORT_PARAMETER_ERROR(
324 "concurrency_limit must not exceed 100",
325 ));
326 }
327 Ok(Self::ServerSupport { concurrency_limit })
328 }
329
330 pub fn concurrency_limit(&self) -> Option<VarInt> {
332 match self {
333 Self::ClientSupport => None,
334 Self::ServerSupport { concurrency_limit } => Some(*concurrency_limit),
335 }
336 }
337
338 pub fn is_client(&self) -> bool {
340 matches!(self, Self::ClientSupport)
341 }
342
343 pub fn is_server(&self) -> bool {
345 matches!(self, Self::ServerSupport { .. })
346 }
347}
348
349#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
351pub enum AddressDiscoveryConfig {
352 SendOnly,
355 ReceiveOnly,
358 #[default]
361 SendAndReceive,
362}
363
364#[derive(Debug, Clone, Eq, PartialEq, Default)]
369pub struct PqcAlgorithms {
370 pub ml_kem_768: bool,
372 pub ml_dsa_65: bool,
374 pub hybrid_x25519_ml_kem: bool,
376 pub hybrid_ed25519_ml_dsa: bool,
378}
379
380impl AddressDiscoveryConfig {
381 pub fn to_value(&self) -> VarInt {
383 match self {
384 Self::SendOnly => VarInt::from_u32(0),
385 Self::ReceiveOnly => VarInt::from_u32(1),
386 Self::SendAndReceive => VarInt::from_u32(2),
387 }
388 }
389
390 pub fn from_value(value: VarInt) -> Result<Self, Error> {
392 match value.into_inner() {
393 0 => Ok(Self::SendOnly),
394 1 => Ok(Self::ReceiveOnly),
395 2 => Ok(Self::SendAndReceive),
396 _ => Err(Error::Malformed),
397 }
398 }
399}
400
401#[derive(Debug, Copy, Clone, Eq, PartialEq)]
403pub enum NatTraversalRole {
404 Client,
406 Server {
408 can_relay: bool,
410 },
411 Bootstrap,
413}
414
415#[derive(Debug, Copy, Clone, Eq, PartialEq)]
419pub(crate) struct PreferredAddress {
420 pub(crate) address_v4: Option<SocketAddrV4>,
421 pub(crate) address_v6: Option<SocketAddrV6>,
422 pub(crate) connection_id: ConnectionId,
423 pub(crate) stateless_reset_token: ResetToken,
424}
425
426impl PreferredAddress {
427 fn wire_size(&self) -> u16 {
428 4 + 2 + 16 + 2 + 1 + self.connection_id.len() as u16 + 16
429 }
430
431 fn write<W: BufMut>(&self, w: &mut W) {
432 w.write(self.address_v4.map_or(Ipv4Addr::UNSPECIFIED, |x| *x.ip()));
433 w.write::<u16>(self.address_v4.map_or(0, |x| x.port()));
434 w.write(self.address_v6.map_or(Ipv6Addr::UNSPECIFIED, |x| *x.ip()));
435 w.write::<u16>(self.address_v6.map_or(0, |x| x.port()));
436 w.write::<u8>(self.connection_id.len() as u8);
437 w.put_slice(&self.connection_id);
438 w.put_slice(&self.stateless_reset_token);
439 }
440
441 fn read<R: Buf>(r: &mut R) -> Result<Self, Error> {
442 let ip_v4 = r.get::<Ipv4Addr>()?;
443 let port_v4 = r.get::<u16>()?;
444 let ip_v6 = r.get::<Ipv6Addr>()?;
445 let port_v6 = r.get::<u16>()?;
446 let cid_len = r.get::<u8>()?;
447 if r.remaining() < cid_len as usize || cid_len > MAX_CID_SIZE as u8 {
448 return Err(Error::Malformed);
449 }
450 let mut stage = [0; MAX_CID_SIZE];
451 r.copy_to_slice(&mut stage[0..cid_len as usize]);
452 let cid = ConnectionId::new(&stage[0..cid_len as usize]);
453 if r.remaining() < 16 {
454 return Err(Error::Malformed);
455 }
456 let mut token = [0; RESET_TOKEN_SIZE];
457 r.copy_to_slice(&mut token);
458 let address_v4 = if ip_v4.is_unspecified() && port_v4 == 0 {
459 None
460 } else {
461 Some(SocketAddrV4::new(ip_v4, port_v4))
462 };
463 let address_v6 = if ip_v6.is_unspecified() && port_v6 == 0 {
464 None
465 } else {
466 Some(SocketAddrV6::new(ip_v6, port_v6, 0, 0))
467 };
468 if address_v4.is_none() && address_v6.is_none() {
469 return Err(Error::IllegalValue);
470 }
471 Ok(Self {
472 address_v4,
473 address_v6,
474 connection_id: cid,
475 stateless_reset_token: token.into(),
476 })
477 }
478}
479
480#[derive(Debug, Copy, Clone, Eq, PartialEq, Error)]
482pub enum Error {
483 #[error("parameter had illegal value")]
485 IllegalValue,
486 #[error("parameters were malformed")]
488 Malformed,
489}
490
491impl From<Error> for TransportError {
492 fn from(e: Error) -> Self {
493 match e {
494 Error::IllegalValue => Self::TRANSPORT_PARAMETER_ERROR("illegal value"),
495 Error::Malformed => Self::TRANSPORT_PARAMETER_ERROR("malformed"),
496 }
497 }
498}
499
500impl From<UnexpectedEnd> for Error {
501 fn from(_: UnexpectedEnd) -> Self {
502 Self::Malformed
503 }
504}
505
506impl TransportParameters {
507 pub fn write<W: BufMut>(&self, w: &mut W) {
509 for idx in self
510 .write_order
511 .as_ref()
512 .unwrap_or(&std::array::from_fn(|i| i as u8))
513 {
514 let id = TransportParameterId::SUPPORTED[*idx as usize];
515 match id {
516 TransportParameterId::ReservedTransportParameter => {
517 if let Some(param) = self.grease_transport_parameter {
518 param.write(w);
519 }
520 }
521 TransportParameterId::StatelessResetToken => {
522 if let Some(ref x) = self.stateless_reset_token {
523 w.write_var(id as u64);
524 w.write_var(16);
525 w.put_slice(x);
526 }
527 }
528 TransportParameterId::DisableActiveMigration => {
529 if self.disable_active_migration {
530 w.write_var(id as u64);
531 w.write_var(0);
532 }
533 }
534 TransportParameterId::MaxDatagramFrameSize => {
535 if let Some(x) = self.max_datagram_frame_size {
536 w.write_var(id as u64);
537 w.write_var(x.size() as u64);
538 w.write(x);
539 }
540 }
541 TransportParameterId::PreferredAddress => {
542 if let Some(ref x) = self.preferred_address {
543 w.write_var(id as u64);
544 w.write_var(x.wire_size() as u64);
545 x.write(w);
546 }
547 }
548 TransportParameterId::OriginalDestinationConnectionId => {
549 if let Some(ref cid) = self.original_dst_cid {
550 w.write_var(id as u64);
551 w.write_var(cid.len() as u64);
552 w.put_slice(cid);
553 }
554 }
555 TransportParameterId::InitialSourceConnectionId => {
556 if let Some(ref cid) = self.initial_src_cid {
557 w.write_var(id as u64);
558 w.write_var(cid.len() as u64);
559 w.put_slice(cid);
560 }
561 }
562 TransportParameterId::RetrySourceConnectionId => {
563 if let Some(ref cid) = self.retry_src_cid {
564 w.write_var(id as u64);
565 w.write_var(cid.len() as u64);
566 w.put_slice(cid);
567 }
568 }
569 TransportParameterId::GreaseQuicBit => {
570 if self.grease_quic_bit {
571 w.write_var(id as u64);
572 w.write_var(0);
573 }
574 }
575 TransportParameterId::MinAckDelayDraft07 => {
576 if let Some(x) = self.min_ack_delay {
577 w.write_var(id as u64);
578 w.write_var(x.size() as u64);
579 w.write(x);
580 }
581 }
582 TransportParameterId::NatTraversal => {
583 if let Some(ref config) = self.nat_traversal {
584 match config {
588 NatTraversalConfig::ClientSupport => {
589 w.write_var(id as u64);
591 w.write_var(0); }
593 NatTraversalConfig::ServerSupport { concurrency_limit } => {
594 w.write_var(id as u64);
596 w.write_var(concurrency_limit.size() as u64);
597 w.write_var(concurrency_limit.0);
598 }
599 }
600 }
601 }
602 TransportParameterId::AddressDiscovery => {
603 if let Some(ref config) = self.address_discovery {
604 w.write_var(id as u64);
605 let value = config.to_value();
606 w.write_var(value.size() as u64);
607 w.write_var(value.into_inner());
608 }
609 }
610 TransportParameterId::RfcNatTraversal => {
611 if self.rfc_nat_traversal {
612 w.write_var(id as u64);
614 w.write_var(0); }
616 }
617 TransportParameterId::PqcAlgorithms => {
618 if let Some(ref algorithms) = self.pqc_algorithms {
619 w.write_var(id as u64);
620 let mut value = 0u8;
622 if algorithms.ml_kem_768 {
623 value |= 1 << 0;
624 }
625 if algorithms.ml_dsa_65 {
626 value |= 1 << 1;
627 }
628 if algorithms.hybrid_x25519_ml_kem {
629 value |= 1 << 2;
630 }
631 if algorithms.hybrid_ed25519_ml_dsa {
632 value |= 1 << 3;
633 }
634 w.write_var(1u64); w.write(value);
636 }
637 }
638 id => {
639 macro_rules! write_params {
640 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {
641 match id {
642 $(TransportParameterId::$id => {
643 if self.$name.0 != $default {
644 w.write_var(id as u64);
645 w.write(VarInt::try_from(self.$name.size()).unwrap());
646 w.write(self.$name);
647 }
648 })*,
649 _ => {
650 panic!("Unsupported transport parameter reached write implementation: {id:?}");
653 }
654 }
655 }
656 }
657 apply_params!(write_params);
658 }
659 }
660 }
661 }
662
663 pub fn read<R: Buf>(side: Side, r: &mut R) -> Result<Self, Error> {
665 let mut params = Self::default();
667
668 macro_rules! param_state {
670 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {{
671 struct ParamState {
672 $($name: bool,)*
673 }
674
675 ParamState {
676 $($name: false,)*
677 }
678 }}
679 }
680 let mut got = apply_params!(param_state);
681
682 while r.has_remaining() {
683 let id = r.get_var()?;
684 let len = r.get_var()?;
685 if (r.remaining() as u64) < len {
686 return Err(Error::Malformed);
687 }
688 let len = len as usize;
689 let Ok(id) = TransportParameterId::try_from(id) else {
690 r.advance(len);
692 continue;
693 };
694
695 match id {
696 TransportParameterId::OriginalDestinationConnectionId => {
697 decode_cid(len, &mut params.original_dst_cid, r)?
698 }
699 TransportParameterId::StatelessResetToken => {
700 if len != 16 || params.stateless_reset_token.is_some() {
701 return Err(Error::Malformed);
702 }
703 let mut tok = [0; RESET_TOKEN_SIZE];
704 r.copy_to_slice(&mut tok);
705 params.stateless_reset_token = Some(tok.into());
706 }
707 TransportParameterId::DisableActiveMigration => {
708 if len != 0 || params.disable_active_migration {
709 return Err(Error::Malformed);
710 }
711 params.disable_active_migration = true;
712 }
713 TransportParameterId::PreferredAddress => {
714 if params.preferred_address.is_some() {
715 return Err(Error::Malformed);
716 }
717 params.preferred_address = Some(PreferredAddress::read(&mut r.take(len))?);
718 }
719 TransportParameterId::InitialSourceConnectionId => {
720 decode_cid(len, &mut params.initial_src_cid, r)?
721 }
722 TransportParameterId::RetrySourceConnectionId => {
723 decode_cid(len, &mut params.retry_src_cid, r)?
724 }
725 TransportParameterId::MaxDatagramFrameSize => {
726 if len > 8 || params.max_datagram_frame_size.is_some() {
727 return Err(Error::Malformed);
728 }
729 params.max_datagram_frame_size = Some(r.get().map_err(|_| Error::Malformed)?);
730 }
731 TransportParameterId::GreaseQuicBit => match len {
732 0 => params.grease_quic_bit = true,
733 _ => return Err(Error::Malformed),
734 },
735 TransportParameterId::MinAckDelayDraft07 => {
736 params.min_ack_delay = Some(r.get().map_err(|_| Error::Malformed)?)
737 }
738 TransportParameterId::NatTraversal => {
739 if params.nat_traversal.is_some() {
740 return Err(Error::Malformed);
741 }
742 match len {
747 0 => {
748 params.nat_traversal = Some(NatTraversalConfig::ClientSupport);
752 }
753 _ if len > 0 => {
754 let limit = r.get_var()?;
758 if limit == 0 {
759 return Err(Error::IllegalValue);
760 }
761 params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
762 concurrency_limit: VarInt::from_u64(limit)
763 .map_err(|_| Error::IllegalValue)?,
764 });
765 }
766 _ => {
767 return Err(Error::IllegalValue);
769 }
770 }
771 }
772 TransportParameterId::AddressDiscovery => {
773 if params.address_discovery.is_some() {
774 return Err(Error::Malformed);
775 }
776 let value = r.get_var()?;
777 let varint = VarInt::from_u64(value).map_err(|_| Error::Malformed)?;
778 params.address_discovery = Some(AddressDiscoveryConfig::from_value(varint)?);
779 }
780 TransportParameterId::RfcNatTraversal => {
781 if params.rfc_nat_traversal {
782 return Err(Error::Malformed);
783 }
784 if len != 0 {
785 return Err(Error::Malformed);
787 }
788 params.rfc_nat_traversal = true;
789 }
790 TransportParameterId::PqcAlgorithms => {
791 if params.pqc_algorithms.is_some() {
792 return Err(Error::Malformed);
793 }
794 if len != 1 {
795 return Err(Error::Malformed);
796 }
797 let value = r.get::<u8>()?;
798 params.pqc_algorithms = Some(PqcAlgorithms {
799 ml_kem_768: (value & (1 << 0)) != 0,
800 ml_dsa_65: (value & (1 << 1)) != 0,
801 hybrid_x25519_ml_kem: (value & (1 << 2)) != 0,
802 hybrid_ed25519_ml_dsa: (value & (1 << 3)) != 0,
803 });
804 }
805 _ => {
806 macro_rules! parse {
807 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {
808 match id {
809 $(TransportParameterId::$id => {
810 let value = r.get::<VarInt>()?;
811 if len != value.size() || got.$name { return Err(Error::Malformed); }
812 params.$name = value.into();
813 got.$name = true;
814 })*
815 _ => r.advance(len),
816 }
817 }
818 }
819 apply_params!(parse);
820 }
821 }
822 }
823
824 validate_ack_delay_exponent(params.ack_delay_exponent.0 as u8)
828 .map_err(|_| Error::IllegalValue)?;
829
830 validate_max_ack_delay(params.max_ack_delay).map_err(|_| Error::IllegalValue)?;
831
832 validate_active_connection_id_limit(params.active_connection_id_limit)
833 .map_err(|_| Error::IllegalValue)?;
834
835 validate_max_udp_payload_size(params.max_udp_payload_size)
836 .map_err(|_| Error::IllegalValue)?;
837
838 if params.initial_max_streams_bidi.0 > MAX_STREAM_COUNT {
840 TransportParameterErrorHandler::log_validation_failure(
841 "initial_max_streams_bidi",
842 params.initial_max_streams_bidi.0,
843 &format!("must be <= {MAX_STREAM_COUNT}"),
844 "RFC 9000 Section 4.6-2",
845 );
846 return Err(Error::IllegalValue);
847 }
848 if params.initial_max_streams_uni.0 > MAX_STREAM_COUNT {
849 TransportParameterErrorHandler::log_validation_failure(
850 "initial_max_streams_uni",
851 params.initial_max_streams_uni.0,
852 &format!("must be <= {MAX_STREAM_COUNT}"),
853 "RFC 9000 Section 4.6-2",
854 );
855 return Err(Error::IllegalValue);
856 }
857
858 validate_min_ack_delay(params.min_ack_delay, params.max_ack_delay)
860 .map_err(|_| Error::IllegalValue)?;
861
862 validate_server_only_params(side, ¶ms).map_err(|_| Error::IllegalValue)?;
864
865 if let Some(ref pref_addr) = params.preferred_address {
867 if pref_addr.connection_id.is_empty() {
868 TransportParameterErrorHandler::log_semantic_error(
869 "preferred_address with empty connection_id",
870 "RFC 9000 Section 18.2-4.38.1",
871 );
872 return Err(Error::IllegalValue);
873 }
874 }
875
876 if let Some(ref nat_config) = params.nat_traversal {
878 match (side, nat_config) {
880 (Side::Server, NatTraversalConfig::ClientSupport) => {
882 tracing::debug!("Server received valid ClientSupport NAT traversal parameter");
883 }
884 (Side::Client, NatTraversalConfig::ServerSupport { concurrency_limit }) => {
886 tracing::debug!(
887 "Client received valid ServerSupport with concurrency_limit: {}",
888 concurrency_limit
889 );
890 }
891 (Side::Server, NatTraversalConfig::ServerSupport { concurrency_limit }) => {
893 tracing::debug!(
894 "P2P: Server received ServerSupport with concurrency_limit: {} (symmetric P2P)",
895 concurrency_limit
896 );
897 if concurrency_limit.0 == 0 || concurrency_limit.0 > 100 {
899 TransportParameterErrorHandler::log_validation_failure(
900 "nat_traversal_concurrency_limit",
901 concurrency_limit.0,
902 "1-100",
903 "draft-seemann-quic-nat-traversal-02",
904 );
905 return Err(Error::IllegalValue);
906 }
907 }
908 (Side::Client, NatTraversalConfig::ClientSupport) => {
910 tracing::debug!("P2P: Client received ClientSupport (symmetric P2P)");
911 }
913 }
914 }
915
916 Ok(params)
917 }
918
919 pub fn negotiated_nat_concurrency_limit(
944 &self,
945 local_config: &NatTraversalConfig,
946 ) -> Option<u64> {
947 match (&self.nat_traversal, local_config) {
948 (
950 Some(NatTraversalConfig::ServerSupport {
951 concurrency_limit: remote,
952 }),
953 NatTraversalConfig::ServerSupport {
954 concurrency_limit: local,
955 },
956 ) => Some(local.0.min(remote.0)),
957
958 (
960 Some(NatTraversalConfig::ServerSupport { concurrency_limit }),
961 NatTraversalConfig::ClientSupport,
962 )
963 | (
964 Some(NatTraversalConfig::ClientSupport),
965 NatTraversalConfig::ServerSupport { concurrency_limit },
966 ) => Some(concurrency_limit.0),
967
968 _ => None,
970 }
971 }
972
973 pub fn supports_bidirectional_nat_traversal(&self) -> bool {
997 matches!(
998 &self.nat_traversal,
999 Some(NatTraversalConfig::ServerSupport { .. })
1000 )
1001 }
1002}
1003
1004#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1013pub(crate) struct ReservedTransportParameter {
1014 id: VarInt,
1016
1017 payload: [u8; Self::MAX_PAYLOAD_LEN],
1019
1020 payload_len: usize,
1022}
1023
1024impl ReservedTransportParameter {
1025 fn random(rng: &mut impl RngCore) -> Result<Self, TransportError> {
1031 let id = Self::generate_reserved_id(rng)?;
1032
1033 let payload_len = rng.gen_range(0..Self::MAX_PAYLOAD_LEN);
1034
1035 let payload = {
1036 let mut slice = [0u8; Self::MAX_PAYLOAD_LEN];
1037 rng.fill_bytes(&mut slice[..payload_len]);
1038 slice
1039 };
1040
1041 Ok(Self {
1042 id,
1043 payload,
1044 payload_len,
1045 })
1046 }
1047
1048 fn write(&self, w: &mut impl BufMut) {
1049 w.write_var(self.id.0);
1050 w.write_var(self.payload_len as u64);
1051 w.put_slice(&self.payload[..self.payload_len]);
1052 }
1053
1054 fn generate_reserved_id(rng: &mut impl RngCore) -> Result<VarInt, TransportError> {
1059 let id = {
1060 let rand = rng.gen_range(0u64..(1 << 62) - 27);
1061 let n = rand / 31;
1062 31 * n + 27
1063 };
1064 debug_assert!(
1065 id % 31 == 27,
1066 "generated id does not have the form of 31 * N + 27"
1067 );
1068 VarInt::from_u64(id).map_err(|_| TransportError {
1069 code: TransportErrorCode::INTERNAL_ERROR,
1070 frame: None,
1071 reason: "generated id does not fit into range of allowed transport parameter IDs"
1072 .to_string(),
1073 })
1074 }
1075
1076 const MAX_PAYLOAD_LEN: usize = 16;
1080}
1081
1082#[repr(u64)]
1083#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1084pub(crate) enum TransportParameterId {
1085 OriginalDestinationConnectionId = 0x00,
1087 MaxIdleTimeout = 0x01,
1088 StatelessResetToken = 0x02,
1089 MaxUdpPayloadSize = 0x03,
1090 InitialMaxData = 0x04,
1091 InitialMaxStreamDataBidiLocal = 0x05,
1092 InitialMaxStreamDataBidiRemote = 0x06,
1093 InitialMaxStreamDataUni = 0x07,
1094 InitialMaxStreamsBidi = 0x08,
1095 InitialMaxStreamsUni = 0x09,
1096 AckDelayExponent = 0x0A,
1097 MaxAckDelay = 0x0B,
1098 DisableActiveMigration = 0x0C,
1099 PreferredAddress = 0x0D,
1100 ActiveConnectionIdLimit = 0x0E,
1101 InitialSourceConnectionId = 0x0F,
1102 RetrySourceConnectionId = 0x10,
1103
1104 ReservedTransportParameter = 0x1B,
1106
1107 MaxDatagramFrameSize = 0x20,
1109
1110 GreaseQuicBit = 0x2AB2,
1112
1113 MinAckDelayDraft07 = 0xFF04DE1B,
1115
1116 NatTraversal = 0x3d7e9f0bca12fea6,
1119
1120 RfcNatTraversal = 0x3d7e9f0bca12fea8,
1123
1124 AddressDiscovery = 0x9f81a176,
1127 PqcAlgorithms = 0x50C0,
1130}
1131
1132impl TransportParameterId {
1133 const SUPPORTED: [Self; 25] = [
1135 Self::MaxIdleTimeout,
1136 Self::MaxUdpPayloadSize,
1137 Self::InitialMaxData,
1138 Self::InitialMaxStreamDataBidiLocal,
1139 Self::InitialMaxStreamDataBidiRemote,
1140 Self::InitialMaxStreamDataUni,
1141 Self::InitialMaxStreamsBidi,
1142 Self::InitialMaxStreamsUni,
1143 Self::AckDelayExponent,
1144 Self::MaxAckDelay,
1145 Self::ActiveConnectionIdLimit,
1146 Self::ReservedTransportParameter,
1147 Self::StatelessResetToken,
1148 Self::DisableActiveMigration,
1149 Self::MaxDatagramFrameSize,
1150 Self::PreferredAddress,
1151 Self::OriginalDestinationConnectionId,
1152 Self::InitialSourceConnectionId,
1153 Self::RetrySourceConnectionId,
1154 Self::GreaseQuicBit,
1155 Self::MinAckDelayDraft07,
1156 Self::NatTraversal,
1157 Self::RfcNatTraversal,
1158 Self::AddressDiscovery,
1159 Self::PqcAlgorithms,
1160 ];
1161}
1162
1163impl std::cmp::PartialEq<u64> for TransportParameterId {
1164 fn eq(&self, other: &u64) -> bool {
1165 *other == (*self as u64)
1166 }
1167}
1168
1169impl TryFrom<u64> for TransportParameterId {
1170 type Error = ();
1171
1172 fn try_from(value: u64) -> Result<Self, Self::Error> {
1173 let param = match value {
1174 id if Self::MaxIdleTimeout == id => Self::MaxIdleTimeout,
1175 id if Self::MaxUdpPayloadSize == id => Self::MaxUdpPayloadSize,
1176 id if Self::InitialMaxData == id => Self::InitialMaxData,
1177 id if Self::InitialMaxStreamDataBidiLocal == id => Self::InitialMaxStreamDataBidiLocal,
1178 id if Self::InitialMaxStreamDataBidiRemote == id => {
1179 Self::InitialMaxStreamDataBidiRemote
1180 }
1181 id if Self::InitialMaxStreamDataUni == id => Self::InitialMaxStreamDataUni,
1182 id if Self::InitialMaxStreamsBidi == id => Self::InitialMaxStreamsBidi,
1183 id if Self::InitialMaxStreamsUni == id => Self::InitialMaxStreamsUni,
1184 id if Self::AckDelayExponent == id => Self::AckDelayExponent,
1185 id if Self::MaxAckDelay == id => Self::MaxAckDelay,
1186 id if Self::ActiveConnectionIdLimit == id => Self::ActiveConnectionIdLimit,
1187 id if Self::ReservedTransportParameter == id => Self::ReservedTransportParameter,
1188 id if Self::StatelessResetToken == id => Self::StatelessResetToken,
1189 id if Self::DisableActiveMigration == id => Self::DisableActiveMigration,
1190 id if Self::MaxDatagramFrameSize == id => Self::MaxDatagramFrameSize,
1191 id if Self::PreferredAddress == id => Self::PreferredAddress,
1192 id if Self::OriginalDestinationConnectionId == id => {
1193 Self::OriginalDestinationConnectionId
1194 }
1195 id if Self::InitialSourceConnectionId == id => Self::InitialSourceConnectionId,
1196 id if Self::RetrySourceConnectionId == id => Self::RetrySourceConnectionId,
1197 id if Self::GreaseQuicBit == id => Self::GreaseQuicBit,
1198 id if Self::MinAckDelayDraft07 == id => Self::MinAckDelayDraft07,
1199 id if Self::NatTraversal == id => Self::NatTraversal,
1200 id if Self::RfcNatTraversal == id => Self::RfcNatTraversal,
1201 id if Self::AddressDiscovery == id => Self::AddressDiscovery,
1202 id if Self::PqcAlgorithms == id => Self::PqcAlgorithms,
1203 _ => return Err(()),
1204 };
1205 Ok(param)
1206 }
1207}
1208
1209fn decode_cid(len: usize, value: &mut Option<ConnectionId>, r: &mut impl Buf) -> Result<(), Error> {
1210 if len > MAX_CID_SIZE || value.is_some() || r.remaining() < len {
1211 return Err(Error::Malformed);
1212 }
1213
1214 *value = Some(ConnectionId::from_buf(r, len));
1215 Ok(())
1216}
1217
1218#[cfg(test)]
1219mod test {
1220 use super::*;
1221
1222 #[test]
1223 fn test_nat_traversal_transport_parameter_encoding_decoding() {
1224 let client_config = NatTraversalConfig::ClientSupport;
1228
1229 let mut client_params = TransportParameters::default();
1230 client_params.nat_traversal = Some(client_config);
1231
1232 let mut encoded = Vec::new();
1233 client_params.write(&mut encoded);
1234
1235 let server_decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1237 .expect("Failed to decode client transport parameters");
1238
1239 assert!(server_decoded.nat_traversal.is_some());
1241 let server_view = server_decoded.nat_traversal.unwrap();
1242 assert!(matches!(server_view, NatTraversalConfig::ClientSupport));
1243
1244 let server_config = NatTraversalConfig::ServerSupport {
1246 concurrency_limit: VarInt::from_u32(5),
1247 };
1248
1249 let mut server_params = TransportParameters::default();
1250 server_params.nat_traversal = Some(server_config);
1251
1252 let mut encoded = Vec::new();
1253 server_params.write(&mut encoded);
1254
1255 let client_decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1257 .expect("Failed to decode server transport parameters");
1258
1259 assert!(client_decoded.nat_traversal.is_some());
1261 let client_view = client_decoded.nat_traversal.unwrap();
1262 assert!(matches!(
1263 client_view,
1264 NatTraversalConfig::ServerSupport { .. }
1265 ));
1266 assert_eq!(client_view.concurrency_limit(), Some(VarInt::from_u32(5)));
1267 }
1268
1269 #[test]
1270 fn test_nat_traversal_parameter_without_peer_id() {
1271 let config = NatTraversalConfig::ClientSupport;
1273
1274 let mut params = TransportParameters::default();
1275 params.nat_traversal = Some(config);
1276
1277 let mut encoded = Vec::new();
1278 params.write(&mut encoded);
1279
1280 let decoded_params = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1282 .expect("Failed to decode transport parameters");
1283
1284 let decoded_config = decoded_params
1285 .nat_traversal
1286 .expect("NAT traversal config should be present");
1287
1288 assert!(matches!(decoded_config, NatTraversalConfig::ClientSupport));
1289
1290 let server_config = NatTraversalConfig::ServerSupport {
1292 concurrency_limit: VarInt::from_u32(4),
1293 };
1294
1295 let mut server_params = TransportParameters::default();
1296 server_params.nat_traversal = Some(server_config);
1297
1298 let mut server_encoded = Vec::new();
1299 server_params.write(&mut server_encoded);
1300
1301 let decoded_server_params =
1303 TransportParameters::read(Side::Client, &mut server_encoded.as_slice())
1304 .expect("Failed to decode server transport parameters");
1305
1306 let decoded_server_config = decoded_server_params
1307 .nat_traversal
1308 .expect("Server NAT traversal config should be present");
1309
1310 assert!(matches!(
1311 decoded_server_config,
1312 NatTraversalConfig::ServerSupport { concurrency_limit } if concurrency_limit == VarInt::from_u32(4)
1313 ));
1314 }
1315
1316 #[test]
1317 fn test_transport_parameters_without_nat_traversal() {
1318 let mut params = TransportParameters::default();
1320 params.nat_traversal = None;
1321
1322 let mut encoded = Vec::new();
1323 params.write(&mut encoded);
1324
1325 let decoded_params = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1326 .expect("Failed to decode transport parameters");
1327
1328 assert!(decoded_params.nat_traversal.is_none());
1329 }
1330
1331 #[test]
1332 fn test_nat_traversal_draft_compliant_encoding() {
1333 let client_config = NatTraversalConfig::ClientSupport;
1337
1338 let mut client_params = TransportParameters::default();
1339 client_params.nat_traversal = Some(client_config);
1340
1341 let mut encoded = Vec::new();
1342 client_params.write(&mut encoded);
1343
1344 use bytes::Buf;
1347 let mut cursor = &encoded[..];
1348 while cursor.has_remaining() {
1349 let id = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1350 let len = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1351 if id.0 == 0x3d7e9f0bca12fea6 {
1352 assert_eq!(len.0, 0, "Client should send empty value");
1354 break;
1355 }
1356 cursor.advance(len.0 as usize);
1358 }
1359
1360 let server_config = NatTraversalConfig::ServerSupport {
1362 concurrency_limit: VarInt::from_u32(5),
1363 };
1364
1365 let mut server_params = TransportParameters::default();
1366 server_params.nat_traversal = Some(server_config);
1367
1368 let mut encoded = Vec::new();
1369 server_params.write(&mut encoded);
1370
1371 let mut cursor = &encoded[..];
1373 while cursor.has_remaining() {
1374 let id = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1375 let len = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1376 if id.0 == 0x3d7e9f0bca12fea6 {
1377 assert_eq!(len.0, 1, "Server should send 1-byte value");
1379 let limit = cursor.chunk()[0];
1380 assert_eq!(limit, 5, "Server should send concurrency limit");
1381 break;
1382 }
1383 cursor.advance(len.0 as usize);
1385 }
1386 }
1387
1388 #[test]
1389 fn test_nat_traversal_draft_compliant_decoding() {
1390 let mut buf = Vec::new();
1392 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(0); let params = TransportParameters::read(Side::Server, &mut buf.as_slice())
1396 .expect("Failed to decode transport parameters");
1397
1398 let config = params
1399 .nat_traversal
1400 .expect("NAT traversal should be present");
1401 assert!(matches!(config, NatTraversalConfig::ClientSupport));
1402
1403 let mut buf = Vec::new();
1405 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(1); buf.put_u8(7); let params = TransportParameters::read(Side::Client, &mut buf.as_slice())
1410 .expect("Failed to decode transport parameters");
1411
1412 let config = params
1413 .nat_traversal
1414 .expect("NAT traversal should be present");
1415 assert!(matches!(
1416 config,
1417 NatTraversalConfig::ServerSupport { concurrency_limit } if concurrency_limit == VarInt::from_u32(7)
1418 ));
1419
1420 let mut buf = Vec::new();
1422 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(2); buf.put_u8(7);
1425 buf.put_u8(8);
1426
1427 let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1428 assert!(result.is_err(), "Should fail with invalid length");
1429 }
1430
1431 #[test]
1432 fn test_nat_traversal_parameter_id() {
1433 assert_eq!(
1435 TransportParameterId::NatTraversal as u64,
1436 0x3d7e9f0bca12fea6
1437 );
1438 }
1439
1440 #[test]
1441 fn test_nat_traversal_simple_encoding() {
1442 let mut client_params = TransportParameters::default();
1446 client_params.nat_traversal = Some(NatTraversalConfig::ClientSupport);
1447
1448 let mut encoded = Vec::new();
1449 client_params.write(&mut encoded);
1450
1451 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1453 .expect("Should decode client params");
1454 assert!(matches!(
1455 decoded.nat_traversal,
1456 Some(NatTraversalConfig::ClientSupport)
1457 ));
1458
1459 let mut server_params = TransportParameters::default();
1461 server_params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1462 concurrency_limit: VarInt::from_u32(10),
1463 });
1464
1465 let mut encoded = Vec::new();
1466 server_params.write(&mut encoded);
1467
1468 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1470 .expect("Should decode server params");
1471
1472 match decoded.nat_traversal {
1473 Some(NatTraversalConfig::ServerSupport { concurrency_limit }) => {
1474 assert_eq!(concurrency_limit, VarInt::from_u32(10));
1475 }
1476 _ => panic!("Expected ServerSupport variant"),
1477 }
1478 }
1479
1480 #[test]
1481 fn test_nat_traversal_config_validation() {
1482 let client_config = NatTraversalConfig::ClientSupport;
1484 assert!(client_config.is_client());
1485 assert_eq!(client_config.concurrency_limit(), None);
1486
1487 let server_config = NatTraversalConfig::server(VarInt::from_u32(5)).unwrap();
1489 assert!(server_config.is_server());
1490 assert_eq!(server_config.concurrency_limit(), Some(VarInt::from_u32(5)));
1491
1492 let result = NatTraversalConfig::server(VarInt::from_u32(0));
1494 assert!(result.is_err());
1495
1496 let result = NatTraversalConfig::server(VarInt::from_u32(101));
1498 assert!(result.is_err());
1499
1500 let min_server = NatTraversalConfig::server(VarInt::from_u32(1)).unwrap();
1502 assert_eq!(min_server.concurrency_limit(), Some(VarInt::from_u32(1)));
1503
1504 let max_server = NatTraversalConfig::server(VarInt::from_u32(100)).unwrap();
1505 assert_eq!(max_server.concurrency_limit(), Some(VarInt::from_u32(100)));
1506 }
1507
1508 #[test]
1509 fn test_nat_traversal_role_validation() {
1510 let mut buf = Vec::new();
1512 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(0); let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1517 assert!(
1518 result.is_ok(),
1519 "P2P: Client should accept ClientSupport from peer for symmetric P2P"
1520 );
1521
1522 let result = TransportParameters::read(Side::Server, &mut buf.as_slice());
1524 assert!(
1525 result.is_ok(),
1526 "Server should accept ClientSupport from client"
1527 );
1528
1529 let mut buf = Vec::new();
1531 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(1); buf.put_u8(5); let result = TransportParameters::read(Side::Server, &mut buf.as_slice());
1537 assert!(
1538 result.is_ok(),
1539 "P2P: Server should accept ServerSupport from peer for symmetric P2P"
1540 );
1541
1542 let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1544 assert!(
1545 result.is_ok(),
1546 "Client should accept ServerSupport from server"
1547 );
1548 }
1549
1550 #[test]
1551 fn test_nat_traversal_parameter_combinations() {
1552 let nat_config = NatTraversalConfig::ClientSupport;
1554
1555 let mut params = TransportParameters::default();
1556 params.nat_traversal = Some(nat_config);
1557 params.max_idle_timeout = VarInt::from_u32(30000);
1558 params.initial_max_data = VarInt::from_u32(1048576);
1559 params.grease_quic_bit = true;
1560
1561 let mut encoded = Vec::new();
1563 params.write(&mut encoded);
1564 assert!(!encoded.is_empty());
1565
1566 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1568 .expect("Should decode successfully");
1569
1570 let decoded_config = decoded
1572 .nat_traversal
1573 .expect("NAT traversal should be present");
1574 assert!(matches!(decoded_config, NatTraversalConfig::ClientSupport));
1575
1576 assert_eq!(decoded.max_idle_timeout, VarInt::from_u32(30000));
1578 assert_eq!(decoded.initial_max_data, VarInt::from_u32(1048576));
1579 assert!(decoded.grease_quic_bit);
1580 }
1581
1582 #[test]
1583 fn test_nat_traversal_default_config() {
1584 let default_config = NatTraversalConfig::default();
1585
1586 assert!(matches!(default_config, NatTraversalConfig::ClientSupport));
1587 assert!(default_config.is_client());
1588 assert_eq!(default_config.concurrency_limit(), None);
1589 }
1590
1591 #[test]
1592 fn test_nat_traversal_endpoint_role_negotiation() {
1593 let client_config = NatTraversalConfig::ClientSupport;
1597
1598 let mut client_params = TransportParameters::default();
1599 client_params.nat_traversal = Some(client_config);
1600
1601 let mut client_encoded = Vec::new();
1603 client_params.write(&mut client_encoded);
1604
1605 let server_received =
1607 TransportParameters::read(Side::Server, &mut client_encoded.as_slice())
1608 .expect("Server should decode client params");
1609
1610 let server_view = server_received
1612 .nat_traversal
1613 .expect("NAT traversal should be present");
1614 assert!(matches!(server_view, NatTraversalConfig::ClientSupport));
1615
1616 let server_config = NatTraversalConfig::ServerSupport {
1618 concurrency_limit: VarInt::from_u32(8),
1619 };
1620
1621 let mut server_params = TransportParameters::default();
1622 server_params.nat_traversal = Some(server_config);
1623
1624 let mut server_encoded = Vec::new();
1626 server_params.write(&mut server_encoded);
1627
1628 let client_received =
1630 TransportParameters::read(Side::Client, &mut server_encoded.as_slice())
1631 .expect("Client should decode server params");
1632
1633 let client_view = client_received
1635 .nat_traversal
1636 .expect("NAT traversal should be present");
1637 assert!(matches!(
1638 client_view,
1639 NatTraversalConfig::ServerSupport { concurrency_limit } if concurrency_limit == VarInt::from_u32(8)
1640 ));
1641 }
1642
1643 #[test]
1646 fn test_p2p_nat_traversal_both_server_support() {
1647 let peer1_config = NatTraversalConfig::ServerSupport {
1651 concurrency_limit: VarInt::from_u32(10),
1652 };
1653 let _peer2_config = NatTraversalConfig::ServerSupport {
1654 concurrency_limit: VarInt::from_u32(5),
1655 };
1656
1657 let mut peer1_params = TransportParameters::default();
1659 peer1_params.nat_traversal = Some(peer1_config);
1660
1661 let mut encoded = Vec::new();
1662 peer1_params.write(&mut encoded);
1663
1664 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1667 .expect("P2P: Server should accept ServerSupport from peer");
1668
1669 assert!(matches!(
1671 decoded.nat_traversal,
1672 Some(NatTraversalConfig::ServerSupport { concurrency_limit })
1673 if concurrency_limit == VarInt::from_u32(10)
1674 ));
1675 }
1676
1677 #[test]
1678 fn test_p2p_nat_traversal_concurrency_negotiation() {
1679 let local = NatTraversalConfig::ServerSupport {
1682 concurrency_limit: VarInt::from_u32(10),
1683 };
1684 let mut remote_params = TransportParameters::default();
1685 remote_params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1686 concurrency_limit: VarInt::from_u32(5),
1687 });
1688
1689 let negotiated = remote_params.negotiated_nat_concurrency_limit(&local);
1691 assert_eq!(negotiated, Some(5));
1692
1693 let local2 = NatTraversalConfig::ServerSupport {
1695 concurrency_limit: VarInt::from_u32(3),
1696 };
1697 let mut remote_params2 = TransportParameters::default();
1698 remote_params2.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1699 concurrency_limit: VarInt::from_u32(8),
1700 });
1701
1702 let negotiated2 = remote_params2.negotiated_nat_concurrency_limit(&local2);
1703 assert_eq!(negotiated2, Some(3));
1704 }
1705
1706 #[test]
1707 fn test_p2p_nat_traversal_invalid_concurrency() {
1708 let config = NatTraversalConfig::ServerSupport {
1711 concurrency_limit: VarInt::from_u32(0), };
1713
1714 let mut params = TransportParameters::default();
1715 params.nat_traversal = Some(config);
1716
1717 let mut encoded = Vec::new();
1718 params.write(&mut encoded);
1719
1720 let result = TransportParameters::read(Side::Server, &mut encoded.as_slice());
1722 assert!(
1723 matches!(result, Err(Error::IllegalValue)),
1724 "Should reject concurrency_limit = 0"
1725 );
1726 }
1727
1728 #[test]
1729 fn test_p2p_nat_traversal_max_concurrency() {
1730 let config = NatTraversalConfig::ServerSupport {
1733 concurrency_limit: VarInt::from_u32(101), };
1735
1736 let mut params = TransportParameters::default();
1737 params.nat_traversal = Some(config);
1738
1739 let mut encoded = Vec::new();
1740 params.write(&mut encoded);
1741
1742 let result = TransportParameters::read(Side::Server, &mut encoded.as_slice());
1744 assert!(
1745 matches!(result, Err(Error::IllegalValue)),
1746 "Should reject concurrency_limit > 100"
1747 );
1748 }
1749
1750 #[test]
1751 fn test_p2p_both_client_support() {
1752 let config = NatTraversalConfig::ClientSupport;
1756
1757 let mut params = TransportParameters::default();
1758 params.nat_traversal = Some(config);
1759
1760 let mut encoded = Vec::new();
1761 params.write(&mut encoded);
1762
1763 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1765 .expect("P2P: Client should accept ClientSupport from peer");
1766
1767 assert!(matches!(
1768 decoded.nat_traversal,
1769 Some(NatTraversalConfig::ClientSupport)
1770 ));
1771 }
1772
1773 #[test]
1774 fn test_p2p_helper_methods() {
1775 let mut params_with_server = TransportParameters::default();
1779 params_with_server.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1780 concurrency_limit: VarInt::from_u32(5),
1781 });
1782 assert!(params_with_server.supports_bidirectional_nat_traversal());
1783
1784 let mut params_with_client = TransportParameters::default();
1785 params_with_client.nat_traversal = Some(NatTraversalConfig::ClientSupport);
1786 assert!(!params_with_client.supports_bidirectional_nat_traversal());
1787
1788 let params_without_nat = TransportParameters::default();
1789 assert!(!params_without_nat.supports_bidirectional_nat_traversal());
1790
1791 let local = NatTraversalConfig::ClientSupport;
1793 let mut remote_params = TransportParameters::default();
1794 remote_params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1795 concurrency_limit: VarInt::from_u32(10),
1796 });
1797
1798 let negotiated = remote_params.negotiated_nat_concurrency_limit(&local);
1800 assert_eq!(negotiated, Some(10));
1801 }
1802
1803 #[test]
1806 fn test_traditional_client_server_unchanged() {
1807 let client_config = NatTraversalConfig::ClientSupport;
1812 let mut client_params = TransportParameters::default();
1813 client_params.nat_traversal = Some(client_config);
1814
1815 let mut encoded = Vec::new();
1816 client_params.write(&mut encoded);
1817
1818 let server_decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1820 .expect("Traditional client/server should still work");
1821
1822 assert!(matches!(
1823 server_decoded.nat_traversal,
1824 Some(NatTraversalConfig::ClientSupport)
1825 ));
1826 }
1827
1828 #[test]
1829 fn test_traditional_server_client_unchanged() {
1830 let server_config = NatTraversalConfig::ServerSupport {
1835 concurrency_limit: VarInt::from_u32(10),
1836 };
1837 let mut server_params = TransportParameters::default();
1838 server_params.nat_traversal = Some(server_config);
1839
1840 let mut encoded = Vec::new();
1841 server_params.write(&mut encoded);
1842
1843 let client_decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1845 .expect("Traditional server/client should still work");
1846
1847 assert!(matches!(
1848 client_decoded.nat_traversal,
1849 Some(NatTraversalConfig::ServerSupport { concurrency_limit })
1850 if concurrency_limit == VarInt::from_u32(10)
1851 ));
1852 }
1853
1854 #[test]
1855 fn coding() {
1856 let mut buf = Vec::new();
1857 let params = TransportParameters {
1858 initial_src_cid: Some(ConnectionId::new(&[])),
1859 original_dst_cid: Some(ConnectionId::new(&[])),
1860 initial_max_streams_bidi: 16u32.into(),
1861 initial_max_streams_uni: 16u32.into(),
1862 ack_delay_exponent: 2u32.into(),
1863 max_udp_payload_size: 1200u32.into(),
1864 preferred_address: Some(PreferredAddress {
1865 address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
1866 address_v6: Some(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 24, 0, 0)),
1867 connection_id: ConnectionId::new(&[0x42]),
1868 stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
1869 }),
1870 grease_quic_bit: true,
1871 min_ack_delay: Some(2_000u32.into()),
1872 ..TransportParameters::default()
1873 };
1874 params.write(&mut buf);
1875 assert_eq!(
1876 TransportParameters::read(Side::Client, &mut buf.as_slice()).unwrap(),
1877 params
1878 );
1879 }
1880
1881 #[test]
1882 fn reserved_transport_parameter_generate_reserved_id() {
1883 use rand::rngs::mock::StepRng;
1884 let mut rngs = [
1885 StepRng::new(0, 1),
1886 StepRng::new(1, 1),
1887 StepRng::new(27, 1),
1888 StepRng::new(31, 1),
1889 StepRng::new(u32::MAX as u64, 1),
1890 StepRng::new(u32::MAX as u64 - 1, 1),
1891 StepRng::new(u32::MAX as u64 + 1, 1),
1892 StepRng::new(u32::MAX as u64 - 27, 1),
1893 StepRng::new(u32::MAX as u64 + 27, 1),
1894 StepRng::new(u32::MAX as u64 - 31, 1),
1895 StepRng::new(u32::MAX as u64 + 31, 1),
1896 StepRng::new(u64::MAX, 1),
1897 StepRng::new(u64::MAX - 1, 1),
1898 StepRng::new(u64::MAX - 27, 1),
1899 StepRng::new(u64::MAX - 31, 1),
1900 StepRng::new(1 << 62, 1),
1901 StepRng::new((1 << 62) - 1, 1),
1902 StepRng::new((1 << 62) + 1, 1),
1903 StepRng::new((1 << 62) - 27, 1),
1904 StepRng::new((1 << 62) + 27, 1),
1905 StepRng::new((1 << 62) - 31, 1),
1906 StepRng::new((1 << 62) + 31, 1),
1907 ];
1908 for rng in &mut rngs {
1909 let id = ReservedTransportParameter::generate_reserved_id(rng).unwrap();
1910 assert!(id.0 % 31 == 27)
1911 }
1912 }
1913
1914 #[test]
1915 fn reserved_transport_parameter_ignored_when_read() {
1916 let mut buf = Vec::new();
1917 let reserved_parameter =
1918 ReservedTransportParameter::random(&mut rand::thread_rng()).unwrap();
1919 assert!(reserved_parameter.payload_len < ReservedTransportParameter::MAX_PAYLOAD_LEN);
1920 assert!(reserved_parameter.id.0 % 31 == 27);
1921
1922 reserved_parameter.write(&mut buf);
1923 assert!(!buf.is_empty());
1924 let read_params = TransportParameters::read(Side::Server, &mut buf.as_slice()).unwrap();
1925 assert_eq!(read_params, TransportParameters::default());
1926 }
1927
1928 #[test]
1929 fn read_semantic_validation() {
1930 #[allow(clippy::type_complexity)]
1931 let illegal_params_builders: Vec<Box<dyn FnMut(&mut TransportParameters)>> = vec![
1932 Box::new(|t| {
1933 let min_ack_delay = t.max_ack_delay.0 * 1_000 + 1;
1935 t.min_ack_delay = Some(VarInt::from_u64(min_ack_delay).unwrap())
1936 }),
1937 Box::new(|t| {
1938 t.preferred_address = Some(PreferredAddress {
1941 address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
1942 address_v6: None,
1943 connection_id: ConnectionId::new(&[]),
1944 stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
1945 })
1946 }),
1947 ];
1948
1949 for mut builder in illegal_params_builders {
1950 let mut buf = Vec::new();
1951 let mut params = TransportParameters::default();
1952 builder(&mut params);
1953 params.write(&mut buf);
1954
1955 assert_eq!(
1956 TransportParameters::read(Side::Server, &mut buf.as_slice()),
1957 Err(Error::IllegalValue)
1958 );
1959 }
1960 }
1961
1962 #[test]
1963 fn resumption_params_validation() {
1964 let high_limit = TransportParameters {
1965 initial_max_streams_uni: 32u32.into(),
1966 ..TransportParameters::default()
1967 };
1968 let low_limit = TransportParameters {
1969 initial_max_streams_uni: 16u32.into(),
1970 ..TransportParameters::default()
1971 };
1972 high_limit.validate_resumption_from(&low_limit).unwrap();
1973 low_limit.validate_resumption_from(&high_limit).unwrap_err();
1974 }
1975
1976 #[test]
1977 fn test_address_discovery_parameter_id() {
1978 assert_eq!(TransportParameterId::AddressDiscovery as u64, 0x9f81a176);
1980 }
1981
1982 #[test]
1983 fn test_address_discovery_config_struct() {
1984 let send_only = AddressDiscoveryConfig::SendOnly;
1986 let receive_only = AddressDiscoveryConfig::ReceiveOnly;
1987 let send_receive = AddressDiscoveryConfig::SendAndReceive;
1988
1989 assert_eq!(send_only.to_value(), VarInt::from_u32(0));
1990 assert_eq!(receive_only.to_value(), VarInt::from_u32(1));
1991 assert_eq!(send_receive.to_value(), VarInt::from_u32(2));
1992 }
1993
1994 #[test]
1995 fn test_address_discovery_config_from_value() {
1996 assert_eq!(
1998 AddressDiscoveryConfig::from_value(VarInt::from_u32(0)).unwrap(),
1999 AddressDiscoveryConfig::SendOnly
2000 );
2001 assert_eq!(
2002 AddressDiscoveryConfig::from_value(VarInt::from_u32(1)).unwrap(),
2003 AddressDiscoveryConfig::ReceiveOnly
2004 );
2005 assert_eq!(
2006 AddressDiscoveryConfig::from_value(VarInt::from_u32(2)).unwrap(),
2007 AddressDiscoveryConfig::SendAndReceive
2008 );
2009 assert!(AddressDiscoveryConfig::from_value(VarInt::from_u32(3)).is_err());
2010 }
2011
2012 #[test]
2013 fn test_transport_parameters_with_address_discovery() {
2014 let mut params = TransportParameters::default();
2016 assert!(params.address_discovery.is_none());
2017
2018 let config = AddressDiscoveryConfig::SendAndReceive;
2019
2020 params.address_discovery = Some(config);
2021 assert!(params.address_discovery.is_some());
2022
2023 let stored_config = params.address_discovery.as_ref().unwrap();
2024 assert_eq!(*stored_config, AddressDiscoveryConfig::SendAndReceive);
2025 }
2026
2027 #[test]
2028 fn test_address_discovery_parameter_encoding() {
2029 let config = AddressDiscoveryConfig::SendAndReceive;
2031
2032 let mut params = TransportParameters::default();
2033 params.address_discovery = Some(config);
2034
2035 let mut encoded = Vec::new();
2036 params.write(&mut encoded);
2037
2038 assert!(!encoded.is_empty());
2040 }
2041
2042 #[test]
2043 fn test_address_discovery_parameter_roundtrip() {
2044 let config = AddressDiscoveryConfig::ReceiveOnly;
2046
2047 let mut params = TransportParameters::default();
2048 params.address_discovery = Some(config);
2049
2050 let mut encoded = Vec::new();
2051 params.write(&mut encoded);
2052
2053 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2055 .expect("Failed to decode transport parameters");
2056
2057 assert!(decoded.address_discovery.is_some());
2058 let decoded_config = decoded.address_discovery.as_ref().unwrap();
2059 assert_eq!(*decoded_config, AddressDiscoveryConfig::ReceiveOnly);
2060 }
2061
2062 #[test]
2063 fn test_address_discovery_disabled_by_default() {
2064 let params = TransportParameters::default();
2066 assert!(params.address_discovery.is_none());
2067 }
2068
2069 #[test]
2070 fn test_address_discovery_all_variants() {
2071 for variant in [
2073 AddressDiscoveryConfig::SendOnly,
2074 AddressDiscoveryConfig::ReceiveOnly,
2075 AddressDiscoveryConfig::SendAndReceive,
2076 ] {
2077 let mut params = TransportParameters::default();
2078 params.address_discovery = Some(variant);
2079
2080 let mut encoded = Vec::new();
2081 params.write(&mut encoded);
2082
2083 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
2084 .expect("Failed to decode");
2085
2086 assert_eq!(decoded.address_discovery, Some(variant));
2087 }
2088 }
2089
2090 #[test]
2091 fn test_address_discovery_none_not_encoded() {
2092 let mut params = TransportParameters::default();
2094 params.address_discovery = None;
2095
2096 let mut encoded = Vec::new();
2097 params.write(&mut encoded);
2098
2099 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2100 .expect("Failed to decode");
2101 assert!(decoded.address_discovery.is_none());
2102 }
2103
2104 #[test]
2105 fn test_address_discovery_serialization_roundtrip() {
2106 let config = AddressDiscoveryConfig::SendOnly;
2107
2108 let mut params = TransportParameters::default();
2109 params.address_discovery = Some(config);
2110 params.initial_max_data = VarInt::from_u32(1_000_000);
2111
2112 let mut encoded = Vec::new();
2113 params.write(&mut encoded);
2114
2115 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2116 .expect("Failed to decode");
2117
2118 assert_eq!(
2119 decoded.address_discovery,
2120 Some(AddressDiscoveryConfig::SendOnly)
2121 );
2122 assert_eq!(decoded.initial_max_data, VarInt::from_u32(1_000_000));
2123 }
2124
2125 #[test]
2126 fn test_address_discovery_invalid_value() {
2127 let mut encoded = Vec::new();
2130 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2131 encoded.write_var(1); encoded.write_var(3); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2135 assert!(result.is_err());
2136 }
2137
2138 #[test]
2139 fn test_address_discovery_edge_cases() {
2140 let mut encoded = Vec::new();
2144 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2145 encoded.write_var(0); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2148 assert!(result.is_err());
2149
2150 let mut encoded = Vec::new();
2152 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2153 encoded.write_var(1); encoded.put_u8(255); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2157 assert!(result.is_err());
2158 }
2159
2160 #[test]
2161 fn test_address_discovery_malformed_length() {
2162 let mut encoded = Vec::new();
2164 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2165 encoded.write_var(1); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2168 assert!(result.is_err());
2169 assert!(matches!(result.unwrap_err(), Error::Malformed));
2170 }
2171
2172 #[test]
2173 fn test_address_discovery_duplicate_parameter() {
2174 let mut encoded = Vec::new();
2176
2177 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2179 encoded.write_var(1);
2180 encoded.put_u8(0x80); encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2184 encoded.write_var(1);
2185 encoded.put_u8(0xC0); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2188 assert!(result.is_err());
2189 assert!(matches!(result.unwrap_err(), Error::Malformed));
2190 }
2191
2192 #[test]
2193 fn test_address_discovery_with_other_parameters() {
2194 let mut params = TransportParameters::default();
2196 params.max_idle_timeout = VarInt::from_u32(30000);
2197 params.initial_max_data = VarInt::from_u32(1_000_000);
2198 params.address_discovery = Some(AddressDiscoveryConfig::SendAndReceive);
2199
2200 let mut encoded = Vec::new();
2201 params.write(&mut encoded);
2202
2203 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2204 .expect("Failed to decode");
2205
2206 assert_eq!(decoded.max_idle_timeout, params.max_idle_timeout);
2208 assert_eq!(decoded.initial_max_data, params.initial_max_data);
2209 assert_eq!(
2210 decoded.address_discovery,
2211 Some(AddressDiscoveryConfig::SendAndReceive)
2212 );
2213 }
2214
2215 #[test]
2216 fn test_pqc_algorithms_transport_parameter() {
2217 let mut params = TransportParameters::default();
2219 params.pqc_algorithms = Some(PqcAlgorithms {
2220 ml_kem_768: true,
2221 ml_dsa_65: false,
2222 hybrid_x25519_ml_kem: true,
2223 hybrid_ed25519_ml_dsa: true,
2224 });
2225
2226 let mut encoded = Vec::new();
2228 params.write(&mut encoded);
2229
2230 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2232 .expect("Failed to decode");
2233
2234 assert!(decoded.pqc_algorithms.is_some());
2236 let pqc = decoded.pqc_algorithms.unwrap();
2237 assert!(pqc.ml_kem_768);
2238 assert!(!pqc.ml_dsa_65);
2239 assert!(pqc.hybrid_x25519_ml_kem);
2240 assert!(pqc.hybrid_ed25519_ml_dsa);
2241 }
2242
2243 #[test]
2244 fn test_pqc_algorithms_all_combinations() {
2245 for ml_kem in [false, true] {
2247 for ml_dsa in [false, true] {
2248 for hybrid_kex in [false, true] {
2249 for hybrid_sig in [false, true] {
2250 let mut params = TransportParameters::default();
2251 params.pqc_algorithms = Some(PqcAlgorithms {
2252 ml_kem_768: ml_kem,
2253 ml_dsa_65: ml_dsa,
2254 hybrid_x25519_ml_kem: hybrid_kex,
2255 hybrid_ed25519_ml_dsa: hybrid_sig,
2256 });
2257
2258 let mut encoded = Vec::new();
2260 params.write(&mut encoded);
2261 let decoded =
2262 TransportParameters::read(Side::Client, &mut encoded.as_slice())
2263 .expect("Failed to decode");
2264
2265 let pqc = decoded.pqc_algorithms.unwrap();
2267 assert_eq!(pqc.ml_kem_768, ml_kem);
2268 assert_eq!(pqc.ml_dsa_65, ml_dsa);
2269 assert_eq!(pqc.hybrid_x25519_ml_kem, hybrid_kex);
2270 assert_eq!(pqc.hybrid_ed25519_ml_dsa, hybrid_sig);
2271 }
2272 }
2273 }
2274 }
2275 }
2276
2277 #[test]
2278 fn test_pqc_algorithms_not_sent_when_none() {
2279 let mut params = TransportParameters::default();
2281 params.pqc_algorithms = None;
2282
2283 let mut encoded = Vec::new();
2284 params.write(&mut encoded);
2285
2286 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2289 .expect("Failed to decode");
2290 assert!(decoded.pqc_algorithms.is_none());
2291 }
2292
2293 #[test]
2294 fn test_pqc_algorithms_duplicate_parameter() {
2295 let mut encoded = Vec::new();
2297
2298 encoded.write_var(TransportParameterId::PqcAlgorithms as u64);
2300 encoded.write_var(1u64); encoded.write(0b1111u8); encoded.write_var(TransportParameterId::PqcAlgorithms as u64);
2305 encoded.write_var(1u64);
2306 encoded.write(0b0000u8);
2307
2308 let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2310 assert!(result.is_err());
2311 assert!(matches!(result.unwrap_err(), Error::Malformed));
2312 }
2313
2314 mod comprehensive_tests {
2316 include!("transport_parameters/tests.rs");
2317 }
2318}