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 }
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
398#[derive(Debug, Copy, Clone, Eq, PartialEq)]
400pub enum NatTraversalRole {
401 Client,
403 Server {
405 can_relay: bool,
407 },
408 Bootstrap,
410}
411
412#[derive(Debug, Copy, Clone, Eq, PartialEq)]
416pub(crate) struct PreferredAddress {
417 pub(crate) address_v4: Option<SocketAddrV4>,
418 pub(crate) address_v6: Option<SocketAddrV6>,
419 pub(crate) connection_id: ConnectionId,
420 pub(crate) stateless_reset_token: ResetToken,
421}
422
423impl PreferredAddress {
424 fn wire_size(&self) -> u16 {
425 4 + 2 + 16 + 2 + 1 + self.connection_id.len() as u16 + 16
426 }
427
428 fn write<W: BufMut>(&self, w: &mut W) {
429 w.write(self.address_v4.map_or(Ipv4Addr::UNSPECIFIED, |x| *x.ip()));
430 w.write::<u16>(self.address_v4.map_or(0, |x| x.port()));
431 w.write(self.address_v6.map_or(Ipv6Addr::UNSPECIFIED, |x| *x.ip()));
432 w.write::<u16>(self.address_v6.map_or(0, |x| x.port()));
433 w.write::<u8>(self.connection_id.len() as u8);
434 w.put_slice(&self.connection_id);
435 w.put_slice(&self.stateless_reset_token);
436 }
437
438 fn read<R: Buf>(r: &mut R) -> Result<Self, Error> {
439 let ip_v4 = r.get::<Ipv4Addr>()?;
440 let port_v4 = r.get::<u16>()?;
441 let ip_v6 = r.get::<Ipv6Addr>()?;
442 let port_v6 = r.get::<u16>()?;
443 let cid_len = r.get::<u8>()?;
444 if r.remaining() < cid_len as usize || cid_len > MAX_CID_SIZE as u8 {
445 return Err(Error::Malformed);
446 }
447 let mut stage = [0; MAX_CID_SIZE];
448 r.copy_to_slice(&mut stage[0..cid_len as usize]);
449 let cid = ConnectionId::new(&stage[0..cid_len as usize]);
450 if r.remaining() < 16 {
451 return Err(Error::Malformed);
452 }
453 let mut token = [0; RESET_TOKEN_SIZE];
454 r.copy_to_slice(&mut token);
455 let address_v4 = if ip_v4.is_unspecified() && port_v4 == 0 {
456 None
457 } else {
458 Some(SocketAddrV4::new(ip_v4, port_v4))
459 };
460 let address_v6 = if ip_v6.is_unspecified() && port_v6 == 0 {
461 None
462 } else {
463 Some(SocketAddrV6::new(ip_v6, port_v6, 0, 0))
464 };
465 if address_v4.is_none() && address_v6.is_none() {
466 return Err(Error::IllegalValue);
467 }
468 Ok(Self {
469 address_v4,
470 address_v6,
471 connection_id: cid,
472 stateless_reset_token: token.into(),
473 })
474 }
475}
476
477#[derive(Debug, Copy, Clone, Eq, PartialEq, Error)]
479pub enum Error {
480 #[error("parameter had illegal value")]
482 IllegalValue,
483 #[error("parameters were malformed")]
485 Malformed,
486}
487
488impl From<Error> for TransportError {
489 fn from(e: Error) -> Self {
490 match e {
491 Error::IllegalValue => Self::TRANSPORT_PARAMETER_ERROR("illegal value"),
492 Error::Malformed => Self::TRANSPORT_PARAMETER_ERROR("malformed"),
493 }
494 }
495}
496
497impl From<UnexpectedEnd> for Error {
498 fn from(_: UnexpectedEnd) -> Self {
499 Self::Malformed
500 }
501}
502
503impl TransportParameters {
504 pub fn write<W: BufMut>(&self, w: &mut W) {
506 for idx in self
507 .write_order
508 .as_ref()
509 .unwrap_or(&std::array::from_fn(|i| i as u8))
510 {
511 let id = TransportParameterId::SUPPORTED[*idx as usize];
512 match id {
513 TransportParameterId::ReservedTransportParameter => {
514 if let Some(param) = self.grease_transport_parameter {
515 param.write(w);
516 }
517 }
518 TransportParameterId::StatelessResetToken => {
519 if let Some(ref x) = self.stateless_reset_token {
520 w.write_var(id as u64);
521 w.write_var(16);
522 w.put_slice(x);
523 }
524 }
525 TransportParameterId::DisableActiveMigration => {
526 if self.disable_active_migration {
527 w.write_var(id as u64);
528 w.write_var(0);
529 }
530 }
531 TransportParameterId::MaxDatagramFrameSize => {
532 if let Some(x) = self.max_datagram_frame_size {
533 w.write_var(id as u64);
534 w.write_var(x.size() as u64);
535 w.write(x);
536 }
537 }
538 TransportParameterId::PreferredAddress => {
539 if let Some(ref x) = self.preferred_address {
540 w.write_var(id as u64);
541 w.write_var(x.wire_size() as u64);
542 x.write(w);
543 }
544 }
545 TransportParameterId::OriginalDestinationConnectionId => {
546 if let Some(ref cid) = self.original_dst_cid {
547 w.write_var(id as u64);
548 w.write_var(cid.len() as u64);
549 w.put_slice(cid);
550 }
551 }
552 TransportParameterId::InitialSourceConnectionId => {
553 if let Some(ref cid) = self.initial_src_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::RetrySourceConnectionId => {
560 if let Some(ref cid) = self.retry_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::GreaseQuicBit => {
567 if self.grease_quic_bit {
568 w.write_var(id as u64);
569 w.write_var(0);
570 }
571 }
572 TransportParameterId::MinAckDelayDraft07 => {
573 if let Some(x) = self.min_ack_delay {
574 w.write_var(id as u64);
575 w.write_var(x.size() as u64);
576 w.write(x);
577 }
578 }
579 TransportParameterId::NatTraversal => {
580 if let Some(ref config) = self.nat_traversal {
581 match config {
585 NatTraversalConfig::ClientSupport => {
586 w.write_var(id as u64);
588 w.write_var(0); }
590 NatTraversalConfig::ServerSupport { concurrency_limit } => {
591 w.write_var(id as u64);
593 w.write_var(concurrency_limit.size() as u64);
594 w.write_var(concurrency_limit.0);
595 }
596 }
597 }
598 }
599 TransportParameterId::AddressDiscovery => {
600 if let Some(ref config) = self.address_discovery {
601 w.write_var(id as u64);
602 let value = config.to_value();
603 w.write_var(value.size() as u64);
604 w.write_var(value.into_inner());
605 }
606 }
607 TransportParameterId::RfcNatTraversal => {
608 if self.rfc_nat_traversal {
609 w.write_var(id as u64);
611 w.write_var(0); }
613 }
614 TransportParameterId::PqcAlgorithms => {
615 if let Some(ref algorithms) = self.pqc_algorithms {
616 w.write_var(id as u64);
617 let mut value = 0u8;
619 if algorithms.ml_kem_768 {
620 value |= 1 << 0;
621 }
622 if algorithms.ml_dsa_65 {
623 value |= 1 << 1;
624 }
625 w.write_var(1u64); w.write(value);
628 }
629 }
630 id => {
631 macro_rules! write_params {
632 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {
633 match id {
634 $(TransportParameterId::$id => {
635 if self.$name.0 != $default {
636 w.write_var(id as u64);
637 w.write(VarInt::try_from(self.$name.size()).unwrap());
638 w.write(self.$name);
639 }
640 })*,
641 _ => {
642 panic!("Unsupported transport parameter reached write implementation: {id:?}");
645 }
646 }
647 }
648 }
649 apply_params!(write_params);
650 }
651 }
652 }
653 }
654
655 pub fn read<R: Buf>(side: Side, r: &mut R) -> Result<Self, Error> {
657 let mut params = Self::default();
659
660 macro_rules! param_state {
662 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {{
663 struct ParamState {
664 $($name: bool,)*
665 }
666
667 ParamState {
668 $($name: false,)*
669 }
670 }}
671 }
672 let mut got = apply_params!(param_state);
673
674 while r.has_remaining() {
675 let id = r.get_var()?;
676 let len = r.get_var()?;
677 if (r.remaining() as u64) < len {
678 return Err(Error::Malformed);
679 }
680 let len = len as usize;
681 let Ok(id) = TransportParameterId::try_from(id) else {
682 r.advance(len);
684 continue;
685 };
686
687 match id {
688 TransportParameterId::OriginalDestinationConnectionId => {
689 decode_cid(len, &mut params.original_dst_cid, r)?
690 }
691 TransportParameterId::StatelessResetToken => {
692 if len != 16 || params.stateless_reset_token.is_some() {
693 return Err(Error::Malformed);
694 }
695 let mut tok = [0; RESET_TOKEN_SIZE];
696 r.copy_to_slice(&mut tok);
697 params.stateless_reset_token = Some(tok.into());
698 }
699 TransportParameterId::DisableActiveMigration => {
700 if len != 0 || params.disable_active_migration {
701 return Err(Error::Malformed);
702 }
703 params.disable_active_migration = true;
704 }
705 TransportParameterId::PreferredAddress => {
706 if params.preferred_address.is_some() {
707 return Err(Error::Malformed);
708 }
709 params.preferred_address = Some(PreferredAddress::read(&mut r.take(len))?);
710 }
711 TransportParameterId::InitialSourceConnectionId => {
712 decode_cid(len, &mut params.initial_src_cid, r)?
713 }
714 TransportParameterId::RetrySourceConnectionId => {
715 decode_cid(len, &mut params.retry_src_cid, r)?
716 }
717 TransportParameterId::MaxDatagramFrameSize => {
718 if len > 8 || params.max_datagram_frame_size.is_some() {
719 return Err(Error::Malformed);
720 }
721 params.max_datagram_frame_size = Some(r.get().map_err(|_| Error::Malformed)?);
722 }
723 TransportParameterId::GreaseQuicBit => match len {
724 0 => params.grease_quic_bit = true,
725 _ => return Err(Error::Malformed),
726 },
727 TransportParameterId::MinAckDelayDraft07 => {
728 params.min_ack_delay = Some(r.get().map_err(|_| Error::Malformed)?)
729 }
730 TransportParameterId::NatTraversal => {
731 if params.nat_traversal.is_some() {
732 return Err(Error::Malformed);
733 }
734 match len {
739 0 => {
740 params.nat_traversal = Some(NatTraversalConfig::ClientSupport);
744 }
745 _ if len > 0 => {
746 let limit = r.get_var()?;
750 if limit == 0 {
751 return Err(Error::IllegalValue);
752 }
753 params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
754 concurrency_limit: VarInt::from_u64(limit)
755 .map_err(|_| Error::IllegalValue)?,
756 });
757 }
758 _ => {
759 return Err(Error::IllegalValue);
761 }
762 }
763 }
764 TransportParameterId::AddressDiscovery => {
765 if params.address_discovery.is_some() {
766 return Err(Error::Malformed);
767 }
768 let value = r.get_var()?;
769 let varint = VarInt::from_u64(value).map_err(|_| Error::Malformed)?;
770 params.address_discovery = Some(AddressDiscoveryConfig::from_value(varint)?);
771 }
772 TransportParameterId::RfcNatTraversal => {
773 if params.rfc_nat_traversal {
774 return Err(Error::Malformed);
775 }
776 if len != 0 {
777 return Err(Error::Malformed);
779 }
780 params.rfc_nat_traversal = true;
781 }
782 TransportParameterId::PqcAlgorithms => {
783 if params.pqc_algorithms.is_some() {
784 return Err(Error::Malformed);
785 }
786 if len != 1 {
787 return Err(Error::Malformed);
788 }
789 let value = r.get::<u8>()?;
790 params.pqc_algorithms = Some(PqcAlgorithms {
792 ml_kem_768: (value & (1 << 0)) != 0,
793 ml_dsa_65: (value & (1 << 1)) != 0,
794 });
795 }
796 _ => {
797 macro_rules! parse {
798 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr_2021,)*} => {
799 match id {
800 $(TransportParameterId::$id => {
801 let value = r.get::<VarInt>()?;
802 if len != value.size() || got.$name { return Err(Error::Malformed); }
803 params.$name = value.into();
804 got.$name = true;
805 })*
806 _ => r.advance(len),
807 }
808 }
809 }
810 apply_params!(parse);
811 }
812 }
813 }
814
815 validate_ack_delay_exponent(params.ack_delay_exponent.0 as u8)
819 .map_err(|_| Error::IllegalValue)?;
820
821 validate_max_ack_delay(params.max_ack_delay).map_err(|_| Error::IllegalValue)?;
822
823 validate_active_connection_id_limit(params.active_connection_id_limit)
824 .map_err(|_| Error::IllegalValue)?;
825
826 validate_max_udp_payload_size(params.max_udp_payload_size)
827 .map_err(|_| Error::IllegalValue)?;
828
829 if params.initial_max_streams_bidi.0 > MAX_STREAM_COUNT {
831 TransportParameterErrorHandler::log_validation_failure(
832 "initial_max_streams_bidi",
833 params.initial_max_streams_bidi.0,
834 &format!("must be <= {MAX_STREAM_COUNT}"),
835 "RFC 9000 Section 4.6-2",
836 );
837 return Err(Error::IllegalValue);
838 }
839 if params.initial_max_streams_uni.0 > MAX_STREAM_COUNT {
840 TransportParameterErrorHandler::log_validation_failure(
841 "initial_max_streams_uni",
842 params.initial_max_streams_uni.0,
843 &format!("must be <= {MAX_STREAM_COUNT}"),
844 "RFC 9000 Section 4.6-2",
845 );
846 return Err(Error::IllegalValue);
847 }
848
849 validate_min_ack_delay(params.min_ack_delay, params.max_ack_delay)
851 .map_err(|_| Error::IllegalValue)?;
852
853 validate_server_only_params(side, ¶ms).map_err(|_| Error::IllegalValue)?;
855
856 if let Some(ref pref_addr) = params.preferred_address {
858 if pref_addr.connection_id.is_empty() {
859 TransportParameterErrorHandler::log_semantic_error(
860 "preferred_address with empty connection_id",
861 "RFC 9000 Section 18.2-4.38.1",
862 );
863 return Err(Error::IllegalValue);
864 }
865 }
866
867 if let Some(ref nat_config) = params.nat_traversal {
869 match (side, nat_config) {
871 (Side::Server, NatTraversalConfig::ClientSupport) => {
873 tracing::debug!("Server received valid ClientSupport NAT traversal parameter");
874 }
875 (Side::Client, NatTraversalConfig::ServerSupport { concurrency_limit }) => {
877 tracing::debug!(
878 "Client received valid ServerSupport with concurrency_limit: {}",
879 concurrency_limit
880 );
881 }
882 (Side::Server, NatTraversalConfig::ServerSupport { concurrency_limit }) => {
884 tracing::debug!(
885 "P2P: Server received ServerSupport with concurrency_limit: {} (symmetric P2P)",
886 concurrency_limit
887 );
888 if concurrency_limit.0 == 0 || concurrency_limit.0 > 100 {
890 TransportParameterErrorHandler::log_validation_failure(
891 "nat_traversal_concurrency_limit",
892 concurrency_limit.0,
893 "1-100",
894 "draft-seemann-quic-nat-traversal-02",
895 );
896 return Err(Error::IllegalValue);
897 }
898 }
899 (Side::Client, NatTraversalConfig::ClientSupport) => {
901 tracing::debug!("P2P: Client received ClientSupport (symmetric P2P)");
902 }
904 }
905 }
906
907 Ok(params)
908 }
909
910 pub fn negotiated_nat_concurrency_limit(
935 &self,
936 local_config: &NatTraversalConfig,
937 ) -> Option<u64> {
938 match (&self.nat_traversal, local_config) {
939 (
941 Some(NatTraversalConfig::ServerSupport {
942 concurrency_limit: remote,
943 }),
944 NatTraversalConfig::ServerSupport {
945 concurrency_limit: local,
946 },
947 ) => Some(local.0.min(remote.0)),
948
949 (
951 Some(NatTraversalConfig::ServerSupport { concurrency_limit }),
952 NatTraversalConfig::ClientSupport,
953 )
954 | (
955 Some(NatTraversalConfig::ClientSupport),
956 NatTraversalConfig::ServerSupport { concurrency_limit },
957 ) => Some(concurrency_limit.0),
958
959 _ => None,
961 }
962 }
963
964 pub fn supports_bidirectional_nat_traversal(&self) -> bool {
988 matches!(
989 &self.nat_traversal,
990 Some(NatTraversalConfig::ServerSupport { .. })
991 )
992 }
993}
994
995#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1004pub(crate) struct ReservedTransportParameter {
1005 id: VarInt,
1007
1008 payload: [u8; Self::MAX_PAYLOAD_LEN],
1010
1011 payload_len: usize,
1013}
1014
1015impl ReservedTransportParameter {
1016 fn random(rng: &mut impl RngCore) -> Result<Self, TransportError> {
1022 let id = Self::generate_reserved_id(rng)?;
1023
1024 let payload_len = rng.gen_range(0..Self::MAX_PAYLOAD_LEN);
1025
1026 let payload = {
1027 let mut slice = [0u8; Self::MAX_PAYLOAD_LEN];
1028 rng.fill_bytes(&mut slice[..payload_len]);
1029 slice
1030 };
1031
1032 Ok(Self {
1033 id,
1034 payload,
1035 payload_len,
1036 })
1037 }
1038
1039 fn write(&self, w: &mut impl BufMut) {
1040 w.write_var(self.id.0);
1041 w.write_var(self.payload_len as u64);
1042 w.put_slice(&self.payload[..self.payload_len]);
1043 }
1044
1045 fn generate_reserved_id(rng: &mut impl RngCore) -> Result<VarInt, TransportError> {
1050 let id = {
1051 let rand = rng.gen_range(0u64..(1 << 62) - 27);
1052 let n = rand / 31;
1053 31 * n + 27
1054 };
1055 debug_assert!(
1056 id % 31 == 27,
1057 "generated id does not have the form of 31 * N + 27"
1058 );
1059 VarInt::from_u64(id).map_err(|_| TransportError {
1060 code: TransportErrorCode::INTERNAL_ERROR,
1061 frame: None,
1062 reason: "generated id does not fit into range of allowed transport parameter IDs"
1063 .to_string(),
1064 })
1065 }
1066
1067 const MAX_PAYLOAD_LEN: usize = 16;
1071}
1072
1073#[repr(u64)]
1074#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1075pub(crate) enum TransportParameterId {
1076 OriginalDestinationConnectionId = 0x00,
1078 MaxIdleTimeout = 0x01,
1079 StatelessResetToken = 0x02,
1080 MaxUdpPayloadSize = 0x03,
1081 InitialMaxData = 0x04,
1082 InitialMaxStreamDataBidiLocal = 0x05,
1083 InitialMaxStreamDataBidiRemote = 0x06,
1084 InitialMaxStreamDataUni = 0x07,
1085 InitialMaxStreamsBidi = 0x08,
1086 InitialMaxStreamsUni = 0x09,
1087 AckDelayExponent = 0x0A,
1088 MaxAckDelay = 0x0B,
1089 DisableActiveMigration = 0x0C,
1090 PreferredAddress = 0x0D,
1091 ActiveConnectionIdLimit = 0x0E,
1092 InitialSourceConnectionId = 0x0F,
1093 RetrySourceConnectionId = 0x10,
1094
1095 ReservedTransportParameter = 0x1B,
1097
1098 MaxDatagramFrameSize = 0x20,
1100
1101 GreaseQuicBit = 0x2AB2,
1103
1104 MinAckDelayDraft07 = 0xFF04DE1B,
1106
1107 NatTraversal = 0x3d7e9f0bca12fea6,
1110
1111 RfcNatTraversal = 0x3d7e9f0bca12fea8,
1114
1115 AddressDiscovery = 0x9f81a176,
1118 PqcAlgorithms = 0x50C0,
1121}
1122
1123impl TransportParameterId {
1124 const SUPPORTED: [Self; 25] = [
1126 Self::MaxIdleTimeout,
1127 Self::MaxUdpPayloadSize,
1128 Self::InitialMaxData,
1129 Self::InitialMaxStreamDataBidiLocal,
1130 Self::InitialMaxStreamDataBidiRemote,
1131 Self::InitialMaxStreamDataUni,
1132 Self::InitialMaxStreamsBidi,
1133 Self::InitialMaxStreamsUni,
1134 Self::AckDelayExponent,
1135 Self::MaxAckDelay,
1136 Self::ActiveConnectionIdLimit,
1137 Self::ReservedTransportParameter,
1138 Self::StatelessResetToken,
1139 Self::DisableActiveMigration,
1140 Self::MaxDatagramFrameSize,
1141 Self::PreferredAddress,
1142 Self::OriginalDestinationConnectionId,
1143 Self::InitialSourceConnectionId,
1144 Self::RetrySourceConnectionId,
1145 Self::GreaseQuicBit,
1146 Self::MinAckDelayDraft07,
1147 Self::NatTraversal,
1148 Self::RfcNatTraversal,
1149 Self::AddressDiscovery,
1150 Self::PqcAlgorithms,
1151 ];
1152}
1153
1154impl std::cmp::PartialEq<u64> for TransportParameterId {
1155 fn eq(&self, other: &u64) -> bool {
1156 *other == (*self as u64)
1157 }
1158}
1159
1160impl TryFrom<u64> for TransportParameterId {
1161 type Error = ();
1162
1163 fn try_from(value: u64) -> Result<Self, Self::Error> {
1164 let param = match value {
1165 id if Self::MaxIdleTimeout == id => Self::MaxIdleTimeout,
1166 id if Self::MaxUdpPayloadSize == id => Self::MaxUdpPayloadSize,
1167 id if Self::InitialMaxData == id => Self::InitialMaxData,
1168 id if Self::InitialMaxStreamDataBidiLocal == id => Self::InitialMaxStreamDataBidiLocal,
1169 id if Self::InitialMaxStreamDataBidiRemote == id => {
1170 Self::InitialMaxStreamDataBidiRemote
1171 }
1172 id if Self::InitialMaxStreamDataUni == id => Self::InitialMaxStreamDataUni,
1173 id if Self::InitialMaxStreamsBidi == id => Self::InitialMaxStreamsBidi,
1174 id if Self::InitialMaxStreamsUni == id => Self::InitialMaxStreamsUni,
1175 id if Self::AckDelayExponent == id => Self::AckDelayExponent,
1176 id if Self::MaxAckDelay == id => Self::MaxAckDelay,
1177 id if Self::ActiveConnectionIdLimit == id => Self::ActiveConnectionIdLimit,
1178 id if Self::ReservedTransportParameter == id => Self::ReservedTransportParameter,
1179 id if Self::StatelessResetToken == id => Self::StatelessResetToken,
1180 id if Self::DisableActiveMigration == id => Self::DisableActiveMigration,
1181 id if Self::MaxDatagramFrameSize == id => Self::MaxDatagramFrameSize,
1182 id if Self::PreferredAddress == id => Self::PreferredAddress,
1183 id if Self::OriginalDestinationConnectionId == id => {
1184 Self::OriginalDestinationConnectionId
1185 }
1186 id if Self::InitialSourceConnectionId == id => Self::InitialSourceConnectionId,
1187 id if Self::RetrySourceConnectionId == id => Self::RetrySourceConnectionId,
1188 id if Self::GreaseQuicBit == id => Self::GreaseQuicBit,
1189 id if Self::MinAckDelayDraft07 == id => Self::MinAckDelayDraft07,
1190 id if Self::NatTraversal == id => Self::NatTraversal,
1191 id if Self::RfcNatTraversal == id => Self::RfcNatTraversal,
1192 id if Self::AddressDiscovery == id => Self::AddressDiscovery,
1193 id if Self::PqcAlgorithms == id => Self::PqcAlgorithms,
1194 _ => return Err(()),
1195 };
1196 Ok(param)
1197 }
1198}
1199
1200fn decode_cid(len: usize, value: &mut Option<ConnectionId>, r: &mut impl Buf) -> Result<(), Error> {
1201 if len > MAX_CID_SIZE || value.is_some() || r.remaining() < len {
1202 return Err(Error::Malformed);
1203 }
1204
1205 *value = Some(ConnectionId::from_buf(r, len));
1206 Ok(())
1207}
1208
1209#[cfg(test)]
1210mod test {
1211 use super::*;
1212
1213 #[test]
1214 fn test_nat_traversal_transport_parameter_encoding_decoding() {
1215 let client_config = NatTraversalConfig::ClientSupport;
1219
1220 let mut client_params = TransportParameters::default();
1221 client_params.nat_traversal = Some(client_config);
1222
1223 let mut encoded = Vec::new();
1224 client_params.write(&mut encoded);
1225
1226 let server_decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1228 .expect("Failed to decode client transport parameters");
1229
1230 assert!(server_decoded.nat_traversal.is_some());
1232 let server_view = server_decoded.nat_traversal.unwrap();
1233 assert!(matches!(server_view, NatTraversalConfig::ClientSupport));
1234
1235 let server_config = NatTraversalConfig::ServerSupport {
1237 concurrency_limit: VarInt::from_u32(5),
1238 };
1239
1240 let mut server_params = TransportParameters::default();
1241 server_params.nat_traversal = Some(server_config);
1242
1243 let mut encoded = Vec::new();
1244 server_params.write(&mut encoded);
1245
1246 let client_decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1248 .expect("Failed to decode server transport parameters");
1249
1250 assert!(client_decoded.nat_traversal.is_some());
1252 let client_view = client_decoded.nat_traversal.unwrap();
1253 assert!(matches!(
1254 client_view,
1255 NatTraversalConfig::ServerSupport { .. }
1256 ));
1257 assert_eq!(client_view.concurrency_limit(), Some(VarInt::from_u32(5)));
1258 }
1259
1260 #[test]
1261 fn test_nat_traversal_parameter_without_peer_id() {
1262 let config = NatTraversalConfig::ClientSupport;
1264
1265 let mut params = TransportParameters::default();
1266 params.nat_traversal = Some(config);
1267
1268 let mut encoded = Vec::new();
1269 params.write(&mut encoded);
1270
1271 let decoded_params = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1273 .expect("Failed to decode transport parameters");
1274
1275 let decoded_config = decoded_params
1276 .nat_traversal
1277 .expect("NAT traversal config should be present");
1278
1279 assert!(matches!(decoded_config, NatTraversalConfig::ClientSupport));
1280
1281 let server_config = NatTraversalConfig::ServerSupport {
1283 concurrency_limit: VarInt::from_u32(4),
1284 };
1285
1286 let mut server_params = TransportParameters::default();
1287 server_params.nat_traversal = Some(server_config);
1288
1289 let mut server_encoded = Vec::new();
1290 server_params.write(&mut server_encoded);
1291
1292 let decoded_server_params =
1294 TransportParameters::read(Side::Client, &mut server_encoded.as_slice())
1295 .expect("Failed to decode server transport parameters");
1296
1297 let decoded_server_config = decoded_server_params
1298 .nat_traversal
1299 .expect("Server NAT traversal config should be present");
1300
1301 assert!(matches!(
1302 decoded_server_config,
1303 NatTraversalConfig::ServerSupport { concurrency_limit } if concurrency_limit == VarInt::from_u32(4)
1304 ));
1305 }
1306
1307 #[test]
1308 fn test_transport_parameters_without_nat_traversal() {
1309 let mut params = TransportParameters::default();
1311 params.nat_traversal = None;
1312
1313 let mut encoded = Vec::new();
1314 params.write(&mut encoded);
1315
1316 let decoded_params = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1317 .expect("Failed to decode transport parameters");
1318
1319 assert!(decoded_params.nat_traversal.is_none());
1320 }
1321
1322 #[test]
1323 fn test_nat_traversal_draft_compliant_encoding() {
1324 let client_config = NatTraversalConfig::ClientSupport;
1328
1329 let mut client_params = TransportParameters::default();
1330 client_params.nat_traversal = Some(client_config);
1331
1332 let mut encoded = Vec::new();
1333 client_params.write(&mut encoded);
1334
1335 use bytes::Buf;
1338 let mut cursor = &encoded[..];
1339 while cursor.has_remaining() {
1340 let id = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1341 let len = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1342 if id.0 == 0x3d7e9f0bca12fea6 {
1343 assert_eq!(len.0, 0, "Client should send empty value");
1345 break;
1346 }
1347 cursor.advance(len.0 as usize);
1349 }
1350
1351 let server_config = NatTraversalConfig::ServerSupport {
1353 concurrency_limit: VarInt::from_u32(5),
1354 };
1355
1356 let mut server_params = TransportParameters::default();
1357 server_params.nat_traversal = Some(server_config);
1358
1359 let mut encoded = Vec::new();
1360 server_params.write(&mut encoded);
1361
1362 let mut cursor = &encoded[..];
1364 while cursor.has_remaining() {
1365 let id = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1366 let len = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1367 if id.0 == 0x3d7e9f0bca12fea6 {
1368 assert_eq!(len.0, 1, "Server should send 1-byte value");
1370 let limit = cursor.chunk()[0];
1371 assert_eq!(limit, 5, "Server should send concurrency limit");
1372 break;
1373 }
1374 cursor.advance(len.0 as usize);
1376 }
1377 }
1378
1379 #[test]
1380 fn test_nat_traversal_draft_compliant_decoding() {
1381 let mut buf = Vec::new();
1383 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(0); let params = TransportParameters::read(Side::Server, &mut buf.as_slice())
1387 .expect("Failed to decode transport parameters");
1388
1389 let config = params
1390 .nat_traversal
1391 .expect("NAT traversal should be present");
1392 assert!(matches!(config, NatTraversalConfig::ClientSupport));
1393
1394 let mut buf = Vec::new();
1396 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(1); buf.put_u8(7); let params = TransportParameters::read(Side::Client, &mut buf.as_slice())
1401 .expect("Failed to decode transport parameters");
1402
1403 let config = params
1404 .nat_traversal
1405 .expect("NAT traversal should be present");
1406 assert!(matches!(
1407 config,
1408 NatTraversalConfig::ServerSupport { concurrency_limit } if concurrency_limit == VarInt::from_u32(7)
1409 ));
1410
1411 let mut buf = Vec::new();
1413 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(2); buf.put_u8(7);
1416 buf.put_u8(8);
1417
1418 let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1419 assert!(result.is_err(), "Should fail with invalid length");
1420 }
1421
1422 #[test]
1423 fn test_nat_traversal_parameter_id() {
1424 assert_eq!(
1426 TransportParameterId::NatTraversal as u64,
1427 0x3d7e9f0bca12fea6
1428 );
1429 }
1430
1431 #[test]
1432 fn test_nat_traversal_simple_encoding() {
1433 let mut client_params = TransportParameters::default();
1437 client_params.nat_traversal = Some(NatTraversalConfig::ClientSupport);
1438
1439 let mut encoded = Vec::new();
1440 client_params.write(&mut encoded);
1441
1442 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1444 .expect("Should decode client params");
1445 assert!(matches!(
1446 decoded.nat_traversal,
1447 Some(NatTraversalConfig::ClientSupport)
1448 ));
1449
1450 let mut server_params = TransportParameters::default();
1452 server_params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1453 concurrency_limit: VarInt::from_u32(10),
1454 });
1455
1456 let mut encoded = Vec::new();
1457 server_params.write(&mut encoded);
1458
1459 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1461 .expect("Should decode server params");
1462
1463 match decoded.nat_traversal {
1464 Some(NatTraversalConfig::ServerSupport { concurrency_limit }) => {
1465 assert_eq!(concurrency_limit, VarInt::from_u32(10));
1466 }
1467 _ => panic!("Expected ServerSupport variant"),
1468 }
1469 }
1470
1471 #[test]
1472 fn test_nat_traversal_config_validation() {
1473 let client_config = NatTraversalConfig::ClientSupport;
1475 assert!(client_config.is_client());
1476 assert_eq!(client_config.concurrency_limit(), None);
1477
1478 let server_config = NatTraversalConfig::server(VarInt::from_u32(5)).unwrap();
1480 assert!(server_config.is_server());
1481 assert_eq!(server_config.concurrency_limit(), Some(VarInt::from_u32(5)));
1482
1483 let result = NatTraversalConfig::server(VarInt::from_u32(0));
1485 assert!(result.is_err());
1486
1487 let result = NatTraversalConfig::server(VarInt::from_u32(101));
1489 assert!(result.is_err());
1490
1491 let min_server = NatTraversalConfig::server(VarInt::from_u32(1)).unwrap();
1493 assert_eq!(min_server.concurrency_limit(), Some(VarInt::from_u32(1)));
1494
1495 let max_server = NatTraversalConfig::server(VarInt::from_u32(100)).unwrap();
1496 assert_eq!(max_server.concurrency_limit(), Some(VarInt::from_u32(100)));
1497 }
1498
1499 #[test]
1500 fn test_nat_traversal_role_validation() {
1501 let mut buf = Vec::new();
1503 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(0); let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1508 assert!(
1509 result.is_ok(),
1510 "P2P: Client should accept ClientSupport from peer for symmetric P2P"
1511 );
1512
1513 let result = TransportParameters::read(Side::Server, &mut buf.as_slice());
1515 assert!(
1516 result.is_ok(),
1517 "Server should accept ClientSupport from client"
1518 );
1519
1520 let mut buf = Vec::new();
1522 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(1); buf.put_u8(5); let result = TransportParameters::read(Side::Server, &mut buf.as_slice());
1528 assert!(
1529 result.is_ok(),
1530 "P2P: Server should accept ServerSupport from peer for symmetric P2P"
1531 );
1532
1533 let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1535 assert!(
1536 result.is_ok(),
1537 "Client should accept ServerSupport from server"
1538 );
1539 }
1540
1541 #[test]
1542 fn test_nat_traversal_parameter_combinations() {
1543 let nat_config = NatTraversalConfig::ClientSupport;
1545
1546 let mut params = TransportParameters::default();
1547 params.nat_traversal = Some(nat_config);
1548 params.max_idle_timeout = VarInt::from_u32(30000);
1549 params.initial_max_data = VarInt::from_u32(1048576);
1550 params.grease_quic_bit = true;
1551
1552 let mut encoded = Vec::new();
1554 params.write(&mut encoded);
1555 assert!(!encoded.is_empty());
1556
1557 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1559 .expect("Should decode successfully");
1560
1561 let decoded_config = decoded
1563 .nat_traversal
1564 .expect("NAT traversal should be present");
1565 assert!(matches!(decoded_config, NatTraversalConfig::ClientSupport));
1566
1567 assert_eq!(decoded.max_idle_timeout, VarInt::from_u32(30000));
1569 assert_eq!(decoded.initial_max_data, VarInt::from_u32(1048576));
1570 assert!(decoded.grease_quic_bit);
1571 }
1572
1573 #[test]
1574 fn test_nat_traversal_default_config() {
1575 let default_config = NatTraversalConfig::default();
1576
1577 assert!(matches!(default_config, NatTraversalConfig::ClientSupport));
1578 assert!(default_config.is_client());
1579 assert_eq!(default_config.concurrency_limit(), None);
1580 }
1581
1582 #[test]
1583 fn test_nat_traversal_endpoint_role_negotiation() {
1584 let client_config = NatTraversalConfig::ClientSupport;
1588
1589 let mut client_params = TransportParameters::default();
1590 client_params.nat_traversal = Some(client_config);
1591
1592 let mut client_encoded = Vec::new();
1594 client_params.write(&mut client_encoded);
1595
1596 let server_received =
1598 TransportParameters::read(Side::Server, &mut client_encoded.as_slice())
1599 .expect("Server should decode client params");
1600
1601 let server_view = server_received
1603 .nat_traversal
1604 .expect("NAT traversal should be present");
1605 assert!(matches!(server_view, NatTraversalConfig::ClientSupport));
1606
1607 let server_config = NatTraversalConfig::ServerSupport {
1609 concurrency_limit: VarInt::from_u32(8),
1610 };
1611
1612 let mut server_params = TransportParameters::default();
1613 server_params.nat_traversal = Some(server_config);
1614
1615 let mut server_encoded = Vec::new();
1617 server_params.write(&mut server_encoded);
1618
1619 let client_received =
1621 TransportParameters::read(Side::Client, &mut server_encoded.as_slice())
1622 .expect("Client should decode server params");
1623
1624 let client_view = client_received
1626 .nat_traversal
1627 .expect("NAT traversal should be present");
1628 assert!(matches!(
1629 client_view,
1630 NatTraversalConfig::ServerSupport { concurrency_limit } if concurrency_limit == VarInt::from_u32(8)
1631 ));
1632 }
1633
1634 #[test]
1637 fn test_p2p_nat_traversal_both_server_support() {
1638 let peer1_config = NatTraversalConfig::ServerSupport {
1642 concurrency_limit: VarInt::from_u32(10),
1643 };
1644 let _peer2_config = NatTraversalConfig::ServerSupport {
1645 concurrency_limit: VarInt::from_u32(5),
1646 };
1647
1648 let mut peer1_params = TransportParameters::default();
1650 peer1_params.nat_traversal = Some(peer1_config);
1651
1652 let mut encoded = Vec::new();
1653 peer1_params.write(&mut encoded);
1654
1655 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1658 .expect("P2P: Server should accept ServerSupport from peer");
1659
1660 assert!(matches!(
1662 decoded.nat_traversal,
1663 Some(NatTraversalConfig::ServerSupport { concurrency_limit })
1664 if concurrency_limit == VarInt::from_u32(10)
1665 ));
1666 }
1667
1668 #[test]
1669 fn test_p2p_nat_traversal_concurrency_negotiation() {
1670 let local = NatTraversalConfig::ServerSupport {
1673 concurrency_limit: VarInt::from_u32(10),
1674 };
1675 let mut remote_params = TransportParameters::default();
1676 remote_params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1677 concurrency_limit: VarInt::from_u32(5),
1678 });
1679
1680 let negotiated = remote_params.negotiated_nat_concurrency_limit(&local);
1682 assert_eq!(negotiated, Some(5));
1683
1684 let local2 = NatTraversalConfig::ServerSupport {
1686 concurrency_limit: VarInt::from_u32(3),
1687 };
1688 let mut remote_params2 = TransportParameters::default();
1689 remote_params2.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1690 concurrency_limit: VarInt::from_u32(8),
1691 });
1692
1693 let negotiated2 = remote_params2.negotiated_nat_concurrency_limit(&local2);
1694 assert_eq!(negotiated2, Some(3));
1695 }
1696
1697 #[test]
1698 fn test_p2p_nat_traversal_invalid_concurrency() {
1699 let config = NatTraversalConfig::ServerSupport {
1702 concurrency_limit: VarInt::from_u32(0), };
1704
1705 let mut params = TransportParameters::default();
1706 params.nat_traversal = Some(config);
1707
1708 let mut encoded = Vec::new();
1709 params.write(&mut encoded);
1710
1711 let result = TransportParameters::read(Side::Server, &mut encoded.as_slice());
1713 assert!(
1714 matches!(result, Err(Error::IllegalValue)),
1715 "Should reject concurrency_limit = 0"
1716 );
1717 }
1718
1719 #[test]
1720 fn test_p2p_nat_traversal_max_concurrency() {
1721 let config = NatTraversalConfig::ServerSupport {
1724 concurrency_limit: VarInt::from_u32(101), };
1726
1727 let mut params = TransportParameters::default();
1728 params.nat_traversal = Some(config);
1729
1730 let mut encoded = Vec::new();
1731 params.write(&mut encoded);
1732
1733 let result = TransportParameters::read(Side::Server, &mut encoded.as_slice());
1735 assert!(
1736 matches!(result, Err(Error::IllegalValue)),
1737 "Should reject concurrency_limit > 100"
1738 );
1739 }
1740
1741 #[test]
1742 fn test_p2p_both_client_support() {
1743 let config = NatTraversalConfig::ClientSupport;
1747
1748 let mut params = TransportParameters::default();
1749 params.nat_traversal = Some(config);
1750
1751 let mut encoded = Vec::new();
1752 params.write(&mut encoded);
1753
1754 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1756 .expect("P2P: Client should accept ClientSupport from peer");
1757
1758 assert!(matches!(
1759 decoded.nat_traversal,
1760 Some(NatTraversalConfig::ClientSupport)
1761 ));
1762 }
1763
1764 #[test]
1765 fn test_p2p_helper_methods() {
1766 let mut params_with_server = TransportParameters::default();
1770 params_with_server.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1771 concurrency_limit: VarInt::from_u32(5),
1772 });
1773 assert!(params_with_server.supports_bidirectional_nat_traversal());
1774
1775 let mut params_with_client = TransportParameters::default();
1776 params_with_client.nat_traversal = Some(NatTraversalConfig::ClientSupport);
1777 assert!(!params_with_client.supports_bidirectional_nat_traversal());
1778
1779 let params_without_nat = TransportParameters::default();
1780 assert!(!params_without_nat.supports_bidirectional_nat_traversal());
1781
1782 let local = NatTraversalConfig::ClientSupport;
1784 let mut remote_params = TransportParameters::default();
1785 remote_params.nat_traversal = Some(NatTraversalConfig::ServerSupport {
1786 concurrency_limit: VarInt::from_u32(10),
1787 });
1788
1789 let negotiated = remote_params.negotiated_nat_concurrency_limit(&local);
1791 assert_eq!(negotiated, Some(10));
1792 }
1793
1794 #[test]
1797 fn test_traditional_client_server_unchanged() {
1798 let client_config = NatTraversalConfig::ClientSupport;
1803 let mut client_params = TransportParameters::default();
1804 client_params.nat_traversal = Some(client_config);
1805
1806 let mut encoded = Vec::new();
1807 client_params.write(&mut encoded);
1808
1809 let server_decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1811 .expect("Traditional client/server should still work");
1812
1813 assert!(matches!(
1814 server_decoded.nat_traversal,
1815 Some(NatTraversalConfig::ClientSupport)
1816 ));
1817 }
1818
1819 #[test]
1820 fn test_traditional_server_client_unchanged() {
1821 let server_config = NatTraversalConfig::ServerSupport {
1826 concurrency_limit: VarInt::from_u32(10),
1827 };
1828 let mut server_params = TransportParameters::default();
1829 server_params.nat_traversal = Some(server_config);
1830
1831 let mut encoded = Vec::new();
1832 server_params.write(&mut encoded);
1833
1834 let client_decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1836 .expect("Traditional server/client should still work");
1837
1838 assert!(matches!(
1839 client_decoded.nat_traversal,
1840 Some(NatTraversalConfig::ServerSupport { concurrency_limit })
1841 if concurrency_limit == VarInt::from_u32(10)
1842 ));
1843 }
1844
1845 #[test]
1846 fn coding() {
1847 let mut buf = Vec::new();
1848 let params = TransportParameters {
1849 initial_src_cid: Some(ConnectionId::new(&[])),
1850 original_dst_cid: Some(ConnectionId::new(&[])),
1851 initial_max_streams_bidi: 16u32.into(),
1852 initial_max_streams_uni: 16u32.into(),
1853 ack_delay_exponent: 2u32.into(),
1854 max_udp_payload_size: 1200u32.into(),
1855 preferred_address: Some(PreferredAddress {
1856 address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
1857 address_v6: Some(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 24, 0, 0)),
1858 connection_id: ConnectionId::new(&[0x42]),
1859 stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
1860 }),
1861 grease_quic_bit: true,
1862 min_ack_delay: Some(2_000u32.into()),
1863 ..TransportParameters::default()
1864 };
1865 params.write(&mut buf);
1866 assert_eq!(
1867 TransportParameters::read(Side::Client, &mut buf.as_slice()).unwrap(),
1868 params
1869 );
1870 }
1871
1872 #[test]
1873 fn reserved_transport_parameter_generate_reserved_id() {
1874 use rand::rngs::mock::StepRng;
1875 let mut rngs = [
1876 StepRng::new(0, 1),
1877 StepRng::new(1, 1),
1878 StepRng::new(27, 1),
1879 StepRng::new(31, 1),
1880 StepRng::new(u32::MAX as u64, 1),
1881 StepRng::new(u32::MAX as u64 - 1, 1),
1882 StepRng::new(u32::MAX as u64 + 1, 1),
1883 StepRng::new(u32::MAX as u64 - 27, 1),
1884 StepRng::new(u32::MAX as u64 + 27, 1),
1885 StepRng::new(u32::MAX as u64 - 31, 1),
1886 StepRng::new(u32::MAX as u64 + 31, 1),
1887 StepRng::new(u64::MAX, 1),
1888 StepRng::new(u64::MAX - 1, 1),
1889 StepRng::new(u64::MAX - 27, 1),
1890 StepRng::new(u64::MAX - 31, 1),
1891 StepRng::new(1 << 62, 1),
1892 StepRng::new((1 << 62) - 1, 1),
1893 StepRng::new((1 << 62) + 1, 1),
1894 StepRng::new((1 << 62) - 27, 1),
1895 StepRng::new((1 << 62) + 27, 1),
1896 StepRng::new((1 << 62) - 31, 1),
1897 StepRng::new((1 << 62) + 31, 1),
1898 ];
1899 for rng in &mut rngs {
1900 let id = ReservedTransportParameter::generate_reserved_id(rng).unwrap();
1901 assert!(id.0 % 31 == 27)
1902 }
1903 }
1904
1905 #[test]
1906 fn reserved_transport_parameter_ignored_when_read() {
1907 let mut buf = Vec::new();
1908 let reserved_parameter =
1909 ReservedTransportParameter::random(&mut rand::thread_rng()).unwrap();
1910 assert!(reserved_parameter.payload_len < ReservedTransportParameter::MAX_PAYLOAD_LEN);
1911 assert!(reserved_parameter.id.0 % 31 == 27);
1912
1913 reserved_parameter.write(&mut buf);
1914 assert!(!buf.is_empty());
1915 let read_params = TransportParameters::read(Side::Server, &mut buf.as_slice()).unwrap();
1916 assert_eq!(read_params, TransportParameters::default());
1917 }
1918
1919 #[test]
1920 fn read_semantic_validation() {
1921 #[allow(clippy::type_complexity)]
1922 let illegal_params_builders: Vec<Box<dyn FnMut(&mut TransportParameters)>> = vec![
1923 Box::new(|t| {
1924 let min_ack_delay = t.max_ack_delay.0 * 1_000 + 1;
1926 t.min_ack_delay = Some(VarInt::from_u64(min_ack_delay).unwrap())
1927 }),
1928 Box::new(|t| {
1929 t.preferred_address = Some(PreferredAddress {
1932 address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
1933 address_v6: None,
1934 connection_id: ConnectionId::new(&[]),
1935 stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
1936 })
1937 }),
1938 ];
1939
1940 for mut builder in illegal_params_builders {
1941 let mut buf = Vec::new();
1942 let mut params = TransportParameters::default();
1943 builder(&mut params);
1944 params.write(&mut buf);
1945
1946 assert_eq!(
1947 TransportParameters::read(Side::Server, &mut buf.as_slice()),
1948 Err(Error::IllegalValue)
1949 );
1950 }
1951 }
1952
1953 #[test]
1954 fn resumption_params_validation() {
1955 let high_limit = TransportParameters {
1956 initial_max_streams_uni: 32u32.into(),
1957 ..TransportParameters::default()
1958 };
1959 let low_limit = TransportParameters {
1960 initial_max_streams_uni: 16u32.into(),
1961 ..TransportParameters::default()
1962 };
1963 high_limit.validate_resumption_from(&low_limit).unwrap();
1964 low_limit.validate_resumption_from(&high_limit).unwrap_err();
1965 }
1966
1967 #[test]
1968 fn test_address_discovery_parameter_id() {
1969 assert_eq!(TransportParameterId::AddressDiscovery as u64, 0x9f81a176);
1971 }
1972
1973 #[test]
1974 fn test_address_discovery_config_struct() {
1975 let send_only = AddressDiscoveryConfig::SendOnly;
1977 let receive_only = AddressDiscoveryConfig::ReceiveOnly;
1978 let send_receive = AddressDiscoveryConfig::SendAndReceive;
1979
1980 assert_eq!(send_only.to_value(), VarInt::from_u32(0));
1981 assert_eq!(receive_only.to_value(), VarInt::from_u32(1));
1982 assert_eq!(send_receive.to_value(), VarInt::from_u32(2));
1983 }
1984
1985 #[test]
1986 fn test_address_discovery_config_from_value() {
1987 assert_eq!(
1989 AddressDiscoveryConfig::from_value(VarInt::from_u32(0)).unwrap(),
1990 AddressDiscoveryConfig::SendOnly
1991 );
1992 assert_eq!(
1993 AddressDiscoveryConfig::from_value(VarInt::from_u32(1)).unwrap(),
1994 AddressDiscoveryConfig::ReceiveOnly
1995 );
1996 assert_eq!(
1997 AddressDiscoveryConfig::from_value(VarInt::from_u32(2)).unwrap(),
1998 AddressDiscoveryConfig::SendAndReceive
1999 );
2000 assert!(AddressDiscoveryConfig::from_value(VarInt::from_u32(3)).is_err());
2001 }
2002
2003 #[test]
2004 fn test_transport_parameters_with_address_discovery() {
2005 let mut params = TransportParameters::default();
2007 assert!(params.address_discovery.is_none());
2008
2009 let config = AddressDiscoveryConfig::SendAndReceive;
2010
2011 params.address_discovery = Some(config);
2012 assert!(params.address_discovery.is_some());
2013
2014 let stored_config = params.address_discovery.as_ref().unwrap();
2015 assert_eq!(*stored_config, AddressDiscoveryConfig::SendAndReceive);
2016 }
2017
2018 #[test]
2019 fn test_address_discovery_parameter_encoding() {
2020 let config = AddressDiscoveryConfig::SendAndReceive;
2022
2023 let mut params = TransportParameters::default();
2024 params.address_discovery = Some(config);
2025
2026 let mut encoded = Vec::new();
2027 params.write(&mut encoded);
2028
2029 assert!(!encoded.is_empty());
2031 }
2032
2033 #[test]
2034 fn test_address_discovery_parameter_roundtrip() {
2035 let config = AddressDiscoveryConfig::ReceiveOnly;
2037
2038 let mut params = TransportParameters::default();
2039 params.address_discovery = Some(config);
2040
2041 let mut encoded = Vec::new();
2042 params.write(&mut encoded);
2043
2044 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2046 .expect("Failed to decode transport parameters");
2047
2048 assert!(decoded.address_discovery.is_some());
2049 let decoded_config = decoded.address_discovery.as_ref().unwrap();
2050 assert_eq!(*decoded_config, AddressDiscoveryConfig::ReceiveOnly);
2051 }
2052
2053 #[test]
2054 fn test_address_discovery_disabled_by_default() {
2055 let params = TransportParameters::default();
2057 assert!(params.address_discovery.is_none());
2058 }
2059
2060 #[test]
2061 fn test_address_discovery_all_variants() {
2062 for variant in [
2064 AddressDiscoveryConfig::SendOnly,
2065 AddressDiscoveryConfig::ReceiveOnly,
2066 AddressDiscoveryConfig::SendAndReceive,
2067 ] {
2068 let mut params = TransportParameters::default();
2069 params.address_discovery = Some(variant);
2070
2071 let mut encoded = Vec::new();
2072 params.write(&mut encoded);
2073
2074 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
2075 .expect("Failed to decode");
2076
2077 assert_eq!(decoded.address_discovery, Some(variant));
2078 }
2079 }
2080
2081 #[test]
2082 fn test_address_discovery_none_not_encoded() {
2083 let mut params = TransportParameters::default();
2085 params.address_discovery = None;
2086
2087 let mut encoded = Vec::new();
2088 params.write(&mut encoded);
2089
2090 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2091 .expect("Failed to decode");
2092 assert!(decoded.address_discovery.is_none());
2093 }
2094
2095 #[test]
2096 fn test_address_discovery_serialization_roundtrip() {
2097 let config = AddressDiscoveryConfig::SendOnly;
2098
2099 let mut params = TransportParameters::default();
2100 params.address_discovery = Some(config);
2101 params.initial_max_data = VarInt::from_u32(1_000_000);
2102
2103 let mut encoded = Vec::new();
2104 params.write(&mut encoded);
2105
2106 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2107 .expect("Failed to decode");
2108
2109 assert_eq!(
2110 decoded.address_discovery,
2111 Some(AddressDiscoveryConfig::SendOnly)
2112 );
2113 assert_eq!(decoded.initial_max_data, VarInt::from_u32(1_000_000));
2114 }
2115
2116 #[test]
2117 fn test_address_discovery_invalid_value() {
2118 let mut encoded = Vec::new();
2121 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2122 encoded.write_var(1); encoded.write_var(3); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2126 assert!(result.is_err());
2127 }
2128
2129 #[test]
2130 fn test_address_discovery_edge_cases() {
2131 let mut encoded = Vec::new();
2135 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2136 encoded.write_var(0); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2139 assert!(result.is_err());
2140
2141 let mut encoded = Vec::new();
2143 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2144 encoded.write_var(1); encoded.put_u8(255); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2148 assert!(result.is_err());
2149 }
2150
2151 #[test]
2152 fn test_address_discovery_malformed_length() {
2153 let mut encoded = Vec::new();
2155 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2156 encoded.write_var(1); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2159 assert!(result.is_err());
2160 assert!(matches!(result.unwrap_err(), Error::Malformed));
2161 }
2162
2163 #[test]
2164 fn test_address_discovery_duplicate_parameter() {
2165 let mut encoded = Vec::new();
2167
2168 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2170 encoded.write_var(1);
2171 encoded.put_u8(0x80); encoded.write_var(TransportParameterId::AddressDiscovery as u64);
2175 encoded.write_var(1);
2176 encoded.put_u8(0xC0); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2179 assert!(result.is_err());
2180 assert!(matches!(result.unwrap_err(), Error::Malformed));
2181 }
2182
2183 #[test]
2184 fn test_address_discovery_with_other_parameters() {
2185 let mut params = TransportParameters::default();
2187 params.max_idle_timeout = VarInt::from_u32(30000);
2188 params.initial_max_data = VarInt::from_u32(1_000_000);
2189 params.address_discovery = Some(AddressDiscoveryConfig::SendAndReceive);
2190
2191 let mut encoded = Vec::new();
2192 params.write(&mut encoded);
2193
2194 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2195 .expect("Failed to decode");
2196
2197 assert_eq!(decoded.max_idle_timeout, params.max_idle_timeout);
2199 assert_eq!(decoded.initial_max_data, params.initial_max_data);
2200 assert_eq!(
2201 decoded.address_discovery,
2202 Some(AddressDiscoveryConfig::SendAndReceive)
2203 );
2204 }
2205
2206 #[test]
2207 fn test_pqc_algorithms_transport_parameter() {
2208 let mut params = TransportParameters::default();
2210 params.pqc_algorithms = Some(PqcAlgorithms {
2211 ml_kem_768: true,
2212 ml_dsa_65: true,
2213 });
2214
2215 let mut encoded = Vec::new();
2217 params.write(&mut encoded);
2218
2219 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2221 .expect("Failed to decode");
2222
2223 assert!(decoded.pqc_algorithms.is_some());
2225 let pqc = decoded.pqc_algorithms.unwrap();
2226 assert!(pqc.ml_kem_768);
2227 assert!(pqc.ml_dsa_65);
2228 }
2229
2230 #[test]
2231 fn test_pqc_algorithms_all_combinations() {
2232 for ml_kem in [false, true] {
2234 for ml_dsa in [false, true] {
2235 let mut params = TransportParameters::default();
2236 params.pqc_algorithms = Some(PqcAlgorithms {
2237 ml_kem_768: ml_kem,
2238 ml_dsa_65: ml_dsa,
2239 });
2240
2241 let mut encoded = Vec::new();
2243 params.write(&mut encoded);
2244 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2245 .expect("Failed to decode");
2246
2247 let pqc = decoded.pqc_algorithms.unwrap();
2249 assert_eq!(pqc.ml_kem_768, ml_kem);
2250 assert_eq!(pqc.ml_dsa_65, ml_dsa);
2251 }
2252 }
2253 }
2254
2255 #[test]
2256 fn test_pqc_algorithms_not_sent_when_none() {
2257 let mut params = TransportParameters::default();
2259 params.pqc_algorithms = None;
2260
2261 let mut encoded = Vec::new();
2262 params.write(&mut encoded);
2263
2264 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
2267 .expect("Failed to decode");
2268 assert!(decoded.pqc_algorithms.is_none());
2269 }
2270
2271 #[test]
2272 fn test_pqc_algorithms_duplicate_parameter() {
2273 let mut encoded = Vec::new();
2275
2276 encoded.write_var(TransportParameterId::PqcAlgorithms as u64);
2278 encoded.write_var(1u64); encoded.write(0b1111u8); encoded.write_var(TransportParameterId::PqcAlgorithms as u64);
2283 encoded.write_var(1u64);
2284 encoded.write(0b0000u8);
2285
2286 let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
2288 assert!(result.is_err());
2289 assert!(matches!(result.unwrap_err(), Error::Malformed));
2290 }
2291
2292 mod comprehensive_tests {
2294 include!("transport_parameters/tests.rs");
2295 }
2296}