1use std::{
10 convert::TryFrom,
11 net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6},
12};
13
14use bytes::{Buf, BufMut};
15use rand::{Rng as _, RngCore, seq::SliceRandom as _};
16use thiserror::Error;
17
18use crate::{
19 LOC_CID_COUNT, MAX_CID_SIZE, MAX_STREAM_COUNT, RESET_TOKEN_SIZE, ResetToken, Side,
20 TIMER_GRANULARITY, TransportError, VarInt,
21 cid_generator::ConnectionIdGenerator,
22 cid_queue::CidQueue,
23 coding::{BufExt, BufMutExt, UnexpectedEnd},
24 config::{EndpointConfig, ServerConfig, TransportConfig},
25 shared::ConnectionId,
26};
27
28macro_rules! apply_params {
34 ($macro:ident) => {
35 $macro! {
36 max_idle_timeout(MaxIdleTimeout) = 0,
39 max_udp_payload_size(MaxUdpPayloadSize) = 65527,
41
42 initial_max_data(InitialMaxData) = 0,
44 initial_max_stream_data_bidi_local(InitialMaxStreamDataBidiLocal) = 0,
46 initial_max_stream_data_bidi_remote(InitialMaxStreamDataBidiRemote) = 0,
48 initial_max_stream_data_uni(InitialMaxStreamDataUni) = 0,
50
51 initial_max_streams_bidi(InitialMaxStreamsBidi) = 0,
53 initial_max_streams_uni(InitialMaxStreamsUni) = 0,
55
56 ack_delay_exponent(AckDelayExponent) = 3,
58 max_ack_delay(MaxAckDelay) = 25,
61 active_connection_id_limit(ActiveConnectionIdLimit) = 2,
63 }
64 };
65}
66
67macro_rules! make_struct {
68 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => {
69 #[derive(Debug, Clone, Eq, PartialEq)]
71 pub struct TransportParameters {
72 $($(#[$doc])* pub(crate) $name : VarInt,)*
73
74 pub(crate) disable_active_migration: bool,
76 pub(crate) max_datagram_frame_size: Option<VarInt>,
78 pub(crate) initial_src_cid: Option<ConnectionId>,
81 pub(crate) grease_quic_bit: bool,
84
85 pub(crate) min_ack_delay: Option<VarInt>,
91
92 pub(crate) nat_traversal: Option<NatTraversalConfig>,
98
99 pub(crate) address_discovery: Option<AddressDiscoveryConfig>,
103
104 pub(crate) original_dst_cid: Option<ConnectionId>,
108 pub(crate) retry_src_cid: Option<ConnectionId>,
111 pub(crate) stateless_reset_token: Option<ResetToken>,
113 pub(crate) preferred_address: Option<PreferredAddress>,
115 pub(crate) grease_transport_parameter: Option<ReservedTransportParameter>,
119
120 pub(crate) write_order: Option<[u8; TransportParameterId::SUPPORTED.len()]>,
125 }
126
127 impl TransportParameters {
131 pub(crate) fn default() -> Self {
133 Self {
134 $($name: VarInt::from_u32($default),)*
135
136 disable_active_migration: false,
137 max_datagram_frame_size: None,
138 initial_src_cid: None,
139 grease_quic_bit: false,
140 min_ack_delay: None,
141 nat_traversal: None,
142 address_discovery: None,
143
144 original_dst_cid: None,
145 retry_src_cid: None,
146 stateless_reset_token: None,
147 preferred_address: None,
148 grease_transport_parameter: None,
149 write_order: None,
150 }
151 }
152 }
153 }
154}
155
156apply_params!(make_struct);
157
158impl TransportParameters {
159 pub(crate) fn new(
160 config: &TransportConfig,
161 endpoint_config: &EndpointConfig,
162 cid_gen: &dyn ConnectionIdGenerator,
163 initial_src_cid: ConnectionId,
164 server_config: Option<&ServerConfig>,
165 rng: &mut impl RngCore,
166 ) -> Self {
167 Self {
168 initial_src_cid: Some(initial_src_cid),
169 initial_max_streams_bidi: config.max_concurrent_bidi_streams,
170 initial_max_streams_uni: config.max_concurrent_uni_streams,
171 initial_max_data: config.receive_window,
172 initial_max_stream_data_bidi_local: config.stream_receive_window,
173 initial_max_stream_data_bidi_remote: config.stream_receive_window,
174 initial_max_stream_data_uni: config.stream_receive_window,
175 max_udp_payload_size: endpoint_config.max_udp_payload_size,
176 max_idle_timeout: config.max_idle_timeout.unwrap_or(VarInt(0)),
177 disable_active_migration: server_config.is_some_and(|c| !c.migration),
178 active_connection_id_limit: if cid_gen.cid_len() == 0 {
179 2 } else {
181 CidQueue::LEN as u32
182 }
183 .into(),
184 max_datagram_frame_size: config
185 .datagram_receive_buffer_size
186 .map(|x| (x.min(u16::MAX.into()) as u16).into()),
187 grease_quic_bit: endpoint_config.grease_quic_bit,
188 min_ack_delay: Some(
189 VarInt::from_u64(u64::try_from(TIMER_GRANULARITY.as_micros()).unwrap()).unwrap(),
190 ),
191 grease_transport_parameter: Some(ReservedTransportParameter::random(rng)),
192 write_order: Some({
193 let mut order = std::array::from_fn(|i| i as u8);
194 order.shuffle(rng);
195 order
196 }),
197 nat_traversal: config.nat_traversal_config.clone(),
198 address_discovery: None, ..Self::default()
200 }
201 }
202
203 pub(crate) fn validate_resumption_from(&self, cached: &Self) -> Result<(), TransportError> {
206 if cached.active_connection_id_limit > self.active_connection_id_limit
207 || cached.initial_max_data > self.initial_max_data
208 || cached.initial_max_stream_data_bidi_local > self.initial_max_stream_data_bidi_local
209 || cached.initial_max_stream_data_bidi_remote > self.initial_max_stream_data_bidi_remote
210 || cached.initial_max_stream_data_uni > self.initial_max_stream_data_uni
211 || cached.initial_max_streams_bidi > self.initial_max_streams_bidi
212 || cached.initial_max_streams_uni > self.initial_max_streams_uni
213 || cached.max_datagram_frame_size > self.max_datagram_frame_size
214 || cached.grease_quic_bit && !self.grease_quic_bit
215 {
216 return Err(TransportError::PROTOCOL_VIOLATION(
217 "0-RTT accepted with incompatible transport parameters",
218 ));
219 }
220 Ok(())
221 }
222
223 pub(crate) fn issue_cids_limit(&self) -> u64 {
228 self.active_connection_id_limit.0.min(LOC_CID_COUNT)
229 }
230
231 pub fn nat_traversal_config(&self) -> Option<&NatTraversalConfig> {
236 self.nat_traversal.as_ref()
237 }
238}
239
240#[derive(Debug, Clone, Eq, PartialEq)]
245pub struct NatTraversalConfig {
246 pub(crate) role: NatTraversalRole,
248 pub(crate) max_candidates: VarInt,
250 pub(crate) coordination_timeout: VarInt,
252 pub(crate) max_concurrent_attempts: VarInt,
254 pub(crate) peer_id: Option<[u8; 32]>,
256}
257
258impl NatTraversalConfig {
262 pub fn new(
267 role: NatTraversalRole,
268 max_candidates: VarInt,
269 coordination_timeout: VarInt,
270 max_concurrent_attempts: VarInt,
271 peer_id: Option<[u8; 32]>,
272 ) -> Self {
273 Self {
274 role,
275 max_candidates,
276 coordination_timeout,
277 max_concurrent_attempts,
278 peer_id,
279 }
280 }
281
282 pub fn role(&self) -> NatTraversalRole {
284 self.role
285 }
286
287 pub fn max_candidates(&self) -> VarInt {
289 self.max_candidates
290 }
291
292 pub fn coordination_timeout(&self) -> VarInt {
294 self.coordination_timeout
295 }
296
297 pub fn max_concurrent_attempts(&self) -> VarInt {
299 self.max_concurrent_attempts
300 }
301
302 pub fn peer_id(&self) -> Option<[u8; 32]> {
304 self.peer_id
305 }
306
307 pub fn validate(&self) -> Result<(), Error> {
309 if self.max_candidates.0 == 0 || self.max_candidates.0 > 100 {
311 return Err(Error::IllegalValue);
312 }
313
314 if self.coordination_timeout.0 < 1000 || self.coordination_timeout.0 > 60000 {
316 return Err(Error::IllegalValue);
317 }
318
319 if self.max_concurrent_attempts.0 == 0 || self.max_concurrent_attempts.0 > 10 {
321 return Err(Error::IllegalValue);
322 }
323
324 Ok(())
325 }
326}
327
328impl Default for NatTraversalConfig {
329 fn default() -> Self {
330 Self {
331 role: NatTraversalRole::Client,
332 max_candidates: VarInt::from_u32(8),
333 coordination_timeout: VarInt::from_u32(10000), max_concurrent_attempts: VarInt::from_u32(3),
335 peer_id: None,
336 }
337 }
338}
339
340#[derive(Debug, Clone, Copy, PartialEq, Eq)]
342pub struct AddressDiscoveryConfig {
343 pub(crate) enabled: bool,
345 pub(crate) max_observation_rate: u8,
348 pub(crate) observe_all_paths: bool,
350}
351
352impl AddressDiscoveryConfig {
353 pub fn new(enabled: bool, max_observation_rate: u8, observe_all_paths: bool) -> Self {
355 Self {
356 enabled,
357 max_observation_rate: max_observation_rate.min(63), observe_all_paths,
359 }
360 }
361
362 pub fn apply_bootstrap_settings(&mut self) {
364 self.enabled = true;
366 self.max_observation_rate = 63; self.observe_all_paths = true;
370 }
371}
372
373impl Default for AddressDiscoveryConfig {
374 fn default() -> Self {
375 Self {
376 enabled: true, max_observation_rate: 10,
378 observe_all_paths: false,
379 }
380 }
381}
382
383#[derive(Debug, Copy, Clone, Eq, PartialEq)]
385pub enum NatTraversalRole {
386 Client,
388 Server {
390 can_relay: bool,
392 },
393 Bootstrap,
395}
396
397#[derive(Debug, Copy, Clone, Eq, PartialEq)]
401pub(crate) struct PreferredAddress {
402 pub(crate) address_v4: Option<SocketAddrV4>,
403 pub(crate) address_v6: Option<SocketAddrV6>,
404 pub(crate) connection_id: ConnectionId,
405 pub(crate) stateless_reset_token: ResetToken,
406}
407
408impl PreferredAddress {
409 fn wire_size(&self) -> u16 {
410 4 + 2 + 16 + 2 + 1 + self.connection_id.len() as u16 + 16
411 }
412
413 fn write<W: BufMut>(&self, w: &mut W) {
414 w.write(self.address_v4.map_or(Ipv4Addr::UNSPECIFIED, |x| *x.ip()));
415 w.write::<u16>(self.address_v4.map_or(0, |x| x.port()));
416 w.write(self.address_v6.map_or(Ipv6Addr::UNSPECIFIED, |x| *x.ip()));
417 w.write::<u16>(self.address_v6.map_or(0, |x| x.port()));
418 w.write::<u8>(self.connection_id.len() as u8);
419 w.put_slice(&self.connection_id);
420 w.put_slice(&self.stateless_reset_token);
421 }
422
423 fn read<R: Buf>(r: &mut R) -> Result<Self, Error> {
424 let ip_v4 = r.get::<Ipv4Addr>()?;
425 let port_v4 = r.get::<u16>()?;
426 let ip_v6 = r.get::<Ipv6Addr>()?;
427 let port_v6 = r.get::<u16>()?;
428 let cid_len = r.get::<u8>()?;
429 if r.remaining() < cid_len as usize || cid_len > MAX_CID_SIZE as u8 {
430 return Err(Error::Malformed);
431 }
432 let mut stage = [0; MAX_CID_SIZE];
433 r.copy_to_slice(&mut stage[0..cid_len as usize]);
434 let cid = ConnectionId::new(&stage[0..cid_len as usize]);
435 if r.remaining() < 16 {
436 return Err(Error::Malformed);
437 }
438 let mut token = [0; RESET_TOKEN_SIZE];
439 r.copy_to_slice(&mut token);
440 let address_v4 = if ip_v4.is_unspecified() && port_v4 == 0 {
441 None
442 } else {
443 Some(SocketAddrV4::new(ip_v4, port_v4))
444 };
445 let address_v6 = if ip_v6.is_unspecified() && port_v6 == 0 {
446 None
447 } else {
448 Some(SocketAddrV6::new(ip_v6, port_v6, 0, 0))
449 };
450 if address_v4.is_none() && address_v6.is_none() {
451 return Err(Error::IllegalValue);
452 }
453 Ok(Self {
454 address_v4,
455 address_v6,
456 connection_id: cid,
457 stateless_reset_token: token.into(),
458 })
459 }
460}
461
462#[derive(Debug, Copy, Clone, Eq, PartialEq, Error)]
464pub enum Error {
465 #[error("parameter had illegal value")]
467 IllegalValue,
468 #[error("parameters were malformed")]
470 Malformed,
471}
472
473impl From<Error> for TransportError {
474 fn from(e: Error) -> Self {
475 match e {
476 Error::IllegalValue => Self::TRANSPORT_PARAMETER_ERROR("illegal value"),
477 Error::Malformed => Self::TRANSPORT_PARAMETER_ERROR("malformed"),
478 }
479 }
480}
481
482impl From<UnexpectedEnd> for Error {
483 fn from(_: UnexpectedEnd) -> Self {
484 Self::Malformed
485 }
486}
487
488impl TransportParameters {
489 pub fn write<W: BufMut>(&self, w: &mut W) {
491 for idx in self
492 .write_order
493 .as_ref()
494 .unwrap_or(&std::array::from_fn(|i| i as u8))
495 {
496 let id = TransportParameterId::SUPPORTED[*idx as usize];
497 match id {
498 TransportParameterId::ReservedTransportParameter => {
499 if let Some(param) = self.grease_transport_parameter {
500 param.write(w);
501 }
502 }
503 TransportParameterId::StatelessResetToken => {
504 if let Some(ref x) = self.stateless_reset_token {
505 w.write_var(id as u64);
506 w.write_var(16);
507 w.put_slice(x);
508 }
509 }
510 TransportParameterId::DisableActiveMigration => {
511 if self.disable_active_migration {
512 w.write_var(id as u64);
513 w.write_var(0);
514 }
515 }
516 TransportParameterId::MaxDatagramFrameSize => {
517 if let Some(x) = self.max_datagram_frame_size {
518 w.write_var(id as u64);
519 w.write_var(x.size() as u64);
520 w.write(x);
521 }
522 }
523 TransportParameterId::PreferredAddress => {
524 if let Some(ref x) = self.preferred_address {
525 w.write_var(id as u64);
526 w.write_var(x.wire_size() as u64);
527 x.write(w);
528 }
529 }
530 TransportParameterId::OriginalDestinationConnectionId => {
531 if let Some(ref cid) = self.original_dst_cid {
532 w.write_var(id as u64);
533 w.write_var(cid.len() as u64);
534 w.put_slice(cid);
535 }
536 }
537 TransportParameterId::InitialSourceConnectionId => {
538 if let Some(ref cid) = self.initial_src_cid {
539 w.write_var(id as u64);
540 w.write_var(cid.len() as u64);
541 w.put_slice(cid);
542 }
543 }
544 TransportParameterId::RetrySourceConnectionId => {
545 if let Some(ref cid) = self.retry_src_cid {
546 w.write_var(id as u64);
547 w.write_var(cid.len() as u64);
548 w.put_slice(cid);
549 }
550 }
551 TransportParameterId::GreaseQuicBit => {
552 if self.grease_quic_bit {
553 w.write_var(id as u64);
554 w.write_var(0);
555 }
556 }
557 TransportParameterId::MinAckDelayDraft07 => {
558 if let Some(x) = self.min_ack_delay {
559 w.write_var(id as u64);
560 w.write_var(x.size() as u64);
561 w.write(x);
562 }
563 }
564 TransportParameterId::NatTraversal => {
565 if let Some(ref config) = self.nat_traversal {
566 match config.role {
570 NatTraversalRole::Client => {
571 w.write_var(id as u64);
573 w.write_var(0); }
575 NatTraversalRole::Server { can_relay: _ } => {
576 w.write_var(id as u64);
578 w.write_var(1); let limit = config.max_concurrent_attempts.0.min(255) as u8;
581 w.put_u8(limit);
582 }
583 NatTraversalRole::Bootstrap => {
584 w.write_var(id as u64);
586 w.write_var(1); let limit = config.max_concurrent_attempts.0.min(255) as u8;
588 w.put_u8(limit);
589 }
590 }
591 }
592 }
593 TransportParameterId::AddressDiscovery => {
594 if let Some(ref config) = self.address_discovery {
595 if config.enabled {
596 w.write_var(id as u64);
597 w.write_var(1); let config_byte = 0x80 | (if config.observe_all_paths { 0x40 } else { 0 }) |
601 (config.max_observation_rate & 0x3F);
602 w.put_u8(config_byte);
603 }
604 }
605 }
606 id => {
607 macro_rules! write_params {
608 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => {
609 match id {
610 $(TransportParameterId::$id => {
611 if self.$name.0 != $default {
612 w.write_var(id as u64);
613 w.write(VarInt::try_from(self.$name.size()).unwrap());
614 w.write(self.$name);
615 }
616 })*,
617 _ => {
618 panic!("Unsupported transport parameter reached write implementation: {id:?}");
621 }
622 }
623 }
624 }
625 apply_params!(write_params);
626 }
627 }
628 }
629 }
630
631 pub fn read<R: Buf>(side: Side, r: &mut R) -> Result<Self, Error> {
633 let mut params = Self::default();
635
636 macro_rules! param_state {
638 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => {{
639 struct ParamState {
640 $($name: bool,)*
641 }
642
643 ParamState {
644 $($name: false,)*
645 }
646 }}
647 }
648 let mut got = apply_params!(param_state);
649
650 while r.has_remaining() {
651 let id = r.get_var()?;
652 let len = r.get_var()?;
653 if (r.remaining() as u64) < len {
654 return Err(Error::Malformed);
655 }
656 let len = len as usize;
657 let Ok(id) = TransportParameterId::try_from(id) else {
658 r.advance(len);
660 continue;
661 };
662
663 match id {
664 TransportParameterId::OriginalDestinationConnectionId => {
665 decode_cid(len, &mut params.original_dst_cid, r)?
666 }
667 TransportParameterId::StatelessResetToken => {
668 if len != 16 || params.stateless_reset_token.is_some() {
669 return Err(Error::Malformed);
670 }
671 let mut tok = [0; RESET_TOKEN_SIZE];
672 r.copy_to_slice(&mut tok);
673 params.stateless_reset_token = Some(tok.into());
674 }
675 TransportParameterId::DisableActiveMigration => {
676 if len != 0 || params.disable_active_migration {
677 return Err(Error::Malformed);
678 }
679 params.disable_active_migration = true;
680 }
681 TransportParameterId::PreferredAddress => {
682 if params.preferred_address.is_some() {
683 return Err(Error::Malformed);
684 }
685 params.preferred_address = Some(PreferredAddress::read(&mut r.take(len))?);
686 }
687 TransportParameterId::InitialSourceConnectionId => {
688 decode_cid(len, &mut params.initial_src_cid, r)?
689 }
690 TransportParameterId::RetrySourceConnectionId => {
691 decode_cid(len, &mut params.retry_src_cid, r)?
692 }
693 TransportParameterId::MaxDatagramFrameSize => {
694 if len > 8 || params.max_datagram_frame_size.is_some() {
695 return Err(Error::Malformed);
696 }
697 params.max_datagram_frame_size = Some(r.get().unwrap());
698 }
699 TransportParameterId::GreaseQuicBit => match len {
700 0 => params.grease_quic_bit = true,
701 _ => return Err(Error::Malformed),
702 },
703 TransportParameterId::MinAckDelayDraft07 => {
704 params.min_ack_delay = Some(r.get().unwrap())
705 }
706 TransportParameterId::NatTraversal => {
707 if params.nat_traversal.is_some() {
708 return Err(Error::Malformed);
709 }
710 match (side, len) {
714 (Side::Server, 0) => {
715 params.nat_traversal = Some(NatTraversalConfig {
717 role: NatTraversalRole::Client,
718 max_candidates: VarInt::from_u32(8), coordination_timeout: VarInt::from_u32(10000), max_concurrent_attempts: VarInt::from_u32(3), peer_id: None,
722 });
723 }
724 (Side::Client, 1) => {
725 let limit = r.get::<u8>()?;
727 params.nat_traversal = Some(NatTraversalConfig {
728 role: NatTraversalRole::Server { can_relay: false }, max_candidates: VarInt::from_u32(8), coordination_timeout: VarInt::from_u32(10000), max_concurrent_attempts: VarInt::from_u32(limit as u32),
732 peer_id: None,
733 });
734 }
735 _ => {
736 return Err(Error::Malformed);
738 }
739 }
740 }
741 TransportParameterId::AddressDiscovery => {
742 if params.address_discovery.is_some() {
743 return Err(Error::Malformed);
744 }
745 if len != 1 {
747 return Err(Error::Malformed);
748 }
749 let config_byte = r.get::<u8>()?;
750 params.address_discovery = Some(AddressDiscoveryConfig {
752 enabled: (config_byte & 0x80) != 0,
753 max_observation_rate: config_byte & 0x3F,
754 observe_all_paths: (config_byte & 0x40) != 0,
755 });
756 }
757 _ => {
758 macro_rules! parse {
759 {$($(#[$doc:meta])* $name:ident ($id:ident) = $default:expr,)*} => {
760 match id {
761 $(TransportParameterId::$id => {
762 let value = r.get::<VarInt>()?;
763 if len != value.size() || got.$name { return Err(Error::Malformed); }
764 params.$name = value.into();
765 got.$name = true;
766 })*
767 _ => r.advance(len),
768 }
769 }
770 }
771 apply_params!(parse);
772 }
773 }
774 }
775
776 if params.ack_delay_exponent.0 > 20
780 || params.max_ack_delay.0 >= 1 << 14
782 || params.active_connection_id_limit.0 < 2
784 || params.max_udp_payload_size.0 < 1200
786 || params.initial_max_streams_bidi.0 > MAX_STREAM_COUNT
788 || params.initial_max_streams_uni.0 > MAX_STREAM_COUNT
789 || params.min_ack_delay.is_some_and(|min_ack_delay| {
791 min_ack_delay.0 > params.max_ack_delay.0 * 1_000
793 })
794 || (side.is_server()
796 && (params.original_dst_cid.is_some()
797 || params.preferred_address.is_some()
798 || params.retry_src_cid.is_some()
799 || params.stateless_reset_token.is_some()))
800 || params
802 .preferred_address.is_some_and(|x| x.connection_id.is_empty())
803 {
804 return Err(Error::IllegalValue);
805 }
806
807 if let Some(ref nat_config) = params.nat_traversal {
809 if let Err(_) = nat_config.validate() {
811 return Err(Error::IllegalValue);
812 }
813
814 match nat_config.role {
816 NatTraversalRole::Server { .. } | NatTraversalRole::Bootstrap => {
817 if side.is_server() {
819 return Err(Error::IllegalValue);
820 }
821 }
822 NatTraversalRole::Client => {
823 if side.is_client() {
825 return Err(Error::IllegalValue);
826 }
827 }
828 }
829 }
830
831 Ok(params)
832 }
833}
834
835#[derive(Debug, Copy, Clone, Eq, PartialEq)]
844pub(crate) struct ReservedTransportParameter {
845 id: VarInt,
847
848 payload: [u8; Self::MAX_PAYLOAD_LEN],
850
851 payload_len: usize,
853}
854
855impl ReservedTransportParameter {
856 fn random(rng: &mut impl RngCore) -> Self {
862 let id = Self::generate_reserved_id(rng);
863
864 let payload_len = rng.gen_range(0..Self::MAX_PAYLOAD_LEN);
865
866 let payload = {
867 let mut slice = [0u8; Self::MAX_PAYLOAD_LEN];
868 rng.fill_bytes(&mut slice[..payload_len]);
869 slice
870 };
871
872 Self {
873 id,
874 payload,
875 payload_len,
876 }
877 }
878
879 fn write(&self, w: &mut impl BufMut) {
880 w.write_var(self.id.0);
881 w.write_var(self.payload_len as u64);
882 w.put_slice(&self.payload[..self.payload_len]);
883 }
884
885 fn generate_reserved_id(rng: &mut impl RngCore) -> VarInt {
890 let id = {
891 let rand = rng.gen_range(0u64..(1 << 62) - 27);
892 let n = rand / 31;
893 31 * n + 27
894 };
895 debug_assert!(
896 id % 31 == 27,
897 "generated id does not have the form of 31 * N + 27"
898 );
899 VarInt::from_u64(id).expect(
900 "generated id does fit into range of allowed transport parameter IDs: [0; 2^62)",
901 )
902 }
903
904 const MAX_PAYLOAD_LEN: usize = 16;
908}
909
910#[repr(u64)]
911#[derive(Debug, Clone, Copy, PartialEq, Eq)]
912pub(crate) enum TransportParameterId {
913 OriginalDestinationConnectionId = 0x00,
915 MaxIdleTimeout = 0x01,
916 StatelessResetToken = 0x02,
917 MaxUdpPayloadSize = 0x03,
918 InitialMaxData = 0x04,
919 InitialMaxStreamDataBidiLocal = 0x05,
920 InitialMaxStreamDataBidiRemote = 0x06,
921 InitialMaxStreamDataUni = 0x07,
922 InitialMaxStreamsBidi = 0x08,
923 InitialMaxStreamsUni = 0x09,
924 AckDelayExponent = 0x0A,
925 MaxAckDelay = 0x0B,
926 DisableActiveMigration = 0x0C,
927 PreferredAddress = 0x0D,
928 ActiveConnectionIdLimit = 0x0E,
929 InitialSourceConnectionId = 0x0F,
930 RetrySourceConnectionId = 0x10,
931
932 ReservedTransportParameter = 0x1B,
934
935 MaxDatagramFrameSize = 0x20,
937
938 GreaseQuicBit = 0x2AB2,
940
941 MinAckDelayDraft07 = 0xFF04DE1B,
943
944 NatTraversal = 0x3d7e9f0bca12fea6,
947
948 AddressDiscovery = 0x1f00,
951}
952
953impl TransportParameterId {
954 const SUPPORTED: [Self; 23] = [
956 Self::MaxIdleTimeout,
957 Self::MaxUdpPayloadSize,
958 Self::InitialMaxData,
959 Self::InitialMaxStreamDataBidiLocal,
960 Self::InitialMaxStreamDataBidiRemote,
961 Self::InitialMaxStreamDataUni,
962 Self::InitialMaxStreamsBidi,
963 Self::InitialMaxStreamsUni,
964 Self::AckDelayExponent,
965 Self::MaxAckDelay,
966 Self::ActiveConnectionIdLimit,
967 Self::ReservedTransportParameter,
968 Self::StatelessResetToken,
969 Self::DisableActiveMigration,
970 Self::MaxDatagramFrameSize,
971 Self::PreferredAddress,
972 Self::OriginalDestinationConnectionId,
973 Self::InitialSourceConnectionId,
974 Self::RetrySourceConnectionId,
975 Self::GreaseQuicBit,
976 Self::MinAckDelayDraft07,
977 Self::NatTraversal,
978 Self::AddressDiscovery,
979 ];
980}
981
982impl std::cmp::PartialEq<u64> for TransportParameterId {
983 fn eq(&self, other: &u64) -> bool {
984 *other == (*self as u64)
985 }
986}
987
988impl TryFrom<u64> for TransportParameterId {
989 type Error = ();
990
991 fn try_from(value: u64) -> Result<Self, Self::Error> {
992 let param = match value {
993 id if Self::MaxIdleTimeout == id => Self::MaxIdleTimeout,
994 id if Self::MaxUdpPayloadSize == id => Self::MaxUdpPayloadSize,
995 id if Self::InitialMaxData == id => Self::InitialMaxData,
996 id if Self::InitialMaxStreamDataBidiLocal == id => Self::InitialMaxStreamDataBidiLocal,
997 id if Self::InitialMaxStreamDataBidiRemote == id => {
998 Self::InitialMaxStreamDataBidiRemote
999 }
1000 id if Self::InitialMaxStreamDataUni == id => Self::InitialMaxStreamDataUni,
1001 id if Self::InitialMaxStreamsBidi == id => Self::InitialMaxStreamsBidi,
1002 id if Self::InitialMaxStreamsUni == id => Self::InitialMaxStreamsUni,
1003 id if Self::AckDelayExponent == id => Self::AckDelayExponent,
1004 id if Self::MaxAckDelay == id => Self::MaxAckDelay,
1005 id if Self::ActiveConnectionIdLimit == id => Self::ActiveConnectionIdLimit,
1006 id if Self::ReservedTransportParameter == id => Self::ReservedTransportParameter,
1007 id if Self::StatelessResetToken == id => Self::StatelessResetToken,
1008 id if Self::DisableActiveMigration == id => Self::DisableActiveMigration,
1009 id if Self::MaxDatagramFrameSize == id => Self::MaxDatagramFrameSize,
1010 id if Self::PreferredAddress == id => Self::PreferredAddress,
1011 id if Self::OriginalDestinationConnectionId == id => {
1012 Self::OriginalDestinationConnectionId
1013 }
1014 id if Self::InitialSourceConnectionId == id => Self::InitialSourceConnectionId,
1015 id if Self::RetrySourceConnectionId == id => Self::RetrySourceConnectionId,
1016 id if Self::GreaseQuicBit == id => Self::GreaseQuicBit,
1017 id if Self::MinAckDelayDraft07 == id => Self::MinAckDelayDraft07,
1018 id if Self::NatTraversal == id => Self::NatTraversal,
1019 id if Self::AddressDiscovery == id => Self::AddressDiscovery,
1020 _ => return Err(()),
1021 };
1022 Ok(param)
1023 }
1024}
1025
1026fn decode_cid(len: usize, value: &mut Option<ConnectionId>, r: &mut impl Buf) -> Result<(), Error> {
1027 if len > MAX_CID_SIZE || value.is_some() || r.remaining() < len {
1028 return Err(Error::Malformed);
1029 }
1030
1031 *value = Some(ConnectionId::from_buf(r, len));
1032 Ok(())
1033}
1034
1035#[cfg(test)]
1036mod test {
1037 use super::*;
1038
1039 #[test]
1040 fn test_nat_traversal_transport_parameter_encoding_decoding() {
1041 let client_config = NatTraversalConfig {
1045 role: NatTraversalRole::Client,
1046 max_candidates: VarInt::from_u32(8),
1047 coordination_timeout: VarInt::from_u32(5000),
1048 max_concurrent_attempts: VarInt::from_u32(3),
1049 peer_id: None,
1050 };
1051
1052 let mut client_params = TransportParameters::default();
1053 client_params.nat_traversal = Some(client_config);
1054
1055 let mut encoded = Vec::new();
1056 client_params.write(&mut encoded);
1057
1058 let server_decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1060 .expect("Failed to decode client transport parameters");
1061
1062 assert!(server_decoded.nat_traversal.is_some());
1064 let server_view = server_decoded.nat_traversal.unwrap();
1065 assert!(matches!(server_view.role, NatTraversalRole::Client));
1066
1067 let server_config = NatTraversalConfig {
1069 role: NatTraversalRole::Server { can_relay: false },
1070 max_candidates: VarInt::from_u32(16),
1071 coordination_timeout: VarInt::from_u32(10000),
1072 max_concurrent_attempts: VarInt::from_u32(5),
1073 peer_id: None,
1074 };
1075
1076 let mut server_params = TransportParameters::default();
1077 server_params.nat_traversal = Some(server_config);
1078
1079 let mut encoded = Vec::new();
1080 server_params.write(&mut encoded);
1081
1082 let client_decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1084 .expect("Failed to decode server transport parameters");
1085
1086 assert!(client_decoded.nat_traversal.is_some());
1088 let client_view = client_decoded.nat_traversal.unwrap();
1089 assert!(matches!(client_view.role, NatTraversalRole::Server { .. }));
1090 assert_eq!(client_view.max_concurrent_attempts, VarInt::from_u32(5));
1091 }
1092
1093 #[test]
1094 fn test_nat_traversal_parameter_without_peer_id() {
1095 let config = NatTraversalConfig {
1097 role: NatTraversalRole::Client,
1098 max_candidates: VarInt::from_u32(4),
1099 coordination_timeout: VarInt::from_u32(3000),
1100 max_concurrent_attempts: VarInt::from_u32(2),
1101 peer_id: None,
1102 };
1103
1104 let mut params = TransportParameters::default();
1105 params.nat_traversal = Some(config);
1106
1107 let mut encoded = Vec::new();
1108 params.write(&mut encoded);
1109
1110 let decoded_params = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1112 .expect("Failed to decode transport parameters");
1113
1114 let decoded_config = decoded_params
1115 .nat_traversal
1116 .expect("NAT traversal config should be present");
1117
1118 assert_eq!(decoded_config.role, NatTraversalRole::Client);
1119 assert!(decoded_config.peer_id.is_none());
1120
1121 let server_config = NatTraversalConfig {
1123 role: NatTraversalRole::Server { can_relay: true },
1124 max_candidates: VarInt::from_u32(8),
1125 coordination_timeout: VarInt::from_u32(5000),
1126 max_concurrent_attempts: VarInt::from_u32(4),
1127 peer_id: None,
1128 };
1129
1130 let mut server_params = TransportParameters::default();
1131 server_params.nat_traversal = Some(server_config);
1132
1133 let mut server_encoded = Vec::new();
1134 server_params.write(&mut server_encoded);
1135
1136 let decoded_server_params =
1138 TransportParameters::read(Side::Client, &mut server_encoded.as_slice())
1139 .expect("Failed to decode server transport parameters");
1140
1141 let decoded_server_config = decoded_server_params
1142 .nat_traversal
1143 .expect("Server NAT traversal config should be present");
1144
1145 match decoded_server_config.role {
1146 NatTraversalRole::Server { can_relay } => {
1147 assert!(!can_relay);
1149 }
1150 _ => panic!("Expected server role"),
1151 }
1152 assert_eq!(
1153 decoded_server_config.max_concurrent_attempts,
1154 VarInt::from_u32(4)
1155 );
1156 }
1157
1158 #[test]
1159 fn test_transport_parameters_without_nat_traversal() {
1160 let mut params = TransportParameters::default();
1162 params.nat_traversal = None;
1163
1164 let mut encoded = Vec::new();
1165 params.write(&mut encoded);
1166
1167 let decoded_params = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1168 .expect("Failed to decode transport parameters");
1169
1170 assert!(decoded_params.nat_traversal.is_none());
1171 }
1172
1173 #[test]
1174 fn test_nat_traversal_draft_compliant_encoding() {
1175 let client_config = NatTraversalConfig {
1179 role: NatTraversalRole::Client,
1180 max_candidates: VarInt::from_u32(8),
1181 coordination_timeout: VarInt::from_u32(10000),
1182 max_concurrent_attempts: VarInt::from_u32(3),
1183 peer_id: None,
1184 };
1185
1186 let mut client_params = TransportParameters::default();
1187 client_params.nat_traversal = Some(client_config);
1188
1189 let mut encoded = Vec::new();
1190 client_params.write(&mut encoded);
1191
1192 use bytes::Buf;
1195 let mut cursor = &encoded[..];
1196 while cursor.has_remaining() {
1197 let id = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1198 let len = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1199 if id.0 == 0x3d7e9f0bca12fea6 {
1200 assert_eq!(len.0, 0, "Client should send empty value");
1202 break;
1203 }
1204 cursor.advance(len.0 as usize);
1206 }
1207
1208 let server_config = NatTraversalConfig {
1210 role: NatTraversalRole::Server { can_relay: true },
1211 max_candidates: VarInt::from_u32(16),
1212 coordination_timeout: VarInt::from_u32(10000),
1213 max_concurrent_attempts: VarInt::from_u32(5),
1214 peer_id: None,
1215 };
1216
1217 let mut server_params = TransportParameters::default();
1218 server_params.nat_traversal = Some(server_config);
1219
1220 let mut encoded = Vec::new();
1221 server_params.write(&mut encoded);
1222
1223 let mut cursor = &encoded[..];
1225 while cursor.has_remaining() {
1226 let id = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1227 let len = VarInt::from_u64(cursor.get_var().unwrap()).unwrap();
1228 if id.0 == 0x3d7e9f0bca12fea6 {
1229 assert_eq!(len.0, 1, "Server should send 1-byte value");
1231 let limit = cursor.chunk()[0];
1232 assert_eq!(limit, 5, "Server should send concurrency limit");
1233 break;
1234 }
1235 cursor.advance(len.0 as usize);
1237 }
1238 }
1239
1240 #[test]
1241 fn test_nat_traversal_draft_compliant_decoding() {
1242 use bytes::BufMut;
1243
1244 let mut buf = Vec::new();
1246 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(0); let params = TransportParameters::read(Side::Server, &mut buf.as_slice())
1250 .expect("Failed to decode transport parameters");
1251
1252 let config = params
1253 .nat_traversal
1254 .expect("NAT traversal should be present");
1255 assert_eq!(config.role, NatTraversalRole::Client);
1256 assert_eq!(config.max_candidates, VarInt::from_u32(8)); assert_eq!(config.coordination_timeout, VarInt::from_u32(10000)); assert_eq!(config.max_concurrent_attempts, VarInt::from_u32(3)); let mut buf = Vec::new();
1262 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(1); buf.put_u8(7); let params = TransportParameters::read(Side::Client, &mut buf.as_slice())
1267 .expect("Failed to decode transport parameters");
1268
1269 let config = params
1270 .nat_traversal
1271 .expect("NAT traversal should be present");
1272 match config.role {
1273 NatTraversalRole::Server { can_relay } => {
1274 assert!(!can_relay); }
1276 _ => panic!("Expected Server role"),
1277 }
1278 assert_eq!(config.max_concurrent_attempts, VarInt::from_u32(7));
1279
1280 let mut buf = Vec::new();
1282 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(2); buf.put_u8(7);
1285 buf.put_u8(8);
1286
1287 let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1288 assert!(result.is_err(), "Should fail with invalid length");
1289 }
1290
1291 #[test]
1292 fn test_nat_traversal_parameter_id() {
1293 assert_eq!(
1295 TransportParameterId::NatTraversal as u64,
1296 0x3d7e9f0bca12fea6
1297 );
1298 }
1299
1300 #[test]
1301 fn test_nat_traversal_config_validation() {
1302 let valid_config = NatTraversalConfig {
1304 role: NatTraversalRole::Client,
1305 max_candidates: VarInt::from_u32(8),
1306 coordination_timeout: VarInt::from_u32(5000),
1307 max_concurrent_attempts: VarInt::from_u32(3),
1308 peer_id: None,
1309 };
1310 assert!(valid_config.validate().is_ok());
1311
1312 let invalid_config = NatTraversalConfig {
1314 max_candidates: VarInt::from_u32(0),
1315 ..valid_config
1316 };
1317 assert!(invalid_config.validate().is_err());
1318
1319 let invalid_config = NatTraversalConfig {
1321 max_candidates: VarInt::from_u32(101),
1322 ..valid_config
1323 };
1324 assert!(invalid_config.validate().is_err());
1325
1326 let invalid_config = NatTraversalConfig {
1328 coordination_timeout: VarInt::from_u32(500),
1329 ..valid_config
1330 };
1331 assert!(invalid_config.validate().is_err());
1332
1333 let invalid_config = NatTraversalConfig {
1335 coordination_timeout: VarInt::from_u32(70000),
1336 ..valid_config
1337 };
1338 assert!(invalid_config.validate().is_err());
1339
1340 let invalid_config = NatTraversalConfig {
1342 max_concurrent_attempts: VarInt::from_u32(0),
1343 ..valid_config
1344 };
1345 assert!(invalid_config.validate().is_err());
1346
1347 let invalid_config = NatTraversalConfig {
1349 max_concurrent_attempts: VarInt::from_u32(11),
1350 ..valid_config
1351 };
1352 assert!(invalid_config.validate().is_err());
1353 }
1354
1355 #[test]
1356 fn test_nat_traversal_role_validation() {
1357 use bytes::BufMut;
1358
1359 let mut buf = Vec::new();
1361 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(0); let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1366 assert!(
1367 result.is_err(),
1368 "Client should not accept client role from peer"
1369 );
1370
1371 let result = TransportParameters::read(Side::Server, &mut buf.as_slice());
1373 assert!(result.is_ok(), "Server should accept client role from peer");
1374
1375 let mut buf = Vec::new();
1377 buf.write_var(0x3d7e9f0bca12fea6); buf.write_var(1); buf.put_u8(5); let result = TransportParameters::read(Side::Server, &mut buf.as_slice());
1383 assert!(
1384 result.is_err(),
1385 "Server should not accept server role from peer"
1386 );
1387
1388 let result = TransportParameters::read(Side::Client, &mut buf.as_slice());
1390 assert!(result.is_ok(), "Client should accept server role from peer");
1391 }
1392
1393 #[test]
1394 fn test_nat_traversal_parameter_combinations() {
1395 let nat_config = NatTraversalConfig {
1397 role: NatTraversalRole::Client,
1398 max_candidates: VarInt::from_u32(10),
1399 coordination_timeout: VarInt::from_u32(8000),
1400 max_concurrent_attempts: VarInt::from_u32(4),
1401 peer_id: Some([42u8; 32]),
1402 };
1403
1404 let mut params = TransportParameters::default();
1405 params.nat_traversal = Some(nat_config);
1406 params.max_idle_timeout = VarInt::from_u32(30000);
1407 params.initial_max_data = VarInt::from_u32(1048576);
1408 params.grease_quic_bit = true;
1409
1410 let mut encoded = Vec::new();
1412 params.write(&mut encoded);
1413 assert!(!encoded.is_empty());
1414
1415 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1417 .expect("Should decode successfully");
1418
1419 let decoded_config = decoded
1421 .nat_traversal
1422 .expect("NAT traversal should be present");
1423 assert_eq!(decoded_config.role, NatTraversalRole::Client);
1424 assert_eq!(decoded_config.max_candidates, VarInt::from_u32(8)); assert_eq!(decoded.max_idle_timeout, VarInt::from_u32(30000));
1428 assert_eq!(decoded.initial_max_data, VarInt::from_u32(1048576));
1429 assert!(decoded.grease_quic_bit);
1430 }
1431
1432 #[test]
1433 fn test_nat_traversal_default_config() {
1434 let default_config = NatTraversalConfig::default();
1435
1436 assert_eq!(default_config.role, NatTraversalRole::Client);
1437 assert_eq!(default_config.max_candidates, VarInt::from_u32(8));
1438 assert_eq!(default_config.coordination_timeout, VarInt::from_u32(10000));
1439 assert_eq!(default_config.max_concurrent_attempts, VarInt::from_u32(3));
1440 assert!(default_config.peer_id.is_none());
1441
1442 assert!(default_config.validate().is_ok());
1444 }
1445
1446 #[test]
1447 fn test_nat_traversal_endpoint_role_negotiation() {
1448 let client_config = NatTraversalConfig {
1452 role: NatTraversalRole::Client,
1453 max_candidates: VarInt::from_u32(12),
1454 coordination_timeout: VarInt::from_u32(7000),
1455 max_concurrent_attempts: VarInt::from_u32(5),
1456 peer_id: None,
1457 };
1458
1459 let mut client_params = TransportParameters::default();
1460 client_params.nat_traversal = Some(client_config);
1461
1462 let mut client_encoded = Vec::new();
1464 client_params.write(&mut client_encoded);
1465
1466 let server_received =
1468 TransportParameters::read(Side::Server, &mut client_encoded.as_slice())
1469 .expect("Server should decode client params");
1470
1471 let server_view = server_received
1473 .nat_traversal
1474 .expect("NAT traversal should be present");
1475 assert_eq!(server_view.role, NatTraversalRole::Client);
1476
1477 let server_config = NatTraversalConfig {
1479 role: NatTraversalRole::Server { can_relay: true },
1480 max_candidates: VarInt::from_u32(16),
1481 coordination_timeout: VarInt::from_u32(12000),
1482 max_concurrent_attempts: VarInt::from_u32(8),
1483 peer_id: Some([123u8; 32]),
1484 };
1485
1486 let mut server_params = TransportParameters::default();
1487 server_params.nat_traversal = Some(server_config);
1488
1489 let mut server_encoded = Vec::new();
1491 server_params.write(&mut server_encoded);
1492
1493 let client_received =
1495 TransportParameters::read(Side::Client, &mut server_encoded.as_slice())
1496 .expect("Client should decode server params");
1497
1498 let client_view = client_received
1500 .nat_traversal
1501 .expect("NAT traversal should be present");
1502 match client_view.role {
1503 NatTraversalRole::Server { can_relay } => {
1504 assert!(!can_relay); }
1506 _ => panic!("Expected server role"),
1507 }
1508 assert_eq!(client_view.max_concurrent_attempts, VarInt::from_u32(8));
1509 }
1510
1511 #[test]
1512 fn coding() {
1513 let mut buf = Vec::new();
1514 let params = TransportParameters {
1515 initial_src_cid: Some(ConnectionId::new(&[])),
1516 original_dst_cid: Some(ConnectionId::new(&[])),
1517 initial_max_streams_bidi: 16u32.into(),
1518 initial_max_streams_uni: 16u32.into(),
1519 ack_delay_exponent: 2u32.into(),
1520 max_udp_payload_size: 1200u32.into(),
1521 preferred_address: Some(PreferredAddress {
1522 address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
1523 address_v6: Some(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 24, 0, 0)),
1524 connection_id: ConnectionId::new(&[0x42]),
1525 stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
1526 }),
1527 grease_quic_bit: true,
1528 min_ack_delay: Some(2_000u32.into()),
1529 ..TransportParameters::default()
1530 };
1531 params.write(&mut buf);
1532 assert_eq!(
1533 TransportParameters::read(Side::Client, &mut buf.as_slice()).unwrap(),
1534 params
1535 );
1536 }
1537
1538 #[test]
1539 fn reserved_transport_parameter_generate_reserved_id() {
1540 use rand::rngs::mock::StepRng;
1541 let mut rngs = [
1542 StepRng::new(0, 1),
1543 StepRng::new(1, 1),
1544 StepRng::new(27, 1),
1545 StepRng::new(31, 1),
1546 StepRng::new(u32::MAX as u64, 1),
1547 StepRng::new(u32::MAX as u64 - 1, 1),
1548 StepRng::new(u32::MAX as u64 + 1, 1),
1549 StepRng::new(u32::MAX as u64 - 27, 1),
1550 StepRng::new(u32::MAX as u64 + 27, 1),
1551 StepRng::new(u32::MAX as u64 - 31, 1),
1552 StepRng::new(u32::MAX as u64 + 31, 1),
1553 StepRng::new(u64::MAX, 1),
1554 StepRng::new(u64::MAX - 1, 1),
1555 StepRng::new(u64::MAX - 27, 1),
1556 StepRng::new(u64::MAX - 31, 1),
1557 StepRng::new(1 << 62, 1),
1558 StepRng::new((1 << 62) - 1, 1),
1559 StepRng::new((1 << 62) + 1, 1),
1560 StepRng::new((1 << 62) - 27, 1),
1561 StepRng::new((1 << 62) + 27, 1),
1562 StepRng::new((1 << 62) - 31, 1),
1563 StepRng::new((1 << 62) + 31, 1),
1564 ];
1565 for rng in &mut rngs {
1566 let id = ReservedTransportParameter::generate_reserved_id(rng);
1567 assert!(id.0 % 31 == 27)
1568 }
1569 }
1570
1571 #[test]
1572 fn reserved_transport_parameter_ignored_when_read() {
1573 let mut buf = Vec::new();
1574 let reserved_parameter = ReservedTransportParameter::random(&mut rand::thread_rng());
1575 assert!(reserved_parameter.payload_len < ReservedTransportParameter::MAX_PAYLOAD_LEN);
1576 assert!(reserved_parameter.id.0 % 31 == 27);
1577
1578 reserved_parameter.write(&mut buf);
1579 assert!(!buf.is_empty());
1580 let read_params = TransportParameters::read(Side::Server, &mut buf.as_slice()).unwrap();
1581 assert_eq!(read_params, TransportParameters::default());
1582 }
1583
1584 #[test]
1585 fn read_semantic_validation() {
1586 #[allow(clippy::type_complexity)]
1587 let illegal_params_builders: Vec<Box<dyn FnMut(&mut TransportParameters)>> = vec![
1588 Box::new(|t| {
1589 let min_ack_delay = t.max_ack_delay.0 * 1_000 + 1;
1591 t.min_ack_delay = Some(VarInt::from_u64(min_ack_delay).unwrap())
1592 }),
1593 Box::new(|t| {
1594 t.preferred_address = Some(PreferredAddress {
1597 address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
1598 address_v6: None,
1599 connection_id: ConnectionId::new(&[]),
1600 stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
1601 })
1602 }),
1603 ];
1604
1605 for mut builder in illegal_params_builders {
1606 let mut buf = Vec::new();
1607 let mut params = TransportParameters::default();
1608 builder(&mut params);
1609 params.write(&mut buf);
1610
1611 assert_eq!(
1612 TransportParameters::read(Side::Server, &mut buf.as_slice()),
1613 Err(Error::IllegalValue)
1614 );
1615 }
1616 }
1617
1618 #[test]
1619 fn resumption_params_validation() {
1620 let high_limit = TransportParameters {
1621 initial_max_streams_uni: 32u32.into(),
1622 ..TransportParameters::default()
1623 };
1624 let low_limit = TransportParameters {
1625 initial_max_streams_uni: 16u32.into(),
1626 ..TransportParameters::default()
1627 };
1628 high_limit.validate_resumption_from(&low_limit).unwrap();
1629 low_limit.validate_resumption_from(&high_limit).unwrap_err();
1630 }
1631
1632 #[test]
1633 fn test_address_discovery_parameter_id() {
1634 assert_eq!(TransportParameterId::AddressDiscovery as u64, 0x1f00);
1636 }
1637
1638 #[test]
1639 fn test_address_discovery_config_struct() {
1640 let config = AddressDiscoveryConfig {
1642 enabled: true,
1643 max_observation_rate: 10,
1644 observe_all_paths: false,
1645 };
1646
1647 assert!(config.enabled);
1648 assert_eq!(config.max_observation_rate, 10);
1649 assert!(!config.observe_all_paths);
1650 }
1651
1652 #[test]
1653 fn test_address_discovery_config_new() {
1654 let config = AddressDiscoveryConfig::new(true, 100, true);
1656 assert!(config.enabled);
1657 assert_eq!(config.max_observation_rate, 63); assert!(config.observe_all_paths);
1659 }
1660
1661 #[test]
1662 fn test_transport_parameters_with_address_discovery() {
1663 let mut params = TransportParameters::default();
1665 assert!(params.address_discovery.is_none());
1666
1667 let config = AddressDiscoveryConfig {
1668 enabled: true,
1669 max_observation_rate: 5,
1670 observe_all_paths: true,
1671 };
1672
1673 params.address_discovery = Some(config);
1674 assert!(params.address_discovery.is_some());
1675
1676 let stored_config = params.address_discovery.as_ref().unwrap();
1677 assert!(stored_config.enabled);
1678 assert_eq!(stored_config.max_observation_rate, 5);
1679 assert!(stored_config.observe_all_paths);
1680 }
1681
1682 #[test]
1683 fn test_address_discovery_parameter_encoding() {
1684 let config = AddressDiscoveryConfig {
1686 enabled: true,
1687 max_observation_rate: 10,
1688 observe_all_paths: false,
1689 };
1690
1691 let mut params = TransportParameters::default();
1692 params.address_discovery = Some(config);
1693
1694 let mut encoded = Vec::new();
1695 params.write(&mut encoded);
1696
1697 assert!(!encoded.is_empty());
1699 }
1700
1701 #[test]
1702 fn test_address_discovery_parameter_roundtrip() {
1703 let config = AddressDiscoveryConfig {
1705 enabled: true,
1706 max_observation_rate: 15,
1707 observe_all_paths: true,
1708 };
1709
1710 let mut params = TransportParameters::default();
1711 params.address_discovery = Some(config);
1712
1713 let mut encoded = Vec::new();
1714 params.write(&mut encoded);
1715
1716 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1718 .expect("Failed to decode transport parameters");
1719
1720 assert!(decoded.address_discovery.is_some());
1721 let decoded_config = decoded.address_discovery.as_ref().unwrap();
1722 assert!(decoded_config.enabled);
1723 assert_eq!(decoded_config.max_observation_rate, 15);
1724 assert!(decoded_config.observe_all_paths);
1725 }
1726
1727 #[test]
1728 fn test_address_discovery_disabled_by_default() {
1729 let params = TransportParameters::default();
1731 assert!(params.address_discovery.is_none());
1732 }
1733
1734 #[test]
1735 fn test_address_discovery_max_rate_limits() {
1736 let config = AddressDiscoveryConfig {
1738 enabled: true,
1739 max_observation_rate: 63, observe_all_paths: false,
1741 };
1742
1743 let mut params = TransportParameters::default();
1744 params.address_discovery = Some(config);
1745
1746 let mut encoded = Vec::new();
1747 params.write(&mut encoded);
1748
1749 let decoded = TransportParameters::read(Side::Server, &mut encoded.as_slice())
1750 .expect("Failed to decode");
1751
1752 let decoded_config = decoded.address_discovery.as_ref().unwrap();
1753 assert_eq!(decoded_config.max_observation_rate, 63);
1754 }
1755
1756 #[test]
1757 fn test_address_discovery_disabled_not_encoded() {
1758 let config = AddressDiscoveryConfig {
1760 enabled: false,
1761 max_observation_rate: 10,
1762 observe_all_paths: false,
1763 };
1764
1765 let mut params = TransportParameters::default();
1766 params.address_discovery = Some(config);
1767
1768 let mut encoded = Vec::new();
1769 params.write(&mut encoded);
1770
1771 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1773 .expect("Failed to decode");
1774
1775 assert!(decoded.address_discovery.is_none());
1777 }
1778
1779 #[test]
1780 fn test_address_discovery_serialization_roundtrip() {
1781 let config = AddressDiscoveryConfig {
1782 enabled: true,
1783 max_observation_rate: 42,
1784 observe_all_paths: true,
1785 };
1786
1787 let mut params = TransportParameters::default();
1788 params.address_discovery = Some(config);
1789
1790 let mut encoded = Vec::new();
1791 params.write(&mut encoded);
1792
1793 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1794 .expect("Failed to decode");
1795
1796 assert!(decoded.address_discovery.is_some());
1797 let decoded_config = decoded.address_discovery.unwrap();
1798 assert_eq!(decoded_config.enabled, config.enabled);
1799 assert_eq!(decoded_config.max_observation_rate, config.max_observation_rate);
1800 assert_eq!(decoded_config.observe_all_paths, config.observe_all_paths);
1801 }
1802
1803 #[test]
1804 fn test_address_discovery_rate_truncation() {
1805 let config = AddressDiscoveryConfig {
1807 enabled: true,
1808 max_observation_rate: 255, observe_all_paths: true,
1810 };
1811
1812 let mut params = TransportParameters::default();
1813 params.address_discovery = Some(config);
1814
1815 let mut encoded = Vec::new();
1816 params.write(&mut encoded);
1817
1818 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1819 .expect("Failed to decode");
1820
1821 let decoded_config = decoded.address_discovery.unwrap();
1822 assert_eq!(decoded_config.max_observation_rate, 63); }
1824
1825 #[test]
1826 fn test_address_discovery_bit_encoding() {
1827 let test_cases = vec![
1829 (true, false, 0), (true, true, 0), (true, false, 25), (true, true, 50), ];
1834
1835 for (enabled, observe_all, rate) in test_cases {
1836 let config = AddressDiscoveryConfig {
1837 enabled,
1838 max_observation_rate: rate,
1839 observe_all_paths: observe_all,
1840 };
1841
1842 let mut params = TransportParameters::default();
1843 params.address_discovery = Some(config);
1844
1845 let mut encoded = Vec::new();
1846 params.write(&mut encoded);
1847
1848 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1849 .expect("Failed to decode");
1850
1851 let decoded_config = decoded.address_discovery.unwrap();
1852 assert_eq!(decoded_config.enabled, enabled);
1853 assert_eq!(decoded_config.observe_all_paths, observe_all);
1854 assert_eq!(decoded_config.max_observation_rate, rate);
1855 }
1856 }
1857
1858 #[test]
1859 fn test_address_discovery_malformed_length() {
1860 use bytes::BufMut;
1861
1862 let mut encoded = Vec::new();
1864 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
1865 encoded.write_var(2); encoded.put_u8(0x80); encoded.put_u8(0x00); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
1870 assert!(result.is_err());
1871 assert!(matches!(result.unwrap_err(), Error::Malformed));
1872 }
1873
1874 #[test]
1875 fn test_address_discovery_duplicate_parameter() {
1876 use bytes::BufMut;
1877
1878 let mut encoded = Vec::new();
1880
1881 encoded.write_var(TransportParameterId::AddressDiscovery as u64);
1883 encoded.write_var(1);
1884 encoded.put_u8(0x80); encoded.write_var(TransportParameterId::AddressDiscovery as u64);
1888 encoded.write_var(1);
1889 encoded.put_u8(0xC0); let result = TransportParameters::read(Side::Client, &mut encoded.as_slice());
1892 assert!(result.is_err());
1893 assert!(matches!(result.unwrap_err(), Error::Malformed));
1894 }
1895
1896 #[test]
1897 fn test_address_discovery_with_other_parameters() {
1898 let mut params = TransportParameters::default();
1900 params.max_idle_timeout = VarInt::from_u32(30000);
1901 params.initial_max_data = VarInt::from_u32(1_000_000);
1902 params.address_discovery = Some(AddressDiscoveryConfig {
1903 enabled: true,
1904 max_observation_rate: 15,
1905 observe_all_paths: true,
1906 });
1907
1908 let mut encoded = Vec::new();
1909 params.write(&mut encoded);
1910
1911 let decoded = TransportParameters::read(Side::Client, &mut encoded.as_slice())
1912 .expect("Failed to decode");
1913
1914 assert_eq!(decoded.max_idle_timeout, params.max_idle_timeout);
1916 assert_eq!(decoded.initial_max_data, params.initial_max_data);
1917 assert!(decoded.address_discovery.is_some());
1918
1919 let decoded_config = decoded.address_discovery.unwrap();
1920 assert_eq!(decoded_config.enabled, true);
1921 assert_eq!(decoded_config.max_observation_rate, 15);
1922 assert_eq!(decoded_config.observe_all_paths, true);
1923 }
1924
1925 mod comprehensive_tests {
1927 include!("transport_parameters/tests.rs");
1928 }
1929}