1use std::{
2 cmp,
3 collections::{BTreeMap, VecDeque, btree_map},
4 convert::TryFrom,
5 fmt, io, mem,
6 net::SocketAddr,
7 num::{NonZeroU32, NonZeroUsize},
8 sync::Arc,
9};
10
11use bytes::{Bytes, BytesMut};
12use frame::StreamMetaVec;
13
14use rand::{RngExt, SeedableRng, rngs::StdRng};
15use rustc_hash::FxHashMap;
16use thiserror::Error;
17use tracing::{debug, error, trace, trace_span, warn};
18
19use crate::{
20 Dir, Duration, EndpointConfig, FourTuple, Frame, INITIAL_MTU, Instant, MAX_CID_SIZE,
21 MAX_STREAM_COUNT, MIN_INITIAL_SIZE, Side, StreamId, TIMER_GRANULARITY, TokenStore, Transmit,
22 TransportError, TransportErrorCode, VarInt,
23 cid_generator::ConnectionIdGenerator,
24 cid_queue::CidQueue,
25 config::{ServerConfig, TransportConfig},
26 congestion::{Controller, PacketId},
27 connection::{
28 paths::PathRetransmits,
29 qlog::{QlogRecvPacket, QlogSink},
30 spaces::LostPacket,
31 stats::PathStatsMap,
32 timer::{ConnTimer, PathTimer},
33 },
34 crypto::{self, Keys},
35 frame::{
36 self, Close, DataBlocked, Datagram, FrameStruct, NewToken, ObservedAddr, StreamDataBlocked,
37 StreamsBlocked,
38 },
39 n0_nat_traversal,
40 packet::{
41 FixedLengthConnectionIdParser, Header, InitialHeader, InitialPacket, LongType, Packet,
42 PacketNumber, PartialDecode, SpaceId,
43 },
44 range_set::ArrayRangeSet,
45 shared::{
46 ConnectionEvent, ConnectionEventInner, ConnectionId, DatagramConnectionEvent, EcnCodepoint,
47 EndpointEvent, EndpointEventInner,
48 },
49 token::{ResetToken, Token, TokenPayload},
50 transport_parameters::TransportParameters,
51};
52
53mod ack_frequency;
54use ack_frequency::AckFrequencyState;
55
56mod assembler;
57pub use assembler::Chunk;
58
59mod cid_state;
60use cid_state::CidState;
61
62mod datagrams;
63use datagrams::DatagramState;
64pub use datagrams::{Datagrams, SendDatagramError};
65
66mod mtud;
67mod pacing;
68
69mod packet_builder;
70use packet_builder::{PacketBuilder, PadDatagram};
71
72mod packet_crypto;
73use packet_crypto::CryptoState;
74pub(crate) use packet_crypto::EncryptionLevel;
75
76mod paths;
77pub use paths::{
78 ClosedPath, PathAbandonReason, PathEvent, PathId, PathStatus, RttEstimator, SetPathStatusError,
79};
80use paths::{PathData, PathState};
81
82pub(crate) mod qlog;
83pub(crate) mod send_buffer;
84
85pub(crate) mod spaces;
86#[cfg(fuzzing)]
87pub use spaces::Retransmits;
88#[cfg(not(fuzzing))]
89use spaces::Retransmits;
90pub use spaces::SpaceKind;
91use spaces::{OpenStatus, PacketSpace, SendableFrames, SentPacket, ThinRetransmits};
92
93mod stats;
94pub use stats::{ConnectionStats, FrameStats, PathStats, UdpStats};
95
96mod streams;
97#[cfg(fuzzing)]
98pub use streams::StreamsState;
99#[cfg(not(fuzzing))]
100use streams::StreamsState;
101pub use streams::{
102 Chunks, ClosedStream, FinishError, ReadError, ReadableError, RecvStream, SendStream,
103 ShouldTransmit, StreamEvent, Streams, WriteError,
104};
105
106pub(crate) mod timer;
107use timer::{Timer, TimerTable};
108
109mod transmit_buf;
110use transmit_buf::TransmitBuf;
111
112mod state;
113
114#[cfg(not(fuzzing))]
115use state::State;
116#[cfg(fuzzing)]
117pub use state::State;
118use state::StateType;
119
120pub struct Connection {
159 endpoint_config: Arc<EndpointConfig>,
160 config: Arc<TransportConfig>,
161 rng: StdRng,
162 crypto_state: CryptoState,
164 handshake_cid: ConnectionId,
166 remote_handshake_cid: ConnectionId,
168 paths: BTreeMap<PathId, PathState>,
174 path_generation_counter: u64,
185 allow_mtud: bool,
187 state: State,
188 side: ConnectionSide,
189 peer_params: TransportParameters,
191 original_remote_cid: ConnectionId,
193 initial_dst_cid: ConnectionId,
195 retry_src_cid: Option<ConnectionId>,
198 events: VecDeque<Event>,
200 endpoint_events: VecDeque<EndpointEventInner>,
201 spin_enabled: bool,
203 spin: bool,
205 spaces: [PacketSpace; 3],
207 highest_space: SpaceKind,
209 idle_timeout: Option<Duration>,
211 timers: TimerTable,
212 authentication_failures: u64,
214
215 connection_close_pending: bool,
219
220 ack_frequency: AckFrequencyState,
223
224 receiving_ecn: bool,
228 total_authed_packets: u64,
230
231 next_observed_addr_seq_no: VarInt,
235
236 streams: StreamsState,
237 remote_cids: FxHashMap<PathId, CidQueue>,
243 local_cid_state: FxHashMap<PathId, CidState>,
250 datagrams: DatagramState,
252 path_stats: PathStatsMap,
254 partial_stats: ConnectionStats,
260 version: u32,
262
263 max_concurrent_paths: NonZeroU32,
271 local_max_path_id: PathId,
286 remote_max_path_id: PathId,
292 max_path_id_with_cids: PathId,
298 abandoned_paths: AbandonedPaths,
304
305 n0_nat_traversal: n0_nat_traversal::State,
307 qlog: QlogSink,
308}
309
310impl Connection {
311 pub(crate) fn new(
312 endpoint_config: Arc<EndpointConfig>,
313 config: Arc<TransportConfig>,
314 init_cid: ConnectionId,
315 local_cid: ConnectionId,
316 remote_cid: ConnectionId,
317 network_path: FourTuple,
318 crypto: Box<dyn crypto::Session>,
319 cid_gen: &dyn ConnectionIdGenerator,
320 now: Instant,
321 version: u32,
322 allow_mtud: bool,
323 rng_seed: [u8; 32],
324 side_args: SideArgs,
325 qlog: QlogSink,
326 ) -> Self {
327 let pref_addr_cid = side_args.pref_addr_cid();
328 let path_validated = side_args.path_validated();
329 let connection_side = ConnectionSide::from(side_args);
330 let side = connection_side.side();
331 let mut rng = StdRng::from_seed(rng_seed);
332 let mut initial_space = PacketSpace::new(now, SpaceId::Initial, &mut rng);
333 let mut handshake_space = PacketSpace::new(now, SpaceId::Handshake, &mut rng);
334 #[cfg(test)]
335 let mut data_space = match config.deterministic_packet_numbers {
336 true => PacketSpace::new_deterministic(now, SpaceId::Data),
337 false => PacketSpace::new(now, SpaceId::Data, &mut rng),
338 };
339 #[cfg(not(test))]
340 let mut data_space = PacketSpace::new(now, SpaceId::Data, &mut rng);
341
342 initial_space.for_path(PathId::ZERO).open_status = OpenStatus::Informed;
344 handshake_space.for_path(PathId::ZERO).open_status = OpenStatus::Informed;
345 data_space.for_path(PathId::ZERO).open_status = OpenStatus::Informed;
346
347 let state = State::handshake(state::Handshake {
348 remote_cid_set: side.is_server(),
349 expected_token: Bytes::new(),
350 client_hello: None,
351 allow_server_migration: side.is_client() && config.server_handshake_migration,
352 });
353 let local_cid_state = FxHashMap::from_iter([(
354 PathId::ZERO,
355 CidState::new(
356 cid_gen.cid_len(),
357 cid_gen.cid_lifetime(),
358 now,
359 if pref_addr_cid.is_some() { 2 } else { 1 },
360 ),
361 )]);
362
363 let mut this = Self {
364 endpoint_config,
365 crypto_state: CryptoState::new(crypto, init_cid, side, &mut rng),
366 handshake_cid: local_cid,
367 remote_handshake_cid: remote_cid,
368 local_cid_state,
369 paths: BTreeMap::from_iter([(
370 PathId::ZERO,
371 PathState {
372 data: PathData::new(network_path, allow_mtud, None, 0, now, &config),
373 prev: None,
374 },
375 )]),
376 path_generation_counter: 0,
377 allow_mtud,
378 state,
379 side: connection_side,
380 peer_params: TransportParameters::default(),
381 original_remote_cid: remote_cid,
382 initial_dst_cid: init_cid,
383 retry_src_cid: None,
384 events: VecDeque::new(),
385 endpoint_events: VecDeque::new(),
386 spin_enabled: config.allow_spin && rng.random_ratio(7, 8),
387 spin: false,
388 spaces: [initial_space, handshake_space, data_space],
389 highest_space: SpaceKind::Initial,
390 idle_timeout: match config.max_idle_timeout {
391 None | Some(VarInt(0)) => None,
392 Some(dur) => Some(Duration::from_millis(dur.0)),
393 },
394 timers: TimerTable::default(),
395 authentication_failures: 0,
396 connection_close_pending: false,
397
398 ack_frequency: AckFrequencyState::new(get_max_ack_delay(
399 &TransportParameters::default(),
400 )),
401
402 receiving_ecn: false,
403 total_authed_packets: 0,
404
405 next_observed_addr_seq_no: 0u32.into(),
406
407 streams: StreamsState::new(
408 side,
409 config.max_concurrent_uni_streams,
410 config.max_concurrent_bidi_streams,
411 config.send_window,
412 config.receive_window,
413 config.stream_receive_window,
414 ),
415 datagrams: DatagramState::default(),
416 config,
417 remote_cids: FxHashMap::from_iter([(PathId::ZERO, CidQueue::new(remote_cid))]),
418 rng,
419 path_stats: Default::default(),
420 partial_stats: ConnectionStats::default(),
421 version,
422
423 max_concurrent_paths: NonZeroU32::MIN,
425 local_max_path_id: PathId::ZERO,
426 remote_max_path_id: PathId::ZERO,
427 max_path_id_with_cids: PathId::ZERO,
428 abandoned_paths: Default::default(),
429
430 n0_nat_traversal: Default::default(),
431 qlog,
432 };
433 if path_validated {
434 this.on_path_validated(PathId::ZERO);
435 }
436 if side.is_client() {
437 this.write_crypto();
439 this.init_0rtt(now);
440 }
441 this.qlog
442 .emit_tuple_assigned(PathId::ZERO, network_path, now);
443 this
444 }
445
446 #[must_use]
454 pub fn poll_timeout(&self) -> Option<Instant> {
455 self.timers.peek()
456 }
457
458 #[cfg(test)]
463 pub(crate) fn timer_pending(&self, timer: Timer) -> Option<Instant> {
464 self.timers.get(timer)
465 }
466
467 #[must_use]
473 pub fn poll(&mut self) -> Option<Event> {
474 if let Some(x) = self.events.pop_front() {
475 return Some(x);
476 }
477
478 if let Some(event) = self.streams.poll() {
479 return Some(Event::Stream(event));
480 }
481
482 if let Some(reason) = self.state.take_error() {
483 return Some(Event::ConnectionLost { reason });
484 }
485
486 None
487 }
488
489 #[must_use]
491 pub fn poll_endpoint_events(&mut self) -> Option<EndpointEvent> {
492 self.endpoint_events.pop_front().map(EndpointEvent)
493 }
494
495 #[must_use]
497 pub fn streams(&mut self) -> Streams<'_> {
498 Streams {
499 state: &mut self.streams,
500 conn_state: &self.state,
501 }
502 }
503
504 #[must_use]
506 pub fn recv_stream(&mut self, id: StreamId) -> RecvStream<'_> {
507 assert!(id.dir() == Dir::Bi || id.initiator() != self.side.side());
508 RecvStream {
509 id,
510 state: &mut self.streams,
511 pending: &mut self.spaces[SpaceId::Data].pending,
512 }
513 }
514
515 #[must_use]
517 pub fn send_stream(&mut self, id: StreamId) -> SendStream<'_> {
518 assert!(id.dir() == Dir::Bi || id.initiator() == self.side.side());
519 SendStream {
520 id,
521 state: &mut self.streams,
522 pending: &mut self.spaces[SpaceId::Data].pending,
523 conn_state: &self.state,
524 }
525 }
526
527 pub fn open_path_ensure(
544 &mut self,
545 network_path: FourTuple,
546 initial_status: PathStatus,
547 now: Instant,
548 ) -> Result<(PathId, bool), PathError> {
549 let existing_open_path = self.paths.iter().find(|(id, path)| {
550 network_path.is_probably_same_path(&path.data.network_path)
551 && !self.abandoned_paths.contains(id)
552 });
553 match existing_open_path {
554 Some((path_id, _state)) => Ok((*path_id, true)),
555 None => Ok((self.open_path(network_path, initial_status, now)?, false)),
556 }
557 }
558
559 pub fn open_path(
565 &mut self,
566 network_path: FourTuple,
567 initial_status: PathStatus,
568 now: Instant,
569 ) -> Result<PathId, PathError> {
570 let Some(max_path_id) = self.max_path_id() else {
571 return Err(PathError::MultipathNotNegotiated);
572 };
573 if self.side().is_server() {
574 return Err(PathError::ServerSideNotAllowed);
575 }
576
577 let max_abandoned = self.abandoned_paths.max();
578 let max_used = self.paths.keys().last().copied();
579 let path_id = max_abandoned
580 .max(max_used)
581 .unwrap_or(PathId::ZERO)
582 .saturating_add(1u8);
583
584 if path_id > max_path_id {
585 self.spaces[SpaceId::Data].pending.paths_blocked = Some(self.remote_max_path_id);
586 return Err(PathError::MaxPathIdReached);
587 }
588 if !self.remote_cids.contains_key(&path_id) {
589 self.spaces[SpaceId::Data]
590 .pending
591 .path_cids_blocked
592 .insert(path_id, VarInt(0));
593 return Err(PathError::RemoteCidsExhausted);
594 }
595
596 let path = self.create_path(path_id, network_path, now, None);
597 path.status.local_update(initial_status);
598
599 Ok(path_id)
600 }
601
602 pub fn close_path(
608 &mut self,
609 now: Instant,
610 path_id: PathId,
611 error_code: VarInt,
612 ) -> Result<(), ClosePathError> {
613 self.close_path_inner(
614 now,
615 path_id,
616 PathAbandonReason::ApplicationClosed { error_code },
617 )
618 }
619
620 pub(crate) fn close_path_inner(
625 &mut self,
626 now: Instant,
627 path_id: PathId,
628 reason: PathAbandonReason,
629 ) -> Result<(), ClosePathError> {
630 if self.state.is_drained() {
631 return Ok(());
632 }
633
634 if !self.is_multipath_negotiated() {
635 return Err(ClosePathError::MultipathNotNegotiated);
636 }
637 if self.abandoned_paths.contains(&path_id)
638 || Some(path_id) > self.max_path_id()
639 || !self.paths.contains_key(&path_id)
640 {
641 return Err(ClosePathError::ClosedPath);
642 }
643
644 let is_last_path = !self
645 .paths
646 .keys()
647 .any(|id| *id != path_id && !self.abandoned_paths.contains(id));
648
649 if is_last_path && !reason.is_remote() {
650 return Err(ClosePathError::LastOpenPath);
651 }
652
653 self.abandon_path(now, path_id, reason);
654
655 if is_last_path {
659 let rtt = RttEstimator::new(self.config.initial_rtt);
663 let pto = rtt.pto_base() + self.ack_frequency.max_ack_delay_for_pto();
664 let grace = pto * 3;
665 self.timers.set(
666 Timer::Conn(ConnTimer::NoAvailablePath),
667 now + grace,
668 self.qlog.with_time(now),
669 );
670 }
671
672 Ok(())
673 }
674
675 fn abandon_path(&mut self, now: Instant, path_id: PathId, reason: PathAbandonReason) {
680 trace!(%path_id, ?reason, "abandoning path");
681
682 let pending_space = &mut self.spaces[SpaceId::Data].pending;
683 pending_space
685 .path_abandon
686 .insert(path_id, reason.error_code());
687
688 pending_space.new_cids.retain(|cid| cid.path_id != path_id);
690 pending_space.path_status.retain(|&id| id != path_id);
691
692 for space in self.spaces[SpaceId::Data].iter_paths_mut() {
695 for sent_packet in space.sent_packets.values_mut() {
696 if let Some(retransmits) = sent_packet.retransmits.get_mut() {
697 retransmits.new_cids.retain(|cid| cid.path_id != path_id);
698 retransmits.path_status.retain(|&id| id != path_id);
699 }
700 }
701 }
702
703 self.spaces[SpaceId::Data].for_path(path_id).loss_probes = 0;
708
709 debug_assert!(!self.state.is_drained()); self.endpoint_events
714 .push_back(EndpointEventInner::RetireResetToken(path_id));
715
716 self.abandoned_paths.insert(path_id);
717
718 for timer in PathTimer::VALUES {
719 let keep_timer = match timer {
721 PathTimer::PathValidationFailed | PathTimer::PathChallengeLost => false,
725 PathTimer::PathKeepAlive | PathTimer::PathIdle => false,
728 PathTimer::MaxAckDelay => false,
731 PathTimer::PathDrained => false,
734 PathTimer::LossDetection => true,
737 PathTimer::Pacing => true,
741 };
742
743 if !keep_timer {
744 let qlog = self.qlog.with_time(now);
745 self.timers.stop(Timer::PerPath(path_id, timer), qlog);
746 }
747 }
748
749 self.set_loss_detection_timer(now, path_id);
754
755 self.events.push_back(Event::Path(PathEvent::Abandoned {
757 id: path_id,
758 reason,
759 }));
760 }
761
762 #[track_caller]
766 fn path_data(&self, path_id: PathId) -> &PathData {
767 if let Some(data) = self.paths.get(&path_id) {
768 &data.data
769 } else {
770 panic!(
771 "unknown path: {path_id}, currently known paths: {:?}",
772 self.paths.keys().collect::<Vec<_>>()
773 );
774 }
775 }
776
777 #[track_caller]
781 fn path_data_mut(&mut self, path_id: PathId) -> &mut PathData {
782 &mut self.paths.get_mut(&path_id).expect("known path").data
783 }
784
785 fn path(&self, path_id: PathId) -> Option<&PathData> {
787 self.paths.get(&path_id).map(|path_state| &path_state.data)
788 }
789
790 fn path_mut(&mut self, path_id: PathId) -> Option<&mut PathData> {
792 self.paths
793 .get_mut(&path_id)
794 .map(|path_state| &mut path_state.data)
795 }
796
797 pub fn paths(&self) -> Vec<PathId> {
801 self.paths.keys().copied().collect()
802 }
803
804 pub fn path_status(&self, path_id: PathId) -> Result<PathStatus, ClosedPath> {
806 self.path(path_id)
807 .map(PathData::local_status)
808 .ok_or(ClosedPath { _private: () })
809 }
810
811 pub fn network_path(&self, path_id: PathId) -> Result<FourTuple, ClosedPath> {
813 self.path(path_id)
814 .map(|path| path.network_path)
815 .ok_or(ClosedPath { _private: () })
816 }
817
818 pub fn set_path_status(
822 &mut self,
823 path_id: PathId,
824 status: PathStatus,
825 ) -> Result<PathStatus, SetPathStatusError> {
826 if !self.is_multipath_negotiated() {
827 return Err(SetPathStatusError::MultipathNotNegotiated);
828 }
829 let path = self
830 .path_mut(path_id)
831 .ok_or(SetPathStatusError::ClosedPath)?;
832 let prev = match path.status.local_update(status) {
833 Some(prev) => {
834 self.spaces[SpaceId::Data]
835 .pending
836 .path_status
837 .insert(path_id);
838 prev
839 }
840 None => path.local_status(),
841 };
842 Ok(prev)
843 }
844
845 pub fn remote_path_status(&self, path_id: PathId) -> Option<PathStatus> {
850 self.path(path_id).and_then(|path| path.remote_status())
851 }
852
853 pub fn set_path_max_idle_timeout(
862 &mut self,
863 now: Instant,
864 path_id: PathId,
865 timeout: Option<Duration>,
866 ) -> Result<Option<Duration>, ClosedPath> {
867 let path = self
868 .paths
869 .get_mut(&path_id)
870 .ok_or(ClosedPath { _private: () })?;
871 let prev_timeout = mem::replace(&mut path.data.idle_timeout, timeout);
872
873 self.rearm_path_max_idle_timer(now, self.highest_space, path_id);
881
882 Ok(prev_timeout)
883 }
884
885 fn rearm_path_max_idle_timer(&mut self, now: Instant, space: SpaceKind, path_id: PathId) {
893 let timer = Timer::PerPath(path_id, PathTimer::PathIdle);
894
895 if self.state.is_closed() || !self.is_multipath_negotiated() {
896 return self.timers.stop(timer, self.qlog.with_time(now));
897 }
898
899 if let Some(timeout) = self.path_data(path_id).idle_timeout {
900 let dt = cmp::max(timeout, 3 * self.pto(space, path_id));
901 self.timers.set(timer, now + dt, self.qlog.with_time(now));
902 } else {
903 self.timers.stop(timer, self.qlog.with_time(now));
904 }
905 }
906
907 pub fn set_path_keep_alive_interval(
913 &mut self,
914 path_id: PathId,
915 interval: Option<Duration>,
916 ) -> Result<Option<Duration>, ClosedPath> {
917 let path = self
918 .paths
919 .get_mut(&path_id)
920 .ok_or(ClosedPath { _private: () })?;
921 Ok(mem::replace(&mut path.data.keep_alive, interval))
922 }
923
924 fn find_validated_path_on_network_path(
928 &self,
929 network_path: FourTuple,
930 ) -> Option<(&PathId, &PathState)> {
931 self.paths.iter().find(|(path_id, path_state)| {
932 path_state.data.validated
933 && network_path.is_probably_same_path(&path_state.data.network_path)
935 && !self.abandoned_paths.contains(path_id)
936 })
937 }
942
943 fn create_path(
947 &mut self,
948 path_id: PathId,
949 network_path: FourTuple,
950 now: Instant,
951 pn: Option<u64>,
952 ) -> &mut PathData {
953 let valid_path = self.find_validated_path_on_network_path(network_path);
954 let validated = valid_path.is_some();
955 let initial_rtt = valid_path.map(|(_, path)| path.data.rtt.conservative());
956 let vacant_entry = match self.paths.entry(path_id) {
957 btree_map::Entry::Vacant(vacant_entry) => vacant_entry,
958 btree_map::Entry::Occupied(occupied_entry) => {
959 return &mut occupied_entry.into_mut().data;
960 }
961 };
962
963 debug!(%validated, %path_id, %network_path, "path added");
964
965 self.timers.stop(
967 Timer::Conn(ConnTimer::NoAvailablePath),
968 self.qlog.with_time(now),
969 );
970 let peer_max_udp_payload_size =
971 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()).unwrap_or(u16::MAX);
972 self.path_generation_counter = self.path_generation_counter.wrapping_add(1);
973 let mut data = PathData::new(
974 network_path,
975 self.allow_mtud,
976 Some(peer_max_udp_payload_size),
977 self.path_generation_counter,
978 now,
979 &self.config,
980 );
981
982 data.validated = validated;
983 if let Some(initial_rtt) = initial_rtt {
984 data.rtt.reset_initial_rtt(initial_rtt);
985 }
986
987 data.pending_challenge = true;
990 data.pending.observed_address = self
991 .config
992 .address_discovery_role
993 .should_report(&self.peer_params.address_discovery_role);
994
995 let path = vacant_entry.insert(PathState { data, prev: None });
996
997 #[cfg(test)]
998 let mut pn_space = match self.config.deterministic_packet_numbers {
999 true => spaces::PacketNumberSpace::new_deterministic(now, SpaceId::Data),
1000 false => spaces::PacketNumberSpace::new(now, SpaceId::Data, &mut self.rng),
1001 };
1002 #[cfg(not(test))]
1003 let mut pn_space = spaces::PacketNumberSpace::new(now, SpaceId::Data, &mut self.rng);
1004 if let Some(pn) = pn {
1005 pn_space.dedup.insert(pn);
1006 }
1007 self.spaces[SpaceId::Data]
1008 .number_spaces
1009 .insert(path_id, pn_space);
1010 self.qlog.emit_tuple_assigned(path_id, network_path, now);
1011
1012 if !self.remote_cids.contains_key(&path_id) {
1016 debug!(%path_id, "Remote opened path without issuing CIDs");
1017 self.spaces[SpaceId::Data]
1018 .pending
1019 .path_cids_blocked
1020 .insert(path_id, VarInt(0));
1021 }
1024
1025 &mut path.data
1026 }
1027
1028 #[must_use]
1038 pub fn poll_transmit(
1039 &mut self,
1040 now: Instant,
1041 max_datagrams: NonZeroUsize,
1042 buf: &mut Vec<u8>,
1043 ) -> Option<Transmit> {
1044 let max_datagrams = match self.config.enable_segmentation_offload {
1045 false => NonZeroUsize::MIN,
1046 true => max_datagrams,
1047 };
1048
1049 let connection_close_pending = match self.state.as_type() {
1055 StateType::Drained => {
1056 for path in self.paths.values_mut() {
1057 path.data.app_limited = true;
1058 }
1059 return None;
1060 }
1061 StateType::Draining | StateType::Closed => {
1062 if !self.connection_close_pending {
1065 for path in self.paths.values_mut() {
1066 path.data.app_limited = true;
1067 }
1068 return None;
1069 }
1070 true
1071 }
1072 _ => false,
1073 };
1074
1075 if let Some(config) = &self.config.ack_frequency_config {
1077 let rtt = self
1078 .paths
1079 .values()
1080 .map(|p| p.data.rtt.get())
1081 .min()
1082 .expect("one path exists");
1083 self.spaces[SpaceId::Data].pending.ack_frequency = self
1084 .ack_frequency
1085 .should_send_ack_frequency(rtt, config, &self.peer_params)
1086 && self.highest_space == SpaceKind::Data
1087 && self.peer_supports_ack_frequency();
1088 }
1089
1090 let mut next_path_id = self.paths.first_entry().map(|e| *e.key());
1091 while let Some(path_id) = next_path_id {
1092 if !connection_close_pending
1093 && let Some(transmit) = self.poll_transmit_off_path(now, buf, path_id)
1094 {
1095 #[cfg(test)]
1096 {
1097 self.partial_stats.transmits_tx += 1;
1098 }
1099 return Some(transmit);
1100 }
1101
1102 let info = self.scheduling_info(path_id);
1103 if let Some(transmit) = self.poll_transmit_on_path(
1104 now,
1105 buf,
1106 path_id,
1107 max_datagrams,
1108 &info,
1109 connection_close_pending,
1110 ) {
1111 #[cfg(test)]
1112 {
1113 self.partial_stats.transmits_tx += 1;
1114 }
1115 return Some(transmit);
1116 }
1117
1118 debug_assert!(
1121 buf.is_empty(),
1122 "nothing to send on path but buffer not empty"
1123 );
1124
1125 next_path_id = self.paths.keys().find(|i| **i > path_id).copied();
1126 }
1127
1128 debug_assert!(
1130 buf.is_empty(),
1131 "there was data in the buffer, but it was not sent"
1132 );
1133
1134 if self.state.is_established() {
1135 let mut next_path_id = self.paths.first_entry().map(|e| *e.key());
1137 while let Some(path_id) = next_path_id {
1138 if let Some(transmit) = self.poll_transmit_mtu_probe(now, buf, path_id) {
1139 #[cfg(test)]
1140 {
1141 self.partial_stats.transmits_tx += 1;
1142 }
1143 return Some(transmit);
1144 }
1145 next_path_id = self.paths.keys().find(|i| **i > path_id).copied();
1146 }
1147 }
1148
1149 None
1150 }
1151
1152 fn scheduling_info(&self, path_id: PathId) -> PathSchedulingInfo {
1170 let have_validated_status_available_space = self.paths.iter().any(|(path_id, path)| {
1172 self.remote_cids.contains_key(path_id)
1173 && !self.abandoned_paths.contains(path_id)
1174 && path.data.validated
1175 && path.data.local_status() == PathStatus::Available
1176 });
1177
1178 let have_validated_space = self.paths.iter().any(|(path_id, path)| {
1180 self.remote_cids.contains_key(path_id)
1181 && !self.abandoned_paths.contains(path_id)
1182 && path.data.validated
1183 });
1184
1185 let is_handshaking = self.is_handshaking();
1186 let has_cids = self.remote_cids.contains_key(&path_id);
1187 let is_abandoned = self.abandoned_paths.contains(&path_id);
1188 let path_data = self.path_data(path_id);
1189 let validated = path_data.validated;
1190 let status = path_data.local_status();
1191
1192 let may_send_data = has_cids
1195 && !is_abandoned
1196 && if is_handshaking {
1197 true
1201 } else if !validated {
1202 false
1209 } else {
1210 match status {
1211 PathStatus::Available => {
1212 true
1214 }
1215 PathStatus::Backup => {
1216 !have_validated_status_available_space
1218 }
1219 }
1220 };
1221
1222 let may_send_close = has_cids
1227 && !is_abandoned
1228 && if !validated && have_validated_status_available_space {
1229 false
1231 } else {
1232 true
1234 };
1235
1236 let may_self_abandon = has_cids && validated && !have_validated_space;
1240
1241 PathSchedulingInfo {
1242 is_abandoned,
1243 may_send_data,
1244 may_send_close,
1245 may_self_abandon,
1246 }
1247 }
1248
1249 fn build_transmit(&mut self, path_id: PathId, transmit: TransmitBuf<'_>) -> Transmit {
1250 debug_assert!(
1251 !transmit.is_empty(),
1252 "must not be called with an empty transmit buffer"
1253 );
1254
1255 let network_path = self.path_data(path_id).network_path;
1256 trace!(
1257 segment_size = transmit.segment_size(),
1258 last_datagram_len = transmit.len() % transmit.segment_size(),
1259 %network_path,
1260 "sending {} bytes in {} datagrams",
1261 transmit.len(),
1262 transmit.num_datagrams()
1263 );
1264 self.path_data_mut(path_id)
1265 .inc_total_sent(transmit.len() as u64);
1266
1267 self.path_stats
1268 .get_mut(path_id)
1269 .udp_tx
1270 .on_sent(transmit.num_datagrams() as u64, transmit.len());
1271
1272 Transmit {
1273 destination: network_path.remote,
1274 size: transmit.len(),
1275 ecn: if self.path_data(path_id).sending_ecn {
1276 Some(EcnCodepoint::Ect0)
1277 } else {
1278 None
1279 },
1280 segment_size: match transmit.num_datagrams() {
1281 1 => None,
1282 _ => Some(transmit.segment_size()),
1283 },
1284 src_ip: network_path.local_ip,
1285 }
1286 }
1287
1288 fn poll_transmit_off_path(
1290 &mut self,
1291 now: Instant,
1292 buf: &mut Vec<u8>,
1293 path_id: PathId,
1294 ) -> Option<Transmit> {
1295 if let Some(challenge) = self.send_prev_path_challenge(now, buf, path_id) {
1296 return Some(challenge);
1297 }
1298 if let Some(response) = self.send_off_path_path_response(now, buf, path_id) {
1299 return Some(response);
1300 }
1301 if let Some(challenge) = self.send_nat_traversal_path_challenge(now, buf, path_id) {
1302 return Some(challenge);
1303 }
1304 None
1305 }
1306
1307 #[must_use]
1314 fn poll_transmit_on_path(
1315 &mut self,
1316 now: Instant,
1317 buf: &mut Vec<u8>,
1318 path_id: PathId,
1319 max_datagrams: NonZeroUsize,
1320 scheduling_info: &PathSchedulingInfo,
1321 connection_close_pending: bool,
1322 ) -> Option<Transmit> {
1323 let Some(remote_cid) = self.remote_cids.get(&path_id).map(CidQueue::active) else {
1325 if !self.abandoned_paths.contains(&path_id) {
1326 debug!(%path_id, "no remote CIDs for path");
1327 }
1328 return None;
1329 };
1330
1331 let mut pad_datagram = PadDatagram::No;
1337
1338 let mut last_packet_number = None;
1342
1343 let mut send_blocked = false;
1346 let mut cwnd_blocked = false;
1349
1350 let path = self.path_data(path_id);
1351
1352 let controller_metrics = path.congestion.metrics();
1358 let max_datagrams = match controller_metrics.send_quantum {
1359 Some(send_quantum) => {
1360 let datagrams = send_quantum / u64::from(path.current_mtu());
1361 let datagrams = usize::try_from(datagrams).unwrap_or(usize::MAX);
1362 max_datagrams.min(NonZeroUsize::new(datagrams).unwrap_or(NonZeroUsize::MIN))
1363 }
1364 None => max_datagrams,
1365 };
1366
1367 let pmtu = path.current_mtu().into();
1369 let mut transmit = TransmitBuf::new(buf, max_datagrams, pmtu);
1370
1371 for space_id in SpaceId::iter() {
1373 if path_id != PathId::ZERO && space_id != SpaceId::Data {
1375 continue;
1376 }
1377 match self.poll_transmit_path_space(
1378 now,
1379 &mut transmit,
1380 path_id,
1381 space_id,
1382 remote_cid,
1383 scheduling_info,
1384 connection_close_pending,
1385 pad_datagram,
1386 ) {
1387 PollPathSpaceStatus::NothingToSend { path_blocked } => {
1388 match path_blocked {
1391 PathBlocked::No => {}
1392 PathBlocked::AntiAmplification => {
1393 send_blocked = true;
1394 }
1395 PathBlocked::Congestion => {
1396 cwnd_blocked = true;
1397 send_blocked = true;
1398 }
1399 PathBlocked::Pacing => send_blocked = true,
1400 }
1401 }
1402 PollPathSpaceStatus::WrotePacket {
1403 last_packet_number: pn,
1404 pad_datagram: pad,
1405 } => {
1406 debug_assert!(!transmit.is_empty(), "transmit must contain packets");
1407 last_packet_number = Some(pn);
1408 pad_datagram = pad;
1409 continue;
1414 }
1415 PollPathSpaceStatus::Send {
1416 last_packet_number: pn,
1417 } => {
1418 debug_assert!(!transmit.is_empty(), "transmit must contain packets");
1419 last_packet_number = Some(pn);
1420 break;
1421 }
1422 }
1423 }
1424
1425 if last_packet_number.is_some() || send_blocked {
1426 self.qlog.emit_recovery_metrics(
1427 path_id,
1428 &mut self
1429 .paths
1430 .get_mut(&path_id)
1431 .expect("path_id was iterated from self.paths above")
1432 .data,
1433 now,
1434 );
1435 }
1436
1437 let path = self.path_data_mut(path_id);
1438
1439 path.app_limited = last_packet_number.is_none() && !send_blocked;
1440
1441 if path.app_limited {
1442 let in_flight = path.in_flight.bytes;
1445 path.congestion.on_app_limited(in_flight);
1446 }
1447 if cwnd_blocked {
1448 path.congestion.on_cwnd_limited();
1449 }
1450
1451 match last_packet_number {
1452 Some(last_packet_number) => {
1453 self.path_data_mut(path_id).congestion.on_sent(
1456 now,
1457 transmit.len() as u64,
1458 last_packet_number,
1459 );
1460 Some(self.build_transmit(path_id, transmit))
1461 }
1462 None => None,
1463 }
1464 }
1465
1466 #[must_use]
1468 fn poll_transmit_path_space(
1469 &mut self,
1470 now: Instant,
1471 transmit: &mut TransmitBuf<'_>,
1472 path_id: PathId,
1473 space_id: SpaceId,
1474 remote_cid: ConnectionId,
1475 scheduling_info: &PathSchedulingInfo,
1476 connection_close_pending: bool,
1478 mut pad_datagram: PadDatagram,
1480 ) -> PollPathSpaceStatus {
1481 let mut last_packet_number = None;
1484
1485 loop {
1501 let max_packet_size = if transmit.datagram_remaining_mut() > 0 {
1503 transmit.datagram_remaining_mut()
1505 } else {
1506 transmit.segment_size()
1508 };
1509 let can_send =
1510 self.space_can_send(space_id, path_id, max_packet_size, connection_close_pending);
1511 let needs_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0;
1512 let space_will_send = {
1513 if scheduling_info.is_abandoned {
1514 scheduling_info.may_self_abandon
1519 && self.spaces[space_id]
1520 .pending
1521 .path_abandon
1522 .contains_key(&path_id)
1523 } else if can_send.close && scheduling_info.may_send_close {
1524 true
1526 } else if needs_loss_probe || can_send.space_specific {
1527 true
1530 } else {
1531 !can_send.is_empty() && scheduling_info.may_send_data
1534 }
1535 };
1536
1537 if !space_will_send {
1538 return match last_packet_number {
1541 Some(pn) => PollPathSpaceStatus::WrotePacket {
1542 last_packet_number: pn,
1543 pad_datagram,
1544 },
1545 None => {
1546 if self.crypto_state.has_keys(space_id.encryption_level())
1548 || (space_id == SpaceId::Data
1549 && self.crypto_state.has_keys(EncryptionLevel::ZeroRtt))
1550 {
1551 trace!(?space_id, %path_id, "nothing to send in space");
1552 }
1553 PollPathSpaceStatus::NothingToSend {
1554 path_blocked: PathBlocked::No,
1555 }
1556 }
1557 };
1558 }
1559
1560 if transmit.datagram_remaining_mut() == 0 {
1564 let path_blocked =
1565 self.path_congestion_check(space_id, path_id, transmit, &can_send, now);
1566 if path_blocked != PathBlocked::No {
1567 return match last_packet_number {
1569 Some(pn) => PollPathSpaceStatus::WrotePacket {
1570 last_packet_number: pn,
1571 pad_datagram,
1572 },
1573 None => PollPathSpaceStatus::NothingToSend { path_blocked },
1574 };
1575 }
1576
1577 if transmit.num_datagrams() >= transmit.max_datagrams().get() {
1580 return match last_packet_number {
1583 Some(pn) => PollPathSpaceStatus::WrotePacket {
1584 last_packet_number: pn,
1585 pad_datagram,
1586 },
1587 None => PollPathSpaceStatus::NothingToSend { path_blocked },
1588 };
1589 }
1590
1591 if needs_loss_probe {
1592 let request_immediate_ack =
1594 space_id == SpaceId::Data && self.peer_supports_ack_frequency();
1595 self.spaces[space_id].queue_tail_loss_probe(
1596 path_id,
1597 request_immediate_ack,
1598 &self.streams,
1599 );
1600
1601 self.spaces[space_id].for_path(path_id).loss_probes -= 1; transmit.start_new_datagram_with_size(cmp::min(
1607 usize::from(INITIAL_MTU),
1608 transmit.segment_size(),
1609 ));
1610 } else {
1611 transmit.start_new_datagram();
1612 }
1613 trace!(count = transmit.num_datagrams(), "new datagram started");
1614
1615 pad_datagram = PadDatagram::No;
1617 }
1618
1619 if transmit.datagram_start_offset() < transmit.len() {
1622 debug_assert!(transmit.datagram_remaining_mut() >= MIN_PACKET_SPACE);
1623 }
1624
1625 if self.crypto_state.has_keys(EncryptionLevel::Initial)
1630 && space_id == SpaceId::Handshake
1631 && self.side.is_client()
1632 {
1633 self.discard_space(now, SpaceKind::Initial);
1636 }
1637 if let Some(ref mut prev) = self.crypto_state.prev_crypto {
1638 prev.update_unacked = false;
1639 }
1640
1641 let Some(mut builder) =
1642 PacketBuilder::new(now, space_id, path_id, remote_cid, transmit, self)
1643 else {
1644 return PollPathSpaceStatus::NothingToSend {
1651 path_blocked: PathBlocked::No,
1652 };
1653 };
1654 last_packet_number = Some(builder.packet_number);
1655
1656 if space_id == SpaceId::Initial
1657 && (self.side.is_client() || can_send.is_ack_eliciting() || needs_loss_probe)
1658 {
1659 pad_datagram |= PadDatagram::ToMinMtu;
1661 }
1662 if space_id == SpaceId::Data && self.config.pad_to_mtu {
1663 pad_datagram |= PadDatagram::ToSegmentSize;
1664 }
1665
1666 if scheduling_info.may_send_close && can_send.close {
1667 trace!("sending CONNECTION_CLOSE");
1668 let is_multipath_negotiated = self.is_multipath_negotiated();
1673 for path_id in self.spaces[space_id]
1674 .number_spaces
1675 .iter()
1676 .filter(|(_, pns)| !pns.pending_acks.ranges().is_empty())
1677 .map(|(&path_id, _)| path_id)
1678 .collect::<Vec<_>>()
1679 {
1680 Self::populate_acks(
1681 now,
1682 self.receiving_ecn,
1683 path_id,
1684 space_id,
1685 &mut self.spaces[space_id],
1686 is_multipath_negotiated,
1687 &mut builder,
1688 &mut self.path_stats.get_mut(path_id).frame_tx,
1689 self.crypto_state.has_keys(space_id.encryption_level()),
1690 );
1691 }
1692
1693 debug_assert!(
1701 builder.frame_space_remaining() > frame::ConnectionClose::SIZE_BOUND,
1702 "ACKs should leave space for ConnectionClose"
1703 );
1704 let stats = &mut self.path_stats.get_mut(path_id).frame_tx;
1705 if frame::ConnectionClose::SIZE_BOUND < builder.frame_space_remaining() {
1706 let max_frame_size = builder.frame_space_remaining();
1707 let close: Close = match self.state.as_type() {
1708 StateType::Closed => {
1709 let reason: Close =
1710 self.state.as_closed().expect("checked").clone().into();
1711 if space_id == SpaceId::Data || reason.is_transport_layer() {
1712 reason
1713 } else {
1714 TransportError::APPLICATION_ERROR("").into()
1715 }
1716 }
1717 StateType::Draining => TransportError::NO_ERROR("").into(),
1718 _ => unreachable!(
1719 "tried to make a close packet when the connection wasn't closed"
1720 ),
1721 };
1722 builder.write_frame(close.encoder(max_frame_size), stats);
1723 }
1724 let last_pn = builder.packet_number;
1725 builder.finish_and_track(now, self, path_id, pad_datagram);
1726 if space_id.kind() == self.highest_space {
1727 self.connection_close_pending = false;
1730 }
1731 return PollPathSpaceStatus::WrotePacket {
1744 last_packet_number: last_pn,
1745 pad_datagram,
1746 };
1747 }
1748
1749 self.populate_packet(now, space_id, path_id, scheduling_info, &mut builder);
1750
1751 debug_assert!(
1758 !(builder.sent_frames().is_ack_only(&self.streams)
1759 && !can_send.acks
1760 && (can_send.other || can_send.space_specific)
1761 && builder.buf.segment_size()
1762 == self.path_data(path_id).current_mtu() as usize
1763 && self.datagrams.outgoing.is_empty()),
1764 "SendableFrames was {can_send:?}, but only ACKs have been written"
1765 );
1766 if builder.sent_frames().requires_padding {
1767 pad_datagram |= PadDatagram::ToMinMtu;
1768 }
1769
1770 for path_id in builder.sent_frames().largest_acked.keys() {
1771 self.spaces[space_id]
1772 .for_path(*path_id)
1773 .pending_acks
1774 .acks_sent();
1775 self.timers.stop(
1776 Timer::PerPath(*path_id, PathTimer::MaxAckDelay),
1777 self.qlog.with_time(now),
1778 );
1779 }
1780
1781 let max_packet_size = builder
1787 .buf
1788 .datagram_remaining_mut()
1789 .saturating_sub(builder.predict_packet_end());
1790 if builder.can_coalesce
1793 && path_id == PathId::ZERO
1794 && let Some(next_space_id) = space_id.next()
1795 && max_packet_size > MIN_PACKET_SPACE
1796 && self
1797 .space_can_send(space_id, path_id, max_packet_size, connection_close_pending)
1798 .is_empty()
1799 && self.has_pending_packet(next_space_id, max_packet_size, connection_close_pending)
1800 {
1801 trace!("will coalesce with next packet");
1804 let last_pn = builder.packet_number;
1805 builder.finish_and_track(now, self, path_id, PadDatagram::No);
1806 return PollPathSpaceStatus::WrotePacket {
1809 last_packet_number: last_pn,
1810 pad_datagram,
1811 };
1812 } else {
1813 if builder.buf.num_datagrams() > 1 && matches!(pad_datagram, PadDatagram::No) {
1819 const MAX_PADDING: usize = 32;
1827 if builder.buf.datagram_remaining_mut()
1828 > builder.predict_packet_end() + MAX_PADDING
1829 {
1830 trace!(
1831 "GSO truncated by demand for {} padding bytes",
1832 builder.buf.datagram_remaining_mut() - builder.predict_packet_end()
1833 );
1834 let last_pn = builder.packet_number;
1835 builder.finish_and_track(now, self, path_id, PadDatagram::No);
1836 return PollPathSpaceStatus::Send {
1837 last_packet_number: last_pn,
1838 };
1839 }
1840
1841 builder.finish_and_track(now, self, path_id, PadDatagram::ToSegmentSize);
1844 } else {
1845 builder.finish_and_track(now, self, path_id, pad_datagram);
1846 }
1847
1848 if transmit.num_datagrams() == 1 {
1851 transmit.clip_segment_size();
1852 }
1853 }
1854 }
1855 }
1856
1857 fn poll_transmit_mtu_probe(
1858 &mut self,
1859 now: Instant,
1860 buf: &mut Vec<u8>,
1861 path_id: PathId,
1862 ) -> Option<Transmit> {
1863 let (active_cid, probe_size) = self.get_mtu_probe_data(now, path_id)?;
1864
1865 let mut transmit = TransmitBuf::new(buf, NonZeroUsize::MIN, probe_size as usize);
1867 transmit.start_new_datagram_with_size(probe_size as usize);
1868
1869 let mut builder =
1870 PacketBuilder::new(now, SpaceId::Data, path_id, active_cid, &mut transmit, self)?;
1871
1872 trace!(?probe_size, "writing MTUD probe");
1874 builder.write_frame(frame::Ping, &mut self.path_stats.get_mut(path_id).frame_tx);
1875
1876 if self.peer_supports_ack_frequency() {
1878 builder.write_frame(
1879 frame::ImmediateAck,
1880 &mut self.path_stats.get_mut(path_id).frame_tx,
1881 );
1882 }
1883
1884 builder.finish_and_track(now, self, path_id, PadDatagram::ToSize(probe_size));
1885
1886 self.path_stats.get_mut(path_id).sent_plpmtud_probes += 1;
1887
1888 Some(self.build_transmit(path_id, transmit))
1889 }
1890
1891 fn get_mtu_probe_data(&mut self, now: Instant, path_id: PathId) -> Option<(ConnectionId, u16)> {
1899 let active_cid = self.remote_cids.get(&path_id).map(CidQueue::active)?;
1900 let is_eligible = self.path_data(path_id).validated
1901 && !self.path_data(path_id).is_validating_path()
1902 && !self.abandoned_paths.contains(&path_id);
1903
1904 if !is_eligible {
1905 return None;
1906 }
1907 let next_pn = self.spaces[SpaceId::Data]
1908 .for_path(path_id)
1909 .peek_tx_number();
1910 let probe_size = self
1911 .path_data_mut(path_id)
1912 .mtud
1913 .poll_transmit(now, next_pn)?;
1914
1915 Some((active_cid, probe_size))
1916 }
1917
1918 fn has_pending_packet(
1935 &mut self,
1936 current_space_id: SpaceId,
1937 max_packet_size: usize,
1938 connection_close_pending: bool,
1939 ) -> bool {
1940 let mut space_id = current_space_id;
1941 loop {
1942 let can_send = self.space_can_send(
1943 space_id,
1944 PathId::ZERO,
1945 max_packet_size,
1946 connection_close_pending,
1947 );
1948 if !can_send.is_empty() {
1949 return true;
1950 }
1951 match space_id.next() {
1952 Some(next_space_id) => space_id = next_space_id,
1953 None => break,
1954 }
1955 }
1956 false
1957 }
1958
1959 fn path_congestion_check(
1961 &mut self,
1962 space_id: SpaceId,
1963 path_id: PathId,
1964 transmit: &TransmitBuf<'_>,
1965 can_send: &SendableFrames,
1966 now: Instant,
1967 ) -> PathBlocked {
1968 if self.side().is_server()
1974 && self
1975 .path_data(path_id)
1976 .anti_amplification_blocked(transmit.len() as u64 + 1)
1977 {
1978 trace!(?space_id, %path_id, "blocked by anti-amplification");
1979 return PathBlocked::AntiAmplification;
1980 }
1981
1982 let bytes_to_send = transmit.segment_size() as u64;
1985 let need_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0;
1986
1987 if can_send.other && !need_loss_probe && !can_send.close {
1988 let path = self.path_data(path_id);
1989 if path.in_flight.bytes + bytes_to_send >= path.congestion.window() {
1990 trace!(
1991 ?space_id,
1992 %path_id,
1993 in_flight=%path.in_flight.bytes,
1994 congestion_window=%path.congestion.window(),
1995 "blocked by congestion control",
1996 );
1997 return PathBlocked::Congestion;
1998 }
1999 }
2000
2001 if let Some(delay) = self.path_data_mut(path_id).pacing_delay(bytes_to_send, now) {
2003 let resume_time = now + delay;
2004 self.timers.set(
2005 Timer::PerPath(path_id, PathTimer::Pacing),
2006 resume_time,
2007 self.qlog.with_time(now),
2008 );
2009 trace!(?space_id, %path_id, ?delay, "blocked by pacing");
2012 return PathBlocked::Pacing;
2013 }
2014
2015 PathBlocked::No
2016 }
2017
2018 fn send_prev_path_challenge(
2023 &mut self,
2024 now: Instant,
2025 buf: &mut Vec<u8>,
2026 path_id: PathId,
2027 ) -> Option<Transmit> {
2028 let (prev_cid, prev_path) = self.paths.get_mut(&path_id)?.prev.as_mut()?;
2029 if !prev_path.pending_challenge {
2030 return None;
2031 };
2032 prev_path.pending_challenge = false;
2033 let token = self.rng.random();
2034 let network_path = prev_path.network_path;
2035 prev_path.record_path_challenge_sent(now, token, network_path);
2036
2037 debug_assert_eq!(
2038 self.highest_space,
2039 SpaceKind::Data,
2040 "PATH_CHALLENGE queued without 1-RTT keys"
2041 );
2042 let buf = &mut TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into());
2043 buf.start_new_datagram();
2044
2045 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, *prev_cid, buf, self)?;
2051 let challenge = frame::PathChallenge(token);
2052 let stats = &mut self.path_stats.get_mut(path_id).frame_tx;
2053 builder.write_frame_with_log_msg(challenge, stats, Some("validating previous path"));
2054
2055 builder.pad_to(MIN_INITIAL_SIZE);
2060
2061 builder.finish(self, now);
2062 self.path_stats
2063 .get_mut(path_id)
2064 .udp_tx
2065 .on_sent(1, buf.len());
2066
2067 trace!(
2068 dst = ?network_path.remote,
2069 src = ?network_path.local_ip,
2070 len = buf.len(),
2071 "sending prev_path off-path challenge",
2072 );
2073 Some(Transmit {
2074 destination: network_path.remote,
2075 size: buf.len(),
2076 ecn: None,
2077 segment_size: None,
2078 src_ip: network_path.local_ip,
2079 })
2080 }
2081
2082 fn send_off_path_path_response(
2083 &mut self,
2084 now: Instant,
2085 buf: &mut Vec<u8>,
2086 path_id: PathId,
2087 ) -> Option<Transmit> {
2088 let network_path = self
2089 .paths
2090 .get_mut(&path_id)
2091 .map(|state| state.data.network_path)?;
2092 let cid_queue = self.remote_cids.get_mut(&path_id)?;
2093 let pns = self.spaces[SpaceKind::Data].for_path(path_id);
2094 let (token, network_path) = pns.pending_path_responses.pop_off_path(network_path)?;
2095
2096 let cid = cid_queue.active();
2098
2099 let frame = frame::PathResponse(token);
2101
2102 let buf = &mut TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into());
2103 buf.start_new_datagram();
2104
2105 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, cid, buf, self)?;
2106 let stats = &mut self.path_stats.get_mut(path_id).frame_tx;
2107 builder.write_frame_with_log_msg(frame, stats, Some("(off-path)"));
2108
2109 if self
2116 .find_validated_path_on_network_path(network_path)
2117 .is_none()
2118 && self.n0_nat_traversal.client_side().is_ok()
2119 {
2120 let token = self.rng.random();
2121 let stats = &mut self.path_stats.get_mut(path_id).frame_tx;
2122 builder.write_frame(frame::PathChallenge(token), stats);
2123 let ip_port = (network_path.remote.ip(), network_path.remote.port());
2124 self.n0_nat_traversal.mark_probe_sent(ip_port, token);
2125 }
2126
2127 builder.pad_to(MIN_INITIAL_SIZE);
2130 builder.finish(self, now);
2131
2132 let size = buf.len();
2133 self.path_stats.get_mut(path_id).udp_tx.on_sent(1, size);
2134
2135 trace!(
2136 dst = ?network_path.remote,
2137 src = ?network_path.local_ip,
2138 len = buf.len(),
2139 "sending off-path PATH_RESPONSE",
2140 );
2141 Some(Transmit {
2142 destination: network_path.remote,
2143 size,
2144 ecn: None,
2145 segment_size: None,
2146 src_ip: network_path.local_ip,
2147 })
2148 }
2149
2150 fn send_nat_traversal_path_challenge(
2152 &mut self,
2153 now: Instant,
2154 buf: &mut Vec<u8>,
2155 path_id: PathId,
2156 ) -> Option<Transmit> {
2157 let remote = self.n0_nat_traversal.next_probe_addr()?;
2158
2159 if !self.paths.get(&path_id)?.data.validated {
2160 return None;
2162 }
2163
2164 let Some(cid) = self
2169 .remote_cids
2170 .get(&path_id)
2171 .map(|cid_queue| cid_queue.active())
2172 else {
2173 trace!(%path_id, "Not sending NAT traversal probe for path with no CIDs");
2174 return None;
2175 };
2176 let token = self.rng.random();
2177
2178 let frame = frame::PathChallenge(token);
2180
2181 let mut buf = TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into());
2182 buf.start_new_datagram();
2183
2184 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, cid, &mut buf, self)?;
2185 let stats = &mut self.path_stats.get_mut(path_id).frame_tx;
2186 builder.write_frame_with_log_msg(frame, stats, Some("(nat-traversal)"));
2187 builder.finish(self, now);
2190
2191 self.n0_nat_traversal.mark_probe_sent(remote, token);
2193
2194 let size = buf.len();
2195 self.path_stats.get_mut(path_id).udp_tx.on_sent(1, size);
2196
2197 trace!(dst = ?remote, len = buf.len(), "sending off-path NAT probe");
2198 Some(Transmit {
2199 destination: remote.into(),
2200 size,
2201 ecn: None,
2202 segment_size: None,
2203 src_ip: None,
2204 })
2205 }
2206
2207 fn space_can_send(
2215 &mut self,
2216 space_id: SpaceId,
2217 path_id: PathId,
2218 packet_size: usize,
2219 connection_close_pending: bool,
2220 ) -> SendableFrames {
2221 let space = &mut self.spaces[space_id];
2222 let space_has_crypto = self.crypto_state.has_keys(space_id.encryption_level());
2223
2224 if !space_has_crypto
2225 && (space_id != SpaceId::Data
2226 || !self.crypto_state.has_keys(EncryptionLevel::ZeroRtt)
2227 || self.side.is_server())
2228 {
2229 return SendableFrames::empty();
2231 }
2232
2233 let mut can_send = space.can_send(path_id, &self.streams);
2234
2235 if space_id == SpaceId::Data {
2237 let pn = space.for_path(path_id).peek_tx_number();
2238 let frame_space_1rtt =
2244 packet_size.saturating_sub(self.predict_1rtt_overhead(pn, path_id));
2245 can_send |= self.can_send_1rtt(path_id, frame_space_1rtt);
2246 }
2247
2248 can_send.close = connection_close_pending && space_has_crypto;
2249
2250 can_send
2251 }
2252
2253 pub fn handle_event(&mut self, event: ConnectionEvent) {
2259 use ConnectionEventInner::*;
2260 match event.0 {
2261 Datagram(DatagramConnectionEvent {
2262 now,
2263 network_path,
2264 path_id,
2265 ecn,
2266 first_decode,
2267 remaining,
2268 }) => {
2269 let span = trace_span!("pkt", %path_id);
2270 let _guard = span.enter();
2271
2272 if self.early_discard_packet(network_path, path_id) {
2273 return;
2275 }
2276
2277 let was_anti_amplification_blocked = self
2278 .path(path_id)
2279 .map(|path| path.anti_amplification_blocked(1))
2280 .unwrap_or(false);
2283
2284 let rx = &mut self.path_stats.get_mut(path_id).udp_rx;
2285 rx.datagrams += 1;
2286 rx.bytes += first_decode.len() as u64;
2287 let data_len = first_decode.len();
2288
2289 self.handle_decode(now, network_path, path_id, ecn, first_decode);
2290 if let Some(path) = self.path_mut(path_id) {
2295 path.inc_total_recvd(data_len as u64);
2296 }
2297
2298 if let Some(data) = remaining {
2299 self.path_stats.get_mut(path_id).udp_rx.bytes += data.len() as u64;
2300 self.handle_coalesced(now, network_path, path_id, ecn, data);
2301 }
2302
2303 if let Some(path) = self.paths.get_mut(&path_id) {
2304 self.qlog
2305 .emit_recovery_metrics(path_id, &mut path.data, now);
2306 }
2307
2308 if was_anti_amplification_blocked {
2309 self.set_loss_detection_timer(now, path_id);
2313 }
2314 }
2315 NewIdentifiers(ids, now, cid_len, cid_lifetime) => {
2316 let path_id = ids.first().map(|issued| issued.path_id).unwrap_or_default();
2317 debug_assert!(ids.iter().all(|issued| issued.path_id == path_id));
2318
2319 if self.abandoned_paths.contains(&path_id) {
2322 if !self.state.is_drained() {
2323 for issued in &ids {
2324 self.endpoint_events
2325 .push_back(EndpointEventInner::RetireConnectionId(
2326 now,
2327 path_id,
2328 issued.sequence,
2329 false,
2330 ));
2331 }
2332 }
2333 return;
2334 }
2335
2336 let cid_state = self
2337 .local_cid_state
2338 .entry(path_id)
2339 .or_insert_with(|| CidState::new(cid_len, cid_lifetime, now, 0));
2340 cid_state.new_cids(&ids, now);
2341
2342 ids.into_iter().rev().for_each(|frame| {
2343 self.spaces[SpaceId::Data].pending.new_cids.push(frame);
2344 });
2345 self.reset_cid_retirement(now);
2347 }
2348 }
2349 }
2350
2351 fn early_discard_packet(&mut self, network_path: FourTuple, path_id: PathId) -> bool {
2359 if self.is_handshaking() && path_id != PathId::ZERO {
2360 debug!(%network_path, %path_id, "discarding multipath packet during handshake");
2361 return true;
2362 }
2363
2364 if !self.paths.contains_key(&path_id) && self.abandoned_paths.contains(&path_id) {
2365 trace!(%path_id, "discarding packet for discarded path");
2366 return true;
2367 }
2368
2369 let peer_may_probe = self.peer_may_probe();
2370 let local_ip_may_migrate = self.local_ip_may_migrate();
2371
2372 if let Some(known_path) = self.path_mut(path_id) {
2376 if network_path.remote != known_path.network_path.remote && !peer_may_probe {
2377 trace!(
2378 %path_id,
2379 %network_path,
2380 %known_path.network_path,
2381 "discarding packet from unrecognized peer"
2382 );
2383 return true;
2384 }
2385
2386 if known_path.network_path.local_ip.is_some()
2387 && network_path.local_ip.is_some()
2388 && known_path.network_path.local_ip != network_path.local_ip
2389 && !local_ip_may_migrate
2390 {
2391 trace!(
2392 %path_id,
2393 %network_path,
2394 %known_path.network_path,
2395 "discarding packet sent to incorrect interface"
2396 );
2397 return true;
2398 }
2399 }
2400 false
2401 }
2402
2403 fn peer_may_probe(&self) -> bool {
2414 match &self.side {
2415 ConnectionSide::Client { .. } => {
2416 if let Some(hs) = self.state.as_handshake() {
2417 hs.allow_server_migration
2418 } else {
2419 self.n0_nat_traversal.is_negotiated() && self.is_handshake_confirmed()
2420 }
2421 }
2422 ConnectionSide::Server { server_config } => {
2423 self.is_handshake_confirmed()
2424 && (server_config.migration || self.n0_nat_traversal.is_negotiated())
2425 }
2426 }
2427 }
2428
2429 fn peer_may_migrate(&self) -> bool {
2441 match &self.side {
2442 ConnectionSide::Server { server_config } => {
2443 server_config.migration && self.is_handshake_confirmed()
2444 }
2445 ConnectionSide::Client { .. } => false,
2446 }
2447 }
2448
2449 fn local_ip_may_migrate(&self) -> bool {
2462 (self.side.is_client() || self.n0_nat_traversal.is_negotiated())
2463 && self.is_handshake_confirmed()
2464 }
2465 pub fn handle_timeout(&mut self, now: Instant) {
2475 while let Some((timer, _time)) = self.timers.expire_before(now, &self.qlog) {
2476 let span = match timer {
2477 Timer::Conn(timer) => trace_span!("timeout", scope = "conn", ?timer),
2478 Timer::PerPath(path_id, timer) => {
2479 trace_span!("timer_fired", scope="path", %path_id, ?timer)
2480 }
2481 };
2482 let _guard = span.enter();
2483 trace!("timeout");
2484 match timer {
2485 Timer::Conn(timer) => match timer {
2486 ConnTimer::Close => {
2487 self.state.move_to_drained(None, &mut self.endpoint_events);
2488 }
2489 ConnTimer::Idle => {
2490 self.kill(ConnectionError::TimedOut);
2491 }
2492 ConnTimer::KeepAlive => {
2493 self.ping();
2494 }
2495 ConnTimer::KeyDiscard => {
2496 self.crypto_state.discard_temporary_keys();
2497 }
2498 ConnTimer::PushNewCid => {
2499 while let Some((path_id, when)) = self.next_cid_retirement() {
2500 if when > now {
2501 break;
2502 }
2503 match self.local_cid_state.get_mut(&path_id) {
2504 None => error!(%path_id, "No local CID state for path"),
2505 Some(cid_state) => {
2506 let num_new_cid = cid_state.on_cid_timeout().into();
2508 if !self.state.is_closed() {
2509 trace!(
2510 "push a new CID to peer RETIRE_PRIOR_TO field {}",
2511 cid_state.retire_prior_to()
2512 );
2513 self.endpoint_events.push_back(
2514 EndpointEventInner::NeedIdentifiers(
2515 path_id,
2516 now,
2517 num_new_cid,
2518 ),
2519 );
2520 }
2521 }
2522 }
2523 }
2524 }
2525 ConnTimer::NoAvailablePath => {
2526 if self.state.is_closed() || self.state.is_drained() {
2531 error!("no viable path timer fired, but connection already closing");
2534 } else {
2535 trace!("no viable path grace period expired, closing connection");
2536 let err = TransportError::NO_VIABLE_PATH(
2537 "last path abandoned, no new path opened",
2538 );
2539 self.close_common();
2540 self.set_close_timer(now);
2541 self.connection_close_pending = true;
2542 self.state.move_to_closed(err);
2543 }
2544 }
2545 ConnTimer::NatTraversalProbeRetry => {
2546 self.n0_nat_traversal.queue_retries(self.is_ipv6());
2547 if let Some(delay) =
2548 self.n0_nat_traversal.retry_delay(self.config.initial_rtt)
2549 {
2550 self.timers.set(
2551 Timer::Conn(ConnTimer::NatTraversalProbeRetry),
2552 now + delay,
2553 self.qlog.with_time(now),
2554 );
2555 trace!("re-queued NAT probes");
2556 } else {
2557 trace!("no more NAT probes remaining");
2558 }
2559 }
2560 },
2561 Timer::PerPath(path_id, timer) => {
2562 match timer {
2563 PathTimer::PathIdle => {
2564 if let Err(err) =
2565 self.close_path_inner(now, path_id, PathAbandonReason::TimedOut)
2566 {
2567 warn!(?err, "failed closing path");
2568 }
2569 }
2570
2571 PathTimer::PathKeepAlive => {
2572 self.ping_path(path_id).ok();
2573 }
2574 PathTimer::LossDetection => {
2575 self.on_loss_detection_timeout(now, path_id);
2576 if let Some(path) = self.paths.get_mut(&path_id) {
2577 self.qlog
2578 .emit_recovery_metrics(path_id, &mut path.data, now);
2579 } else {
2580 error!("LossDetection fired for unknown path");
2581 }
2582 }
2583 PathTimer::PathValidationFailed => {
2584 let Some(path) = self.paths.get_mut(&path_id) else {
2585 continue;
2586 };
2587 self.timers.stop(
2588 Timer::PerPath(path_id, PathTimer::PathChallengeLost),
2589 self.qlog.with_time(now),
2590 );
2591 debug!("path migration validation failed");
2592 path.data.reset_on_path_challenges();
2593 if let Some((_, prev)) = path.prev.take() {
2594 path.data = prev;
2595 self.set_loss_detection_timer(now, path_id);
2596 }
2597 }
2598 PathTimer::PathChallengeLost => {
2599 let Some(path) = self.paths.get_mut(&path_id) else {
2600 continue;
2601 };
2602 trace!(?path.data.lost_challenge_count, "path challenge deemed lost");
2603 path.data.pending_challenge = true;
2604 path.data.lost_challenge_count += 1;
2605 self.timers.set(
2606 Timer::PerPath(path_id, PathTimer::PathChallengeLost),
2607 now + path.data.on_path_challenge_pto(),
2608 self.qlog.with_time(now),
2609 );
2610 }
2611 PathTimer::Pacing => {}
2612 PathTimer::MaxAckDelay => {
2613 self.spaces[SpaceId::Data]
2615 .for_path(path_id)
2616 .pending_acks
2617 .on_max_ack_delay_timeout()
2618 }
2619 PathTimer::PathDrained => {
2620 self.timers.stop_per_path(path_id, self.qlog.with_time(now));
2623 if let Some(local_cid_state) = self.local_cid_state.remove(&path_id) {
2624 debug_assert!(!self.state.is_drained()); let (min_seq, max_seq) = local_cid_state.active_seq();
2626 for seq in min_seq..=max_seq {
2627 self.endpoint_events.push_back(
2628 EndpointEventInner::RetireConnectionId(
2629 now, path_id, seq, false,
2630 ),
2631 );
2632 }
2633 }
2634 self.discard_path(path_id, now);
2635 }
2636 }
2637 }
2638 }
2639 }
2640 }
2641
2642 pub fn close(&mut self, now: Instant, error_code: VarInt, reason: Bytes) {
2654 self.close_inner(
2655 now,
2656 Close::Application(frame::ApplicationClose { error_code, reason }),
2657 )
2658 }
2659
2660 fn close_inner(&mut self, now: Instant, reason: Close) {
2676 let was_closed = self.state.is_closed();
2677 if !was_closed {
2678 self.close_common();
2679 self.set_close_timer(now);
2680 self.connection_close_pending = true;
2681 self.state.move_to_closed_local(reason);
2682 }
2683 }
2684
2685 pub fn datagrams(&mut self) -> Datagrams<'_> {
2687 Datagrams { conn: self }
2688 }
2689
2690 pub fn stats(&mut self) -> ConnectionStats {
2692 let mut stats = self.partial_stats.clone();
2693
2694 for path_stats in self.path_stats.iter_stats() {
2695 stats += *path_stats;
2700 }
2701
2702 stats
2703 }
2704
2705 pub fn path_stats(&mut self, path_id: PathId) -> Option<PathStats> {
2707 let path = self.paths.get(&path_id)?;
2708 let mut stats = self.path_stats.get(path_id).unwrap_or_default();
2709 stats.rtt = path.data.rtt.get();
2710 stats.cwnd = path.data.congestion.window();
2711 stats.current_mtu = path.data.mtud.current_mtu();
2712 Some(stats)
2713 }
2714
2715 pub fn ping(&mut self) {
2719 for path_data in self.spaces[self.highest_space].number_spaces.values_mut() {
2722 path_data.pending_ping = true;
2723 }
2724 }
2725
2726 pub fn ping_path(&mut self, path: PathId) -> Result<(), ClosedPath> {
2730 let path_data = self.spaces[self.highest_space]
2731 .number_spaces
2732 .get_mut(&path)
2733 .ok_or(ClosedPath { _private: () })?;
2734 path_data.pending_ping = true;
2735 Ok(())
2736 }
2737
2738 pub fn force_key_update(&mut self) {
2742 if !self.state.is_established() {
2743 debug!("ignoring forced key update in illegal state");
2744 return;
2745 }
2746 if self.crypto_state.prev_crypto.is_some() {
2747 debug!("ignoring redundant forced key update");
2750 return;
2751 }
2752 self.crypto_state.update_keys(None, false);
2753 }
2754
2755 pub fn crypto_session(&self) -> &dyn crypto::Session {
2757 self.crypto_state.session.as_ref()
2758 }
2759
2760 pub fn is_handshaking(&self) -> bool {
2770 self.state.is_handshake()
2771 }
2772
2773 pub fn is_closed(&self) -> bool {
2784 self.state.is_closed()
2785 }
2786
2787 pub fn is_drained(&self) -> bool {
2792 self.state.is_drained()
2793 }
2794
2795 pub fn accepted_0rtt(&self) -> bool {
2799 self.crypto_state.accepted_0rtt
2800 }
2801
2802 pub fn has_0rtt(&self) -> bool {
2804 self.crypto_state.zero_rtt_enabled
2805 }
2806
2807 pub fn has_pending_retransmits(&self) -> bool {
2809 !self.spaces[SpaceId::Data].pending.is_empty(&self.streams)
2810 }
2811
2812 pub fn side(&self) -> Side {
2814 self.side.side()
2815 }
2816
2817 pub fn path_observed_address(&self, path_id: PathId) -> Result<Option<SocketAddr>, ClosedPath> {
2819 self.path(path_id)
2820 .map(|path_data| {
2821 path_data
2822 .last_observed_addr_report
2823 .as_ref()
2824 .map(|observed| observed.socket_addr())
2825 })
2826 .ok_or(ClosedPath { _private: () })
2827 }
2828
2829 pub fn rtt(&self, path_id: PathId) -> Option<Duration> {
2831 self.path(path_id).map(|d| d.rtt.get())
2832 }
2833
2834 pub fn congestion_state(&self, path_id: PathId) -> Option<&dyn Controller> {
2836 self.path(path_id).map(|d| d.congestion.as_ref())
2837 }
2838
2839 pub fn set_max_concurrent_streams(&mut self, dir: Dir, count: VarInt) {
2844 self.streams.set_max_concurrent(dir, count);
2845 let pending = &mut self.spaces[SpaceId::Data].pending;
2848 self.streams.queue_max_stream_id(pending);
2849 }
2850
2851 pub fn set_max_concurrent_paths(
2861 &mut self,
2862 now: Instant,
2863 count: NonZeroU32,
2864 ) -> Result<(), MultipathNotNegotiated> {
2865 if !self.is_multipath_negotiated() {
2866 return Err(MultipathNotNegotiated { _private: () });
2867 }
2868 self.max_concurrent_paths = count;
2869
2870 let in_use_count = self
2871 .local_max_path_id
2872 .next()
2873 .saturating_sub(self.abandoned_paths.len())
2874 .as_u32();
2875 let extra_needed = count.get().saturating_sub(in_use_count);
2876 let new_max_path_id = self.local_max_path_id.saturating_add(extra_needed);
2877
2878 self.set_max_path_id(now, new_max_path_id);
2879
2880 Ok(())
2881 }
2882
2883 fn set_max_path_id(&mut self, now: Instant, max_path_id: PathId) {
2885 if max_path_id <= self.local_max_path_id {
2886 return;
2887 }
2888
2889 self.local_max_path_id = max_path_id;
2890 self.spaces[SpaceId::Data].pending.max_path_id = true;
2891
2892 self.issue_first_path_cids(now);
2893 }
2894
2895 pub fn max_concurrent_streams(&self, dir: Dir) -> u64 {
2902 self.streams.max_concurrent(dir)
2903 }
2904
2905 pub fn set_send_window(&mut self, send_window: u64) {
2907 self.streams.set_send_window(send_window);
2908 }
2909
2910 pub fn set_receive_window(&mut self, receive_window: VarInt) {
2912 if self.streams.set_receive_window(receive_window) {
2913 self.spaces[SpaceId::Data].pending.max_data = true;
2914 }
2915 }
2916
2917 pub fn is_multipath_negotiated(&self) -> bool {
2922 !self.is_handshaking()
2923 && self.config.max_concurrent_multipath_paths.is_some()
2924 && self.peer_params.initial_max_path_id.is_some()
2925 }
2926
2927 fn on_ack_received(
2928 &mut self,
2929 now: Instant,
2930 space: SpaceId,
2931 ack: frame::Ack,
2932 ) -> Result<(), TransportError> {
2933 let path = PathId::ZERO;
2935 self.inner_on_ack_received(now, space, path, ack)
2936 }
2937
2938 fn on_path_ack_received(
2939 &mut self,
2940 now: Instant,
2941 space: SpaceId,
2942 path_ack: frame::PathAck,
2943 ) -> Result<(), TransportError> {
2944 let (ack, path) = path_ack.into_ack();
2945 self.inner_on_ack_received(now, space, path, ack)
2946 }
2947
2948 fn inner_on_ack_received(
2950 &mut self,
2951 now: Instant,
2952 space: SpaceId,
2953 path: PathId,
2954 ack: frame::Ack,
2955 ) -> Result<(), TransportError> {
2956 if !self.spaces[space].number_spaces.contains_key(&path) {
2957 if self.abandoned_paths.contains(&path) {
2958 trace!("silently ignoring PATH_ACK on discarded path");
2964 return Ok(());
2965 } else {
2966 return Err(TransportError::PROTOCOL_VIOLATION(
2967 "received PATH_ACK with path ID never used",
2968 ));
2969 }
2970 }
2971 if ack.largest >= self.spaces[space].for_path(path).next_packet_number {
2972 return Err(TransportError::PROTOCOL_VIOLATION("unsent packet acked"));
2973 }
2974 let new_largest_pn = {
2976 let space = &mut self.spaces[space].for_path(path);
2977 if space
2978 .largest_acked_packet_pn
2979 .is_none_or(|pn| ack.largest > pn)
2980 {
2981 space.largest_acked_packet_pn = Some(ack.largest);
2982 if let Some(info) = space.sent_packets.get(ack.largest) {
2983 space.largest_acked_packet_send_time = info.time_sent;
2987 }
2988 Some(ack.largest)
2989 } else {
2990 None
2991 }
2992 };
2993
2994 if self.detect_spurious_loss(&ack, space, path) {
2995 self.path_stats.get_mut(path).spurious_congestion_events += 1;
2996 self.path_data_mut(path)
2997 .congestion
2998 .on_spurious_congestion_event();
2999 }
3000
3001 let mut newly_acked: ArrayRangeSet = ArrayRangeSet::new();
3003 for range in ack.iter() {
3004 self.spaces[space].for_path(path).check_ack(range.clone())?;
3005 for (pn, _) in self.spaces[space]
3006 .for_path(path)
3007 .sent_packets
3008 .iter_range(range)
3009 {
3010 newly_acked.insert_one(pn);
3011 }
3012 }
3013
3014 if newly_acked.is_empty() {
3015 return Ok(());
3016 }
3017
3018 let mut ack_eliciting_acked = false;
3019 for packet in newly_acked.elts() {
3020 if let Some(info) = self.spaces[space].for_path(path).take(packet) {
3021 for (acked_path_id, acked_pn) in info.largest_acked.iter() {
3022 if let Some(pns) = self.spaces[space].path_space_mut(*acked_path_id) {
3028 pns.pending_acks.subtract_below(*acked_pn);
3029 }
3030 }
3031 ack_eliciting_acked |= info.ack_eliciting;
3032
3033 let path_data = self.path_data_mut(path);
3035 let mtu_updated = path_data.mtud.on_acked(space.kind(), packet, info.size);
3036 if mtu_updated {
3037 path_data
3038 .congestion
3039 .on_mtu_update(path_data.mtud.current_mtu());
3040 }
3041
3042 self.ack_frequency.on_acked(path, packet);
3045
3046 self.on_packet_acked(now, path, space.kind(), packet, info);
3047 }
3048 }
3049
3050 let largest_ackd = self.spaces[space].for_path(path).largest_acked_packet_pn;
3051 let path_data = self.path_data_mut(path);
3052 let app_limited = path_data.app_limited;
3053 let in_flight = path_data.in_flight.bytes;
3054
3055 path_data
3056 .congestion
3057 .on_end_acks(now, in_flight, app_limited, largest_ackd);
3058
3059 if new_largest_pn.is_some() && ack_eliciting_acked {
3060 let ack_delay = if space != SpaceId::Data {
3061 Duration::from_micros(0)
3062 } else {
3063 cmp::min(
3064 self.ack_frequency.peer_max_ack_delay,
3065 Duration::from_micros(ack.delay << self.peer_params.ack_delay_exponent.0),
3066 )
3067 };
3068 let rtt = now.saturating_duration_since(
3069 self.spaces[space]
3070 .for_path(path)
3071 .largest_acked_packet_send_time,
3072 );
3073
3074 let next_pn = self.spaces[space].for_path(path).next_packet_number;
3075 let path_data = self.path_data_mut(path);
3076 path_data.rtt.update(ack_delay, rtt);
3078 if path_data.first_packet_after_rtt_sample.is_none() {
3079 path_data.first_packet_after_rtt_sample = Some((space.kind(), next_pn));
3080 }
3081 }
3082
3083 self.detect_lost_packets(now, space, path, true);
3085
3086 if self.peer_completed_handshake_address_validation() {
3091 self.path_data_mut(path).pto_count = 0;
3092 }
3093
3094 if self.path_data(path).sending_ecn {
3099 if let Some(ecn) = ack.ecn {
3100 if let Some(largest_sent_pn) = new_largest_pn {
3105 let sent = self.spaces[space]
3106 .for_path(path)
3107 .largest_acked_packet_send_time;
3108 self.process_ecn(
3109 now,
3110 space,
3111 path,
3112 newly_acked.range_count() as u64,
3113 ecn,
3114 sent,
3115 largest_sent_pn,
3116 );
3117 }
3118 } else {
3119 debug!("ECN not acknowledged by peer");
3122 self.path_data_mut(path).sending_ecn = false;
3123 }
3124 }
3125
3126 self.set_loss_detection_timer(now, path);
3127 Ok(())
3128 }
3129
3130 fn detect_spurious_loss(&mut self, ack: &frame::Ack, space: SpaceId, path: PathId) -> bool {
3131 let lost_packets = &mut self.spaces[space].for_path(path).lost_packets;
3132
3133 if lost_packets.is_empty() {
3134 return false;
3135 }
3136
3137 for range in ack.iter() {
3138 let spurious_losses: Vec<u64> = lost_packets
3139 .iter_range(range.clone())
3140 .map(|(pn, _info)| pn)
3141 .collect();
3142
3143 for pn in spurious_losses {
3144 lost_packets.remove(pn);
3145 }
3146 }
3147
3148 lost_packets.is_empty()
3153 }
3154
3155 fn drain_lost_packets(&mut self, now: Instant, space: SpaceId, path: PathId) {
3160 let two_pto = 2 * self.path_data(path).rtt.pto_base();
3161
3162 let lost_packets = &mut self.spaces[space].for_path(path).lost_packets;
3163 lost_packets.retain(|_pn, info| now.saturating_duration_since(info.time_sent) <= two_pto);
3164 }
3165
3166 fn process_ecn(
3168 &mut self,
3169 now: Instant,
3170 space: SpaceId,
3171 path: PathId,
3172 newly_acked_pn: u64,
3173 ecn: frame::EcnCounts,
3174 largest_sent_time: Instant,
3175 largest_sent_pn: u64,
3176 ) {
3177 match self.spaces[space]
3178 .for_path(path)
3179 .detect_ecn(newly_acked_pn, ecn)
3180 {
3181 Err(e) => {
3182 debug!("halting ECN due to verification failure: {}", e);
3183
3184 self.path_data_mut(path).sending_ecn = false;
3185 self.spaces[space].for_path(path).ecn_feedback = frame::EcnCounts::ZERO;
3188 }
3189 Ok(false) => {}
3190 Ok(true) => {
3191 self.path_stats.get_mut(path).congestion_events += 1;
3192 self.path_data_mut(path)
3193 .congestion
3194 .on_congestion_event_space(
3195 now,
3196 largest_sent_time,
3197 false,
3198 true,
3199 0,
3200 PacketId {
3201 space: space.kind(),
3202 number: largest_sent_pn,
3203 },
3204 );
3205 }
3206 }
3207 }
3208
3209 fn on_packet_acked(
3212 &mut self,
3213 now: Instant,
3214 path_id: PathId,
3215 space: SpaceKind,
3216 pn: u64,
3217 info: SentPacket,
3218 ) {
3219 let path = self.path_data_mut(path_id);
3220 let app_limited = path.app_limited;
3221 path.remove_in_flight(&info);
3222 if info.ack_eliciting && info.path_generation == path.generation() {
3223 let rtt = path.rtt;
3227 let packet = PacketId { space, number: pn };
3228 path.congestion.on_packet_space_acked(
3229 now,
3230 info.time_sent,
3231 info.size.into(),
3232 packet,
3233 app_limited,
3234 &rtt,
3235 );
3236 }
3237
3238 if let Some(retransmits) = info.retransmits.get() {
3240 for (id, _) in retransmits.reset_stream.iter() {
3241 self.streams.reset_acked(*id);
3242 }
3243 }
3244
3245 for frame in info.stream_frames {
3246 self.streams.received_ack_of(frame);
3247 }
3248 }
3249
3250 fn set_key_discard_timer(&mut self, now: Instant, space: SpaceKind) {
3251 let start = if self.crypto_state.has_keys(EncryptionLevel::ZeroRtt) {
3252 now
3253 } else {
3254 self.crypto_state
3255 .prev_crypto
3256 .as_ref()
3257 .expect("no previous keys")
3258 .end_packet
3259 .as_ref()
3260 .expect("update not acknowledged yet")
3261 .1
3262 };
3263
3264 self.timers.set(
3266 Timer::Conn(ConnTimer::KeyDiscard),
3267 start + self.max_pto_for_space(space) * 3,
3268 self.qlog.with_time(now),
3269 );
3270 }
3271
3272 fn on_loss_detection_timeout(&mut self, now: Instant, path_id: PathId) {
3285 if let Some((_, pn_space)) = self.loss_time_and_space(path_id) {
3286 self.detect_lost_packets(now, pn_space, path_id, false);
3288 self.set_loss_detection_timer(now, path_id);
3289 return;
3290 }
3291
3292 let Some((_, space)) = self.pto_time_and_space(now, path_id) else {
3293 debug!(%path_id, "PTO expired while unset");
3294 return;
3295 };
3296 trace!(
3297 in_flight = self.path_data(path_id).in_flight.bytes,
3298 count = self.path_data(path_id).pto_count,
3299 ?space,
3300 %path_id,
3301 "PTO fired"
3302 );
3303
3304 let count = match self.path_data(path_id).in_flight.ack_eliciting {
3305 0 => {
3308 debug_assert!(!self.peer_completed_handshake_address_validation());
3309 1
3310 }
3311 _ => 2,
3313 };
3314 let pns = self.spaces[space].for_path(path_id);
3315 pns.loss_probes = pns.loss_probes.saturating_add(count);
3316 let path_data = self.path_data_mut(path_id);
3317 path_data.pto_count = path_data.pto_count.saturating_add(1);
3318 self.set_loss_detection_timer(now, path_id);
3319 }
3320
3321 fn detect_lost_packets(
3338 &mut self,
3339 now: Instant,
3340 pn_space: SpaceId,
3341 path_id: PathId,
3342 due_to_ack: bool,
3343 ) {
3344 let mut lost_packets = Vec::<u64>::new();
3345 let mut lost_mtu_probe = None;
3346 let mut in_persistent_congestion = false;
3347 let mut size_of_lost_packets = 0u64;
3348 self.spaces[pn_space].for_path(path_id).loss_time = None;
3349
3350 let path = self.path_data(path_id);
3353 let in_flight_mtu_probe = path.mtud.in_flight_mtu_probe();
3354 let loss_delay = path
3355 .rtt
3356 .conservative()
3357 .mul_f32(self.config.time_threshold)
3358 .max(TIMER_GRANULARITY);
3359 let first_packet_after_rtt_sample = path.first_packet_after_rtt_sample;
3360
3361 let largest_acked_packet_pn = self.spaces[pn_space]
3362 .for_path(path_id)
3363 .largest_acked_packet_pn
3364 .expect("detect_lost_packets only to be called if path received at least one ACK");
3365 let packet_threshold = self.config.packet_threshold as u64;
3366
3367 let congestion_period = self
3371 .pto(SpaceKind::Data, path_id)
3372 .saturating_mul(self.config.persistent_congestion_threshold);
3373 let mut persistent_congestion_start: Option<Instant> = None;
3374 let mut prev_packet = None;
3375 let space = self.spaces[pn_space].for_path(path_id);
3376
3377 for (packet, info) in space.sent_packets.iter_range(0..largest_acked_packet_pn) {
3378 if prev_packet != Some(packet.wrapping_sub(1)) {
3379 persistent_congestion_start = None;
3381 }
3382
3383 let packet_too_old = now.saturating_duration_since(info.time_sent) >= loss_delay;
3387 if packet_too_old || largest_acked_packet_pn >= packet + packet_threshold {
3388 if Some(packet) == in_flight_mtu_probe {
3390 lost_mtu_probe = in_flight_mtu_probe;
3393 } else {
3394 lost_packets.push(packet);
3395 size_of_lost_packets += info.size as u64;
3396 if info.ack_eliciting && due_to_ack {
3397 match persistent_congestion_start {
3398 Some(start) if info.time_sent - start > congestion_period => {
3401 in_persistent_congestion = true;
3402 }
3403 None if first_packet_after_rtt_sample
3405 .is_some_and(|x| x < (pn_space.kind(), packet)) =>
3406 {
3407 persistent_congestion_start = Some(info.time_sent);
3408 }
3409 _ => {}
3410 }
3411 }
3412 }
3413 } else {
3414 if space.loss_time.is_none() {
3416 space.loss_time = Some(info.time_sent + loss_delay);
3419 }
3420 persistent_congestion_start = None;
3421 }
3422
3423 prev_packet = Some(packet);
3424 }
3425
3426 self.handle_lost_packets(
3427 pn_space,
3428 path_id,
3429 now,
3430 lost_packets,
3431 lost_mtu_probe,
3432 loss_delay,
3433 in_persistent_congestion,
3434 size_of_lost_packets,
3435 );
3436 }
3437
3438 fn discard_path(&mut self, path_id: PathId, now: Instant) {
3440 trace!(%path_id, "dropping path state");
3441 let path = self.path_data(path_id);
3442 let in_flight_mtu_probe = path.mtud.in_flight_mtu_probe();
3443
3444 let mut size_of_lost_packets = 0u64; let lost_pns: Vec<_> = self.spaces[SpaceId::Data]
3446 .for_path(path_id)
3447 .sent_packets
3448 .iter()
3449 .filter(|(pn, _info)| Some(*pn) != in_flight_mtu_probe)
3450 .map(|(pn, info)| {
3451 size_of_lost_packets += info.size as u64;
3452 pn
3453 })
3454 .collect();
3455
3456 if !lost_pns.is_empty() {
3457 trace!(
3458 %path_id,
3459 count = lost_pns.len(),
3460 lost_bytes = size_of_lost_packets,
3461 "packets lost on path abandon"
3462 );
3463 self.handle_lost_packets(
3464 SpaceId::Data,
3465 path_id,
3466 now,
3467 lost_pns,
3468 in_flight_mtu_probe,
3469 Duration::ZERO,
3470 false,
3471 size_of_lost_packets,
3472 );
3473 }
3474 let path_stats = self.path_stats(path_id).unwrap_or_default();
3477 self.path_stats.discard(&path_id);
3478 self.partial_stats += path_stats;
3479 self.paths.remove(&path_id);
3480 self.spaces[SpaceId::Data].number_spaces.remove(&path_id);
3481
3482 self.events.push_back(
3483 PathEvent::Discarded {
3484 id: path_id,
3485 path_stats: Box::new(path_stats),
3486 }
3487 .into(),
3488 );
3489 }
3490
3491 fn handle_lost_packets(
3492 &mut self,
3493 pn_space: SpaceId,
3494 path_id: PathId,
3495 now: Instant,
3496 lost_packets: Vec<u64>,
3497 lost_mtu_probe: Option<u64>,
3498 loss_delay: Duration,
3499 in_persistent_congestion: bool,
3500 size_of_lost_packets: u64,
3501 ) {
3502 debug_assert!(lost_packets.is_sorted(), "lost_packets must be sorted");
3503
3504 self.drain_lost_packets(now, pn_space, path_id);
3505
3506 if let Some(largest_lost) = lost_packets.last().cloned() {
3508 let old_bytes_in_flight = self.path_data_mut(path_id).in_flight.bytes;
3509 let largest_lost_sent = self.spaces[pn_space]
3510 .for_path(path_id)
3511 .sent_packets
3512 .get(largest_lost)
3513 .unwrap()
3514 .time_sent;
3515 let path_stats = self.path_stats.get_mut(path_id);
3516 path_stats.lost_packets += lost_packets.len() as u64;
3517 path_stats.lost_bytes += size_of_lost_packets;
3518 trace!(
3519 %path_id,
3520 count = lost_packets.len(),
3521 lost_bytes = size_of_lost_packets,
3522 "packets lost",
3523 );
3524
3525 for &packet in &lost_packets {
3526 let Some(info) = self.spaces[pn_space].for_path(path_id).take(packet) else {
3527 continue;
3528 };
3529 self.qlog
3530 .emit_packet_lost(packet, &info, loss_delay, pn_space.kind(), now);
3531 self.paths
3532 .get_mut(&path_id)
3533 .unwrap()
3534 .remove_in_flight(&info);
3535
3536 for frame in info.stream_frames {
3537 self.streams.retransmit(frame);
3538 }
3539 self.spaces[pn_space].pending |= info.retransmits;
3540 let path = self.path_data_mut(path_id);
3541 path.pending |= info.path_retransmits;
3542 path.mtud.on_non_probe_lost(packet, info.size);
3543 let lost = PacketId {
3544 space: pn_space.kind(),
3545 number: packet,
3546 };
3547 path.congestion.on_packet_space_lost(info.size, lost, now);
3548
3549 self.spaces[pn_space].for_path(path_id).lost_packets.insert(
3550 packet,
3551 LostPacket {
3552 time_sent: info.time_sent,
3553 },
3554 );
3555 }
3556
3557 let path = self.path_data_mut(path_id);
3558 if path.mtud.black_hole_detected(now) {
3559 path.congestion.on_mtu_update(path.mtud.current_mtu());
3560 if let Some(max_datagram_size) = self.datagrams().max_size()
3561 && self.datagrams.drop_oversized(max_datagram_size)
3562 && self.datagrams.send_blocked
3563 {
3564 self.datagrams.send_blocked = false;
3565 self.events.push_back(Event::DatagramsUnblocked);
3566 }
3567 self.path_stats.get_mut(path_id).black_holes_detected += 1;
3568 }
3569
3570 let lost_ack_eliciting =
3572 old_bytes_in_flight != self.path_data_mut(path_id).in_flight.bytes;
3573
3574 if lost_ack_eliciting {
3575 self.path_stats.get_mut(path_id).congestion_events += 1;
3576 self.path_data_mut(path_id)
3577 .congestion
3578 .on_congestion_event_space(
3579 now,
3580 largest_lost_sent,
3581 in_persistent_congestion,
3582 false,
3583 size_of_lost_packets,
3584 PacketId {
3585 space: pn_space.kind(),
3586 number: largest_lost,
3587 },
3588 );
3589 }
3590 }
3591
3592 if let Some(packet) = lost_mtu_probe {
3594 let info = self.spaces[SpaceId::Data]
3595 .for_path(path_id)
3596 .take(packet)
3597 .unwrap(); self.paths
3600 .get_mut(&path_id)
3601 .unwrap()
3602 .remove_in_flight(&info);
3603 self.path_data_mut(path_id).mtud.on_probe_lost();
3604 self.path_stats.get_mut(path_id).lost_plpmtud_probes += 1;
3605 }
3606 }
3607
3608 fn loss_time_and_space(&self, path_id: PathId) -> Option<(Instant, SpaceId)> {
3614 SpaceId::iter()
3615 .filter_map(|id| {
3616 self.spaces[id]
3617 .number_spaces
3618 .get(&path_id)
3619 .and_then(|pns| pns.loss_time)
3620 .map(|time| (time, id))
3621 })
3622 .min_by_key(|&(time, _)| time)
3623 }
3624
3625 fn pto_time_and_space(&mut self, now: Instant, path_id: PathId) -> Option<(Instant, SpaceId)> {
3633 let path = self.path(path_id)?;
3634 let pto_count = path.pto_count;
3635
3636 let idle = if self.state.is_handshake() {
3638 Some(self.config.handshake_idle_timeout)
3639 } else {
3640 path.idle_timeout.or(self.idle_timeout)
3641 };
3642
3643 let max_interval = if path.rtt.get() > SLOW_RTT_THRESHOLD {
3645 (path.rtt.get() * 3) / 2
3647 } else if let Some(idle) = idle
3648 && idle <= MIN_IDLE_FOR_FAST_PTO
3649 {
3650 MAX_PTO_FAST_INTERVAL
3653 } else {
3654 MAX_PTO_INTERVAL
3656 };
3657
3658 if path_id == PathId::ZERO
3659 && path.in_flight.ack_eliciting == 0
3660 && !self.peer_completed_handshake_address_validation()
3661 {
3662 let space = match self.highest_space {
3668 SpaceKind::Handshake => SpaceId::Handshake,
3669 _ => SpaceId::Initial,
3670 };
3671
3672 let backoff = 2u32.pow(path.pto_count.min(MAX_BACKOFF_EXPONENT));
3673 let duration = path.rtt.pto_base() * backoff;
3674 let duration = duration.min(max_interval);
3675 return Some((now + duration, space));
3676 }
3677
3678 let mut result = None;
3679 for space in SpaceId::iter() {
3680 let Some(pns) = self.spaces[space].number_spaces.get(&path_id) else {
3681 continue;
3682 };
3683
3684 if space == SpaceId::Data && !self.is_handshake_confirmed() {
3685 continue;
3689 }
3690
3691 if !pns.has_in_flight() {
3692 continue;
3693 }
3694
3695 let duration = {
3700 let max_ack_delay = if space == SpaceId::Data {
3701 self.ack_frequency.max_ack_delay_for_pto()
3702 } else {
3703 Duration::ZERO
3704 };
3705 let pto_base = path.rtt.pto_base() + max_ack_delay;
3706 let mut duration = pto_base;
3707 for i in 1..=pto_count {
3708 let exponential_duration = pto_base * 2u32.pow(i.min(MAX_BACKOFF_EXPONENT));
3709 let max_duration = duration + max_interval;
3710 duration = exponential_duration.min(max_duration);
3711 }
3712 duration
3713 };
3714
3715 let Some(last_ack_eliciting) = pns.time_of_last_ack_eliciting_packet else {
3716 continue;
3717 };
3718 let pto = last_ack_eliciting + duration;
3721 if result.is_none_or(|(earliest_pto, _)| pto < earliest_pto) {
3722 if path.anti_amplification_blocked(1) {
3723 continue;
3725 }
3726 if path.in_flight.ack_eliciting == 0 {
3727 continue;
3729 }
3730 result = Some((pto, space));
3731 }
3732 }
3733 result
3734 }
3735
3736 fn peer_completed_handshake_address_validation(&self) -> bool {
3738 if self.side.is_server() || self.state.is_closed() {
3739 return true;
3740 }
3741 self.spaces[SpaceId::Handshake]
3745 .path_space(PathId::ZERO)
3746 .and_then(|pns| pns.largest_acked_packet_pn)
3747 .is_some()
3748 || self.spaces[SpaceId::Data]
3749 .path_space(PathId::ZERO)
3750 .and_then(|pns| pns.largest_acked_packet_pn)
3751 .is_some()
3752 || (self.crypto_state.has_keys(EncryptionLevel::OneRtt)
3753 && !self.crypto_state.has_keys(EncryptionLevel::Handshake))
3754 }
3755
3756 fn set_loss_detection_timer(&mut self, now: Instant, path_id: PathId) {
3764 if self.state.is_closed() {
3765 return;
3769 }
3770
3771 if let Some((loss_time, _)) = self.loss_time_and_space(path_id) {
3772 self.timers.set(
3774 Timer::PerPath(path_id, PathTimer::LossDetection),
3775 loss_time,
3776 self.qlog.with_time(now),
3777 );
3778 return;
3779 }
3780
3781 if !self.abandoned_paths.contains(&path_id)
3784 && let Some((timeout, _)) = self.pto_time_and_space(now, path_id)
3785 {
3786 self.timers.set(
3787 Timer::PerPath(path_id, PathTimer::LossDetection),
3788 timeout,
3789 self.qlog.with_time(now),
3790 );
3791 } else {
3792 self.timers.stop(
3793 Timer::PerPath(path_id, PathTimer::LossDetection),
3794 self.qlog.with_time(now),
3795 );
3796 }
3797 }
3798
3799 fn max_pto_for_space(&self, space: SpaceKind) -> Duration {
3803 self.paths
3804 .keys()
3805 .map(|path_id| self.pto(space, *path_id))
3806 .max()
3807 .unwrap_or_else(|| {
3808 let rtt = self.config.initial_rtt;
3812 let max_ack_delay = match space {
3813 SpaceKind::Initial | SpaceKind::Handshake => Duration::ZERO,
3814 SpaceKind::Data => self.ack_frequency.max_ack_delay_for_pto(),
3815 };
3816 rtt + cmp::max(4 * (rtt / 2), TIMER_GRANULARITY) + max_ack_delay
3817 })
3818 }
3819
3820 fn pto(&self, space: SpaceKind, path_id: PathId) -> Duration {
3825 let max_ack_delay = match space {
3826 SpaceKind::Initial | SpaceKind::Handshake => Duration::ZERO,
3827 SpaceKind::Data => self.ack_frequency.max_ack_delay_for_pto(),
3828 };
3829 self.path_data(path_id).rtt.pto_base() + max_ack_delay
3830 }
3831
3832 fn on_packet_authenticated(
3833 &mut self,
3834 now: Instant,
3835 space_id: SpaceKind,
3836 path_id: PathId,
3837 ecn: Option<EcnCodepoint>,
3838 packet_number: Option<u64>,
3839 spin: bool,
3840 is_1rtt: bool,
3841 remote: &FourTuple,
3842 ) {
3843 let is_on_path = self
3850 .path_data(path_id)
3851 .network_path
3852 .is_probably_same_path(remote);
3853
3854 self.total_authed_packets += 1;
3855 self.reset_keep_alive(path_id, now);
3856 self.reset_idle_timeout(now, space_id, path_id);
3857 self.path_data_mut(path_id).permit_idle_reset = true;
3858
3859 if is_on_path {
3862 self.receiving_ecn |= ecn.is_some();
3863 if let Some(x) = ecn {
3864 let space = &mut self.spaces[space_id];
3865 space.for_path(path_id).ecn_counters += x;
3866
3867 if x.is_ce() {
3868 space
3869 .for_path(path_id)
3870 .pending_acks
3871 .set_immediate_ack_required();
3872 }
3873 }
3874 }
3875
3876 let Some(packet_number) = packet_number else {
3877 return;
3878 };
3879 match &self.side {
3880 ConnectionSide::Client { .. } => {
3881 if space_id == SpaceKind::Handshake
3885 && let Some(hs) = self.state.as_handshake_mut()
3886 {
3887 hs.allow_server_migration = false;
3888 }
3889 }
3890 ConnectionSide::Server { .. } => {
3891 if self.crypto_state.has_keys(EncryptionLevel::Initial)
3892 && space_id == SpaceKind::Handshake
3893 {
3894 self.discard_space(now, SpaceKind::Initial);
3897 }
3898 if self.crypto_state.has_keys(EncryptionLevel::ZeroRtt) && is_1rtt {
3899 self.set_key_discard_timer(now, space_id)
3901 }
3902 }
3903 }
3904 let space = self.spaces[space_id].for_path(path_id);
3905
3906 space.pending_acks.insert_one(packet_number, now);
3907 if packet_number >= space.largest_received_packet_number.unwrap_or_default() {
3908 space.largest_received_packet_number = Some(packet_number);
3909
3910 if is_on_path {
3912 self.spin = self.side.is_client() ^ spin;
3913 }
3914 }
3915 }
3916
3917 fn reset_idle_timeout(&mut self, now: Instant, space: SpaceKind, path_id: PathId) {
3922 let timeout = if self.state.is_closed() {
3924 None
3925 } else if self.state.is_handshake() {
3926 Some(self.config.handshake_idle_timeout)
3927 } else {
3928 self.idle_timeout
3929 };
3930 let deadline = timeout.and_then(|timeout| {
3932 now.checked_add(cmp::max(timeout, 3 * self.max_pto_for_space(space)))
3933 });
3934 match deadline {
3935 Some(deadline) => {
3936 self.timers.set(
3937 Timer::Conn(ConnTimer::Idle),
3938 deadline,
3939 self.qlog.with_time(now),
3940 );
3941 }
3942 None => self
3943 .timers
3944 .stop(Timer::Conn(ConnTimer::Idle), self.qlog.with_time(now)),
3945 }
3946
3947 self.rearm_path_max_idle_timer(now, space, path_id);
3949 }
3950
3951 fn reset_keep_alive(&mut self, path_id: PathId, now: Instant) {
3953 if !self.state.is_established() {
3954 return;
3955 }
3956
3957 if let Some(interval) = self.config.keep_alive_interval {
3958 self.timers.set(
3959 Timer::Conn(ConnTimer::KeepAlive),
3960 now + interval,
3961 self.qlog.with_time(now),
3962 );
3963 }
3964
3965 if let Some(interval) = self.path_data(path_id).keep_alive {
3966 self.timers.set(
3967 Timer::PerPath(path_id, PathTimer::PathKeepAlive),
3968 now + interval,
3969 self.qlog.with_time(now),
3970 );
3971 }
3972 }
3973
3974 fn reset_cid_retirement(&mut self, now: Instant) {
3976 if let Some((_path, t)) = self.next_cid_retirement() {
3977 self.timers.set(
3978 Timer::Conn(ConnTimer::PushNewCid),
3979 t,
3980 self.qlog.with_time(now),
3981 );
3982 }
3983 }
3984
3985 fn next_cid_retirement(&self) -> Option<(PathId, Instant)> {
3987 self.local_cid_state
3988 .iter()
3989 .filter_map(|(path_id, cid_state)| cid_state.next_timeout().map(|t| (*path_id, t)))
3990 .min_by_key(|(_path_id, timeout)| *timeout)
3991 }
3992
3993 pub(crate) fn handle_first_packet(
3998 &mut self,
3999 now: Instant,
4000 network_path: FourTuple,
4001 ecn: Option<EcnCodepoint>,
4002 packet_number: u64,
4003 packet: InitialPacket,
4004 remaining: Option<BytesMut>,
4005 ) -> Result<(), ConnectionError> {
4006 let span = trace_span!("first recv");
4007 let _guard = span.enter();
4008 debug_assert!(self.side.is_server());
4009 let len = packet.header_data.len() + packet.payload.len();
4010 let path_id = PathId::ZERO;
4011 self.path_data_mut(path_id).total_recvd = len as u64;
4012
4013 if let Some(hs) = self.state.as_handshake_mut() {
4014 hs.expected_token = packet.header.token.clone();
4015 } else {
4016 unreachable!("first packet must be delivered in Handshake state");
4017 }
4018
4019 self.on_packet_authenticated(
4021 now,
4022 SpaceKind::Initial,
4023 path_id,
4024 ecn,
4025 Some(packet_number),
4026 false,
4027 false,
4028 &network_path,
4029 );
4030
4031 let packet: Packet = packet.into();
4032
4033 let mut qlog = QlogRecvPacket::new(len);
4034 qlog.header(&packet.header, Some(packet_number), path_id);
4035
4036 self.process_decrypted_packet(
4037 now,
4038 network_path,
4039 path_id,
4040 Some(packet_number),
4041 packet,
4042 &mut qlog,
4043 )?;
4044 self.qlog.emit_packet_received(qlog, now);
4045 if let Some(data) = remaining {
4046 self.handle_coalesced(now, network_path, path_id, ecn, data);
4047 }
4048
4049 self.qlog.emit_recovery_metrics(
4050 path_id,
4051 &mut self
4052 .paths
4053 .get_mut(&path_id)
4054 .expect("path_id was supplied by the caller for an active path")
4055 .data,
4056 now,
4057 );
4058
4059 Ok(())
4060 }
4061
4062 fn init_0rtt(&mut self, now: Instant) {
4063 let Some((header, packet)) = self.crypto_state.session.early_crypto() else {
4064 return;
4065 };
4066 if self.side.is_client() {
4067 match self.crypto_state.session.transport_parameters() {
4068 Ok(params) => {
4069 let params = params
4070 .expect("crypto layer didn't supply transport parameters with ticket");
4071 let params = TransportParameters {
4073 initial_src_cid: None,
4074 original_dst_cid: None,
4075 preferred_address: None,
4076 retry_src_cid: None,
4077 stateless_reset_token: None,
4078 min_ack_delay: None,
4079 ack_delay_exponent: TransportParameters::default().ack_delay_exponent,
4080 max_ack_delay: TransportParameters::default().max_ack_delay,
4081 initial_max_path_id: None,
4082 ..params
4083 };
4084 self.set_peer_params(params);
4085 self.qlog.emit_peer_transport_params_restored(self, now);
4086 }
4087 Err(e) => {
4088 error!("session ticket has malformed transport parameters: {}", e);
4089 return;
4090 }
4091 }
4092 }
4093 trace!("0-RTT enabled");
4094 self.crypto_state.enable_zero_rtt(header, packet);
4095 }
4096
4097 fn read_crypto(
4098 &mut self,
4099 space: SpaceId,
4100 crypto: &frame::Crypto,
4101 payload_len: usize,
4102 ) -> Result<(), TransportError> {
4103 let expected = if !self.state.is_handshake() {
4104 SpaceId::Data
4105 } else if self.highest_space == SpaceKind::Initial {
4106 SpaceId::Initial
4107 } else {
4108 SpaceId::Handshake
4111 };
4112 debug_assert!(space <= expected, "received out-of-order CRYPTO data");
4116
4117 let end = crypto.offset + crypto.data.len() as u64;
4118 if space < expected
4119 && end
4120 > self.crypto_state.spaces[space.kind()]
4121 .crypto_stream
4122 .bytes_read()
4123 {
4124 warn!(
4125 "received new {:?} CRYPTO data when expecting {:?}",
4126 space, expected
4127 );
4128 return Err(TransportError::PROTOCOL_VIOLATION(
4129 "new data at unexpected encryption level",
4130 ));
4131 }
4132
4133 let crypto_space = &mut self.crypto_state.spaces[space.kind()];
4134 let max = end.saturating_sub(crypto_space.crypto_stream.bytes_read());
4135 if max > self.config.crypto_buffer_size as u64 {
4136 return Err(TransportError::CRYPTO_BUFFER_EXCEEDED(""));
4137 }
4138
4139 crypto_space
4140 .crypto_stream
4141 .insert(crypto.offset, crypto.data.clone(), payload_len)
4142 .map_err(|_| TransportError::INTERNAL_ERROR("too many gaps in crypto stream buffer"))?;
4143
4144 while let Some(chunk) = crypto_space.crypto_stream.read(usize::MAX, true) {
4145 trace!("consumed {} CRYPTO bytes", chunk.bytes.len());
4146 if self.crypto_state.session.read_handshake(&chunk.bytes)? {
4147 self.events.push_back(Event::HandshakeDataReady);
4148 }
4149 }
4150
4151 Ok(())
4152 }
4153
4154 fn write_crypto(&mut self) {
4155 loop {
4156 let space = self.highest_space;
4157 let mut outgoing = Vec::new();
4158 if let Some(crypto) = self.crypto_state.session.write_handshake(&mut outgoing) {
4159 match space {
4160 SpaceKind::Initial => {
4161 self.upgrade_crypto(SpaceKind::Handshake, crypto);
4162 }
4163 SpaceKind::Handshake => {
4164 self.upgrade_crypto(SpaceKind::Data, crypto);
4165 }
4166 SpaceKind::Data => unreachable!("got updated secrets during 1-RTT"),
4167 }
4168 }
4169 if outgoing.is_empty() {
4170 if space == self.highest_space {
4171 break;
4172 } else {
4173 continue;
4175 }
4176 }
4177 let offset = self.crypto_state.spaces[space].crypto_offset;
4178 let outgoing = Bytes::from(outgoing);
4179 if let Some(hs) = self.state.as_handshake_mut()
4180 && space == SpaceKind::Initial
4181 && offset == 0
4182 && self.side.is_client()
4183 {
4184 hs.client_hello = Some(outgoing.clone());
4185 }
4186 self.crypto_state.spaces[space].crypto_offset += outgoing.len() as u64;
4187 trace!("wrote {} {:?} CRYPTO bytes", outgoing.len(), space);
4188 self.spaces[space].pending.crypto.push_back(frame::Crypto {
4189 offset,
4190 data: outgoing,
4191 });
4192 }
4193 }
4194
4195 fn upgrade_crypto(&mut self, space: SpaceKind, crypto: Keys) {
4197 debug_assert!(
4198 !self.crypto_state.has_keys(space.encryption_level()),
4199 "already reached packet space {space:?}"
4200 );
4201 trace!("{:?} keys ready", space);
4202 if space == SpaceKind::Data {
4203 self.crypto_state.next_crypto = Some(
4205 self.crypto_state
4206 .session
4207 .next_1rtt_keys()
4208 .expect("handshake should be complete"),
4209 );
4210 }
4211
4212 self.crypto_state.spaces[space].keys = Some(crypto);
4213 debug_assert!(space > self.highest_space);
4214 self.highest_space = space;
4215 if space == SpaceKind::Data && self.side.is_client() {
4216 self.crypto_state.discard_zero_rtt();
4218 }
4219 }
4220
4221 fn discard_space(&mut self, now: Instant, space: SpaceKind) {
4222 debug_assert!(space != SpaceKind::Data);
4223 trace!("discarding {:?} keys", space);
4224 if space == SpaceKind::Initial {
4225 if let ConnectionSide::Client { token, .. } = &mut self.side {
4227 *token = Bytes::new();
4228 }
4229 }
4230 self.crypto_state.spaces[space].keys = None;
4231 let space = &mut self.spaces[space];
4232 let pns = space.for_path(PathId::ZERO);
4233 pns.time_of_last_ack_eliciting_packet = None;
4234 pns.loss_time = None;
4235 pns.loss_probes = 0;
4236 let sent_packets = mem::take(&mut pns.sent_packets);
4237 let path = self
4238 .paths
4239 .get_mut(&PathId::ZERO)
4240 .expect("PathId::ZERO is alive while Initial/Handshake spaces exist");
4241 for (_, packet) in sent_packets.into_iter() {
4242 path.data.remove_in_flight(&packet);
4243 }
4244 path.data.pto_count = 0;
4248
4249 self.set_loss_detection_timer(now, PathId::ZERO)
4250 }
4251
4252 fn handle_coalesced(
4253 &mut self,
4254 now: Instant,
4255 network_path: FourTuple,
4256 path_id: PathId,
4257 ecn: Option<EcnCodepoint>,
4258 data: BytesMut,
4259 ) {
4260 let Some(path) = self.paths.get_mut(&path_id) else {
4261 trace!(%path_id, "discarding coalesced datagram tail for unknown path");
4262 return;
4263 };
4264 path.data.inc_total_recvd(data.len() as u64);
4265 let mut remaining = Some(data);
4266 let cid_len = self
4267 .local_cid_state
4268 .values()
4269 .map(|cid_state| cid_state.cid_len())
4270 .next()
4271 .expect("one cid_state must exist");
4272 while let Some(data) = remaining {
4273 match PartialDecode::new(
4274 data,
4275 &FixedLengthConnectionIdParser::new(cid_len),
4276 &[self.version],
4277 self.endpoint_config.grease_quic_bit,
4278 ) {
4279 Ok((partial_decode, rest)) => {
4280 remaining = rest;
4281 self.handle_decode(now, network_path, path_id, ecn, partial_decode);
4282 }
4283 Err(e) => {
4284 trace!("malformed header: {}", e);
4285 return;
4286 }
4287 }
4288 }
4289 }
4290
4291 fn handle_decode(
4297 &mut self,
4298 now: Instant,
4299 network_path: FourTuple,
4300 path_id: PathId,
4301 ecn: Option<EcnCodepoint>,
4302 partial_decode: PartialDecode,
4303 ) {
4304 let qlog = QlogRecvPacket::new(partial_decode.len());
4305 if let Some(decoded) = self
4306 .crypto_state
4307 .unprotect_header(partial_decode, self.peer_params.stateless_reset_token)
4308 {
4309 self.handle_packet(
4310 now,
4311 network_path,
4312 path_id,
4313 ecn,
4314 decoded.packet,
4315 decoded.stateless_reset,
4316 qlog,
4317 );
4318 }
4319 }
4320
4321 fn handle_packet(
4328 &mut self,
4329 now: Instant,
4330 network_path: FourTuple,
4331 path_id: PathId,
4332 ecn: Option<EcnCodepoint>,
4333 packet: Option<Packet>,
4334 stateless_reset: bool,
4335 mut qlog: QlogRecvPacket,
4336 ) {
4337 if let Some(ref packet) = packet {
4338 trace!(
4339 "got {:?} packet ({} bytes) from {} using id {}",
4340 packet.header.space(),
4341 packet.payload.len() + packet.header_data.len(),
4342 network_path,
4343 packet.header.dst_cid(),
4344 );
4345 }
4346
4347 let was_closed = self.state.is_closed();
4348 let was_drained = self.state.is_drained();
4349
4350 let decrypted = match packet {
4352 None => Err(None),
4353 Some(mut packet) => self
4354 .decrypt_packet(now, path_id, &mut packet)
4355 .map(move |number| (packet, number)),
4356 };
4357 let result = match decrypted {
4358 _ if stateless_reset => {
4359 debug!("got stateless reset");
4360 Err(ConnectionError::Reset)
4361 }
4362 Err(Some(e)) => {
4363 warn!("illegal packet: {}", e);
4364 Err(e.into())
4365 }
4366 Err(None) => {
4367 debug!("failed to authenticate packet");
4368 self.authentication_failures += 1;
4369 let integrity_limit = self
4370 .crypto_state
4371 .integrity_limit(self.highest_space)
4372 .unwrap();
4373 if self.authentication_failures > integrity_limit {
4374 Err(TransportError::AEAD_LIMIT_REACHED("integrity limit violated").into())
4375 } else {
4376 return;
4377 }
4378 }
4379 Ok((packet, pn)) => {
4380 qlog.header(&packet.header, pn, path_id);
4382 let span = match pn {
4383 Some(pn) => trace_span!("recv", space = ?packet.header.space(), pn),
4384 None => trace_span!("recv", space = ?packet.header.space()),
4385 };
4386 let _guard = span.enter();
4387
4388 if self.is_handshaking()
4396 && self
4397 .path(path_id)
4398 .map(|path_data| {
4399 !path_data.network_path.is_probably_same_path(&network_path)
4400 })
4401 .unwrap_or(false)
4402 {
4403 if let Some(hs) = self.state.as_handshake()
4404 && hs.allow_server_migration
4405 {
4406 trace!(
4407 %network_path,
4408 prev = %self.path_data(path_id).network_path,
4409 "server migrated to new remote",
4410 );
4411 self.path_data_mut(path_id).network_path = network_path;
4412 self.qlog.emit_tuple_assigned(path_id, network_path, now);
4413 } else {
4414 debug!(
4415 recv_path = %network_path,
4416 expected_path = %self.path_data_mut(path_id).network_path,
4417 "discarding packet with unexpected remote during handshake",
4418 );
4419 return;
4420 }
4421 }
4422
4423 let dedup = self.spaces[packet.header.space()]
4424 .path_space_mut(path_id)
4425 .map(|pns| &mut pns.dedup);
4426 if pn.zip(dedup).is_some_and(|(n, d)| d.insert(n)) {
4427 debug!("discarding possible duplicate packet");
4428 self.qlog.emit_packet_received(qlog, now);
4429 return;
4430 } else if self.state.is_handshake() && packet.header.is_short() {
4431 trace!("dropping short packet during handshake");
4433 self.qlog.emit_packet_received(qlog, now);
4434 return;
4435 } else {
4436 if let Header::Initial(InitialHeader { ref token, .. }) = packet.header
4437 && let Some(hs) = self.state.as_handshake()
4438 && self.side.is_server()
4439 && token != &hs.expected_token
4440 {
4441 warn!("discarding Initial with invalid retry token");
4445 self.qlog.emit_packet_received(qlog, now);
4446 return;
4447 }
4448
4449 if !self.state.is_closed() {
4450 let spin = match packet.header {
4451 Header::Short { spin, .. } => spin,
4452 _ => false,
4453 };
4454
4455 if self.side().is_server() && !self.abandoned_paths.contains(&path_id) {
4456 self.create_path(path_id, network_path, now, pn);
4458 }
4459 if self.paths.contains_key(&path_id) {
4460 self.on_packet_authenticated(
4461 now,
4462 packet.header.space(),
4463 path_id,
4464 ecn,
4465 pn,
4466 spin,
4467 packet.header.is_1rtt(),
4468 &network_path,
4469 );
4470 }
4471 }
4472
4473 let res = self.process_decrypted_packet(
4474 now,
4475 network_path,
4476 path_id,
4477 pn,
4478 packet,
4479 &mut qlog,
4480 );
4481
4482 self.qlog.emit_packet_received(qlog, now);
4483 res
4484 }
4485 }
4486 };
4487
4488 if let Err(conn_err) = result {
4490 match conn_err {
4491 ConnectionError::ApplicationClosed(reason) => self.state.move_to_closed(reason),
4492 ConnectionError::ConnectionClosed(reason) => self.state.move_to_closed(reason),
4493 ConnectionError::Reset
4494 | ConnectionError::TransportError(TransportError {
4495 code: TransportErrorCode::AEAD_LIMIT_REACHED,
4496 ..
4497 }) => {
4498 if !self.state.is_drained() {
4499 self.state
4500 .move_to_drained(Some(conn_err), &mut self.endpoint_events);
4501 }
4502 }
4503 ConnectionError::TimedOut => {
4504 unreachable!("timeouts aren't generated by packet processing");
4505 }
4506 ConnectionError::TransportError(err) => {
4507 debug!("closing connection due to transport error: {}", err);
4508 self.state.move_to_closed(err);
4509 }
4510 ConnectionError::VersionMismatch => {
4511 self.state
4512 .move_to_draining(Some(conn_err), &mut self.endpoint_events);
4513 }
4514 ConnectionError::LocallyClosed => {
4515 unreachable!("LocallyClosed isn't generated by packet processing");
4516 }
4517 ConnectionError::CidsExhausted => {
4518 unreachable!("CidsExhausted isn't generated by packet processing");
4519 }
4520 };
4521 }
4522
4523 if !was_closed && self.state.is_closed() {
4524 self.close_common();
4525 if !self.state.is_drained() {
4526 self.set_close_timer(now);
4527 }
4528 }
4529 if !was_drained && self.state.is_drained() {
4530 self.timers
4533 .stop(Timer::Conn(ConnTimer::Close), self.qlog.with_time(now));
4534 }
4535
4536 if matches!(self.state.as_type(), StateType::Closed) {
4543 if self
4561 .paths
4562 .get(&path_id)
4563 .map(|p| p.data.validated && p.data.network_path == network_path)
4564 .unwrap_or(false)
4565 {
4566 self.connection_close_pending = true;
4567 }
4568 }
4569 }
4570
4571 fn process_decrypted_packet(
4572 &mut self,
4573 now: Instant,
4574 network_path: FourTuple,
4575 path_id: PathId,
4576 number: Option<u64>,
4577 packet: Packet,
4578 qlog: &mut QlogRecvPacket,
4579 ) -> Result<(), ConnectionError> {
4580 if !self.paths.contains_key(&path_id) {
4581 trace!(%path_id, ?number, "discarding packet for unknown path");
4585 return Ok(());
4586 }
4587 let state = match self.state.as_type() {
4588 StateType::Established => {
4589 match packet.header.space() {
4590 SpaceKind::Data => self.process_payload(
4591 now,
4592 network_path,
4593 path_id,
4594 number.unwrap(),
4595 packet,
4596 qlog,
4597 )?,
4598 _ if packet.header.has_frames() => {
4599 self.process_early_payload(now, path_id, packet, qlog)?
4600 }
4601 _ => {
4602 trace!("discarding unexpected pre-handshake packet");
4603 }
4604 }
4605 return Ok(());
4606 }
4607 StateType::Closed => {
4608 for result in frame::Iter::new(packet.payload.freeze())? {
4609 let frame = match result {
4610 Ok(frame) => frame,
4611 Err(err) => {
4612 debug!("frame decoding error: {err:?}");
4613 continue;
4614 }
4615 };
4616 qlog.frame(&frame);
4617
4618 if let Frame::Padding = frame {
4619 continue;
4620 };
4621
4622 trace!(?frame, "processing frame in closed state");
4623
4624 self.path_stats.get_mut(path_id).frame_rx.record(frame.ty());
4625
4626 if let Frame::Close(_error) = frame {
4627 self.state.move_to_draining(None, &mut self.endpoint_events);
4628 break;
4629 }
4630 }
4631 return Ok(());
4632 }
4633 StateType::Draining | StateType::Drained => return Ok(()),
4634 StateType::Handshake => self.state.as_handshake_mut().expect("checked"),
4635 };
4636
4637 match packet.header {
4638 Header::Retry {
4639 src_cid: remote_cid,
4640 ..
4641 } => {
4642 debug_assert_eq!(path_id, PathId::ZERO);
4643 if self.side.is_server() {
4644 return Err(TransportError::PROTOCOL_VIOLATION("client sent Retry").into());
4645 }
4646
4647 let is_valid_retry = self
4648 .remote_cids
4649 .get(&path_id)
4650 .map(|cids| cids.active())
4651 .map(|orig_dst_cid| {
4652 self.crypto_state.session.is_valid_retry(
4653 orig_dst_cid,
4654 &packet.header_data,
4655 &packet.payload,
4656 )
4657 })
4658 .unwrap_or_default();
4659 if self.total_authed_packets > 1
4660 || packet.payload.len() <= 16 || !is_valid_retry
4662 {
4663 trace!("discarding invalid Retry");
4664 return Ok(());
4670 }
4671
4672 trace!("retrying with CID {}", remote_cid);
4673 let client_hello = state.client_hello.take().unwrap();
4674 self.retry_src_cid = Some(remote_cid);
4675 self.remote_cids
4676 .get_mut(&path_id)
4677 .expect("PathId::ZERO not yet abandoned, is_valid_retry would have been false")
4678 .update_initial_cid(remote_cid);
4679 self.remote_handshake_cid = remote_cid;
4680
4681 let space = &mut self.spaces[SpaceId::Initial];
4682 if let Some(info) = space.for_path(PathId::ZERO).take(0) {
4683 self.on_packet_acked(now, PathId::ZERO, SpaceKind::Initial, 0, info);
4684 };
4685
4686 self.discard_space(now, SpaceKind::Initial); let crypto_space = &mut self.crypto_state.spaces[SpaceKind::Initial];
4689 crypto_space.keys = Some(
4690 self.crypto_state
4691 .session
4692 .initial_keys(remote_cid, self.side.side()),
4693 );
4694 crypto_space.crypto_offset = client_hello.len() as u64;
4695
4696 let next_pn = self.spaces[SpaceId::Initial]
4697 .for_path(path_id)
4698 .next_packet_number;
4699 self.spaces[SpaceId::Initial] = {
4700 let mut space = PacketSpace::new(now, SpaceId::Initial, &mut self.rng);
4701 space.for_path(path_id).next_packet_number = next_pn;
4702 space.pending.crypto.push_back(frame::Crypto {
4703 offset: 0,
4704 data: client_hello,
4705 });
4706 space
4707 };
4708
4709 let zero_rtt = mem::take(
4711 &mut self.spaces[SpaceId::Data]
4712 .for_path(PathId::ZERO)
4713 .sent_packets,
4714 );
4715 for (_, info) in zero_rtt.into_iter() {
4716 self.paths
4717 .get_mut(&PathId::ZERO)
4718 .unwrap()
4719 .remove_in_flight(&info);
4720 self.spaces[SpaceId::Data].pending |= info.retransmits;
4721 }
4722 self.streams.retransmit_all_for_0rtt();
4723
4724 let token_len = packet.payload.len() - 16;
4725 let ConnectionSide::Client { ref mut token, .. } = self.side else {
4726 unreachable!("we already short-circuited if we're server");
4727 };
4728 *token = packet.payload.freeze().split_to(token_len);
4729
4730 self.state = State::handshake(state::Handshake {
4731 expected_token: Bytes::new(),
4732 remote_cid_set: false,
4733 client_hello: None,
4734 allow_server_migration: self.config.server_handshake_migration,
4735 });
4736 Ok(())
4737 }
4738 Header::Long {
4739 ty: LongType::Handshake,
4740 src_cid: remote_cid,
4741 dst_cid: local_cid,
4742 ..
4743 } => {
4744 debug_assert_eq!(path_id, PathId::ZERO);
4745 if remote_cid != self.remote_handshake_cid {
4746 debug!(
4747 "discarding packet with mismatched remote CID: {} != {}",
4748 self.remote_handshake_cid, remote_cid
4749 );
4750 return Ok(());
4751 }
4752 self.on_path_validated(path_id);
4753
4754 self.process_early_payload(now, path_id, packet, qlog)?;
4755 if self.state.is_closed() {
4756 return Ok(());
4757 }
4758
4759 if self.crypto_state.session.is_handshaking() {
4760 trace!("handshake ongoing");
4761 return Ok(());
4762 }
4763
4764 if self.side.is_client() {
4765 let params = self
4767 .crypto_state
4768 .session
4769 .transport_parameters()?
4770 .ok_or_else(|| {
4771 TransportError::new(
4772 TransportErrorCode::crypto(0x6d),
4773 "transport parameters missing".to_owned(),
4774 )
4775 })?;
4776
4777 if self.has_0rtt() {
4778 if !self.crypto_state.session.early_data_accepted().unwrap() {
4779 debug_assert!(self.side.is_client());
4780 debug!("0-RTT rejected");
4781 self.crypto_state.accepted_0rtt = false;
4782 self.streams.zero_rtt_rejected();
4783
4784 self.spaces[SpaceId::Data].pending = Retransmits::default();
4786
4787 let sent_packets = mem::take(
4789 &mut self.spaces[SpaceId::Data].for_path(path_id).sent_packets,
4790 );
4791 for (_, packet) in sent_packets.into_iter() {
4792 self.paths
4793 .get_mut(&path_id)
4794 .unwrap()
4795 .remove_in_flight(&packet);
4796 }
4797 } else {
4798 self.crypto_state.accepted_0rtt = true;
4799 params.validate_resumption_from(&self.peer_params)?;
4800 }
4801 }
4802 if let Some(token) = params.stateless_reset_token {
4803 let remote = self.path_data(path_id).network_path.remote;
4804 debug_assert!(!self.state.is_drained()); self.endpoint_events
4806 .push_back(EndpointEventInner::ResetToken(path_id, remote, token));
4807 }
4808 self.handle_peer_params(params, local_cid, remote_cid, now)?;
4809 self.issue_first_cids(now);
4810 } else {
4811 self.spaces[SpaceId::Data].pending.handshake_done = true;
4813 self.discard_space(now, SpaceKind::Handshake);
4814 self.events.push_back(Event::HandshakeConfirmed);
4815 trace!("handshake confirmed");
4816 }
4817
4818 self.events.push_back(Event::Connected);
4819 self.state.move_to_established();
4820 self.reset_idle_timeout(now, SpaceKind::Data, path_id);
4822 trace!("established");
4823
4824 self.issue_first_path_cids(now);
4827 self.rearm_path_max_idle_timer(now, self.highest_space, path_id);
4828 Ok(())
4829 }
4830 Header::Initial(InitialHeader {
4831 src_cid: remote_cid,
4832 dst_cid: local_cid,
4833 ..
4834 }) => {
4835 debug_assert_eq!(path_id, PathId::ZERO);
4836 if !state.remote_cid_set {
4837 trace!("switching remote CID to {}", remote_cid);
4838 let mut state = state.clone();
4839 self.remote_cids
4840 .get_mut(&path_id)
4841 .expect("PathId::ZERO not yet abandoned")
4842 .update_initial_cid(remote_cid);
4843 self.remote_handshake_cid = remote_cid;
4844 self.original_remote_cid = remote_cid;
4845 state.remote_cid_set = true;
4846 self.state.move_to_handshake(state);
4847 } else if remote_cid != self.remote_handshake_cid {
4848 debug!(
4849 "discarding packet with mismatched remote CID: {} != {}",
4850 self.remote_handshake_cid, remote_cid
4851 );
4852 return Ok(());
4853 }
4854
4855 let starting_space = self.highest_space;
4856 self.process_early_payload(now, path_id, packet, qlog)?;
4857
4858 if self.side.is_server()
4859 && starting_space == SpaceKind::Initial
4860 && self.highest_space != SpaceKind::Initial
4861 {
4862 let params = self
4863 .crypto_state
4864 .session
4865 .transport_parameters()?
4866 .ok_or_else(|| {
4867 TransportError::new(
4868 TransportErrorCode::crypto(0x6d),
4869 "transport parameters missing".to_owned(),
4870 )
4871 })?;
4872 self.handle_peer_params(params, local_cid, remote_cid, now)?;
4873 self.issue_first_cids(now);
4874 self.init_0rtt(now);
4875 }
4876 Ok(())
4877 }
4878 Header::Long {
4879 ty: LongType::ZeroRtt,
4880 ..
4881 } => {
4882 self.process_payload(now, network_path, path_id, number.unwrap(), packet, qlog)?;
4883 Ok(())
4884 }
4885 Header::VersionNegotiate { .. } => {
4886 if self.total_authed_packets > 1 {
4887 return Ok(());
4888 }
4889 let supported = packet
4890 .payload
4891 .chunks(4)
4892 .any(|x| match <[u8; 4]>::try_from(x) {
4893 Ok(version) => self.version == u32::from_be_bytes(version),
4894 Err(_) => false,
4895 });
4896 if supported {
4897 return Ok(());
4898 }
4899 debug!("remote doesn't support our version");
4900 Err(ConnectionError::VersionMismatch)
4901 }
4902 Header::Short { .. } => unreachable!(
4903 "short packets received during handshake are discarded in handle_packet"
4904 ),
4905 }
4906 }
4907
4908 fn process_early_payload(
4910 &mut self,
4911 now: Instant,
4912 path_id: PathId,
4913 packet: Packet,
4914 #[allow(unused)] qlog: &mut QlogRecvPacket,
4915 ) -> Result<(), TransportError> {
4916 debug_assert_ne!(packet.header.space(), SpaceKind::Data);
4917 debug_assert_eq!(path_id, PathId::ZERO);
4918 let payload_len = packet.payload.len();
4919 let mut ack_eliciting = false;
4920 for result in frame::Iter::new(packet.payload.freeze())? {
4921 let frame = result?;
4922 qlog.frame(&frame);
4923 let span = match frame {
4924 Frame::Padding => continue,
4925 _ => Some(trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty)),
4926 };
4927
4928 self.path_stats.get_mut(path_id).frame_rx.record(frame.ty());
4929
4930 let _guard = span.as_ref().map(|x| x.enter());
4931 ack_eliciting |= frame.is_ack_eliciting();
4932
4933 if frame.is_1rtt() && packet.header.space() != SpaceKind::Data {
4935 return Err(TransportError::PROTOCOL_VIOLATION(
4936 "illegal frame type in handshake",
4937 ));
4938 }
4939
4940 match frame {
4941 Frame::Padding | Frame::Ping => {}
4942 Frame::Crypto(frame) => {
4943 self.read_crypto(packet.header.space().into(), &frame, payload_len)?;
4944 }
4945 Frame::Ack(ack) => {
4946 self.on_ack_received(now, packet.header.space().into(), ack)?;
4947 }
4948 Frame::PathAck(ack) => {
4949 span.as_ref()
4950 .map(|span| span.record("path", tracing::field::display(&ack.path_id)));
4951 self.on_path_ack_received(now, packet.header.space().into(), ack)?;
4952 }
4953 Frame::Close(reason) => {
4954 self.state
4955 .move_to_draining(Some(reason.into()), &mut self.endpoint_events);
4956 return Ok(());
4957 }
4958 _ => {
4959 let mut err =
4960 TransportError::PROTOCOL_VIOLATION("illegal frame type in handshake");
4961 err.frame = frame::MaybeFrame::Known(frame.ty());
4962 return Err(err);
4963 }
4964 }
4965 }
4966
4967 if ack_eliciting {
4968 self.spaces[packet.header.space()]
4970 .for_path(path_id)
4971 .pending_acks
4972 .set_immediate_ack_required();
4973 }
4974
4975 self.write_crypto();
4976 Ok(())
4977 }
4978
4979 fn process_payload(
4981 &mut self,
4982 now: Instant,
4983 network_path: FourTuple,
4984 path_id: PathId,
4985 number: u64,
4986 packet: Packet,
4987 #[allow(unused)] qlog: &mut QlogRecvPacket,
4988 ) -> Result<(), TransportError> {
4989 let payload = packet.payload.freeze();
4990 let mut is_probing_packet = true;
4991 let mut close = None;
4992 let payload_len = payload.len();
4993 let mut ack_eliciting = false;
4994 let mut migration_observed_addr = None;
4997 for result in frame::Iter::new(payload)? {
4998 let frame = result?;
4999 qlog.frame(&frame);
5000 let span = match frame {
5001 Frame::Padding => continue,
5002 _ => trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty),
5003 };
5004
5005 self.path_stats.get_mut(path_id).frame_rx.record(frame.ty());
5006 match &frame {
5009 Frame::Crypto(f) => {
5010 trace!(offset = f.offset, len = f.data.len(), "got frame CRYPTO");
5011 }
5012 Frame::Stream(f) => {
5013 trace!(id = %f.id, offset = f.offset, len = f.data.len(), fin = f.fin, "got frame STREAM");
5014 }
5015 Frame::Datagram(f) => {
5016 trace!(len = f.data.len(), "got frame DATAGRAM");
5017 }
5018 f => {
5019 trace!("got frame {f}");
5020 }
5021 }
5022
5023 let _guard = span.enter();
5024 if packet.header.is_0rtt() {
5025 match frame {
5026 Frame::Crypto(_) | Frame::Close(Close::Application(_)) => {
5027 return Err(TransportError::PROTOCOL_VIOLATION(
5028 "illegal frame type in 0-RTT",
5029 ));
5030 }
5031 _ => {
5032 if frame.is_1rtt() {
5033 return Err(TransportError::PROTOCOL_VIOLATION(
5034 "illegal frame type in 0-RTT",
5035 ));
5036 }
5037 }
5038 }
5039 }
5040 ack_eliciting |= frame.is_ack_eliciting();
5041
5042 match frame {
5044 Frame::Padding
5045 | Frame::PathChallenge(_)
5046 | Frame::PathResponse(_)
5047 | Frame::NewConnectionId(_)
5048 | Frame::ObservedAddr(_) => {}
5049 _ => {
5050 is_probing_packet = false;
5051 }
5052 }
5053
5054 match frame {
5055 Frame::Crypto(frame) => {
5056 self.read_crypto(SpaceId::Data, &frame, payload_len)?;
5057 }
5058 Frame::Stream(frame) => {
5059 if self.streams.received(frame, payload_len)?.should_transmit() {
5060 self.spaces[SpaceId::Data].pending.max_data = true;
5061 }
5062 }
5063 Frame::Ack(ack) => {
5064 self.on_ack_received(now, SpaceId::Data, ack)?;
5065 }
5066 Frame::PathAck(ack) => {
5067 if !self.is_multipath_negotiated() {
5068 return Err(TransportError::PROTOCOL_VIOLATION(
5069 "received PATH_ACK frame when multipath was not negotiated",
5070 ));
5071 }
5072 span.record("path", tracing::field::display(&ack.path_id));
5073 self.on_path_ack_received(now, SpaceId::Data, ack)?;
5074 }
5075 Frame::Padding | Frame::Ping => {}
5076 Frame::Close(reason) => {
5077 close = Some(reason);
5078 }
5079 Frame::PathChallenge(challenge) => {
5080 self.spaces[SpaceKind::Data]
5081 .for_path(path_id)
5082 .pending_path_responses
5083 .push(number, challenge.0, network_path);
5084 let path = &mut self
5088 .path_mut(path_id)
5089 .expect("payload is processed only after the path becomes known");
5090 if network_path.remote == path.network_path.remote {
5091 match self.peer_supports_ack_frequency() {
5099 true => self.immediate_ack(path_id),
5100 false => {
5101 self.ping_path(path_id).ok();
5102 }
5103 }
5104 }
5105 }
5106 Frame::PathResponse(response) => {
5107 if self
5109 .n0_nat_traversal
5110 .handle_path_response(network_path, response.0)
5111 {
5112 self.open_nat_traversed_paths(now);
5113 } else {
5114 self.handle_path_response_on_path(now, response, path_id);
5116 }
5117 }
5118 Frame::MaxData(frame::MaxData(bytes)) => {
5119 self.streams.received_max_data(bytes);
5120 }
5121 Frame::MaxStreamData(frame::MaxStreamData { id, offset }) => {
5122 self.streams.received_max_stream_data(id, offset)?;
5123 }
5124 Frame::MaxStreams(frame::MaxStreams { dir, count }) => {
5125 self.streams.received_max_streams(dir, count)?;
5126 }
5127 Frame::ResetStream(frame) => {
5128 if self.streams.received_reset(frame)?.should_transmit() {
5129 self.spaces[SpaceId::Data].pending.max_data = true;
5130 }
5131 }
5132 Frame::DataBlocked(DataBlocked(offset)) => {
5133 debug!(offset, "peer claims to be blocked at connection level");
5134 }
5135 Frame::StreamDataBlocked(StreamDataBlocked { id, offset }) => {
5136 if id.initiator() == self.side.side() && id.dir() == Dir::Uni {
5137 debug!("got STREAM_DATA_BLOCKED on send-only {}", id);
5138 return Err(TransportError::STREAM_STATE_ERROR(
5139 "STREAM_DATA_BLOCKED on send-only stream",
5140 ));
5141 }
5142 debug!(
5143 stream = %id,
5144 offset, "peer claims to be blocked at stream level"
5145 );
5146 }
5147 Frame::StreamsBlocked(StreamsBlocked { dir, limit }) => {
5148 if limit > MAX_STREAM_COUNT {
5149 return Err(TransportError::FRAME_ENCODING_ERROR(
5150 "unrepresentable stream limit",
5151 ));
5152 }
5153 debug!(
5154 "peer claims to be blocked opening more than {} {} streams",
5155 limit, dir
5156 );
5157 }
5158 Frame::StopSending(frame::StopSending { id, error_code }) => {
5159 if id.initiator() != self.side.side() {
5160 if id.dir() == Dir::Uni {
5161 debug!("got STOP_SENDING on recv-only {}", id);
5162 return Err(TransportError::STREAM_STATE_ERROR(
5163 "STOP_SENDING on recv-only stream",
5164 ));
5165 }
5166 } else if self.streams.is_local_unopened(id) {
5167 return Err(TransportError::STREAM_STATE_ERROR(
5168 "STOP_SENDING on unopened stream",
5169 ));
5170 }
5171 self.streams.received_stop_sending(id, error_code);
5172 }
5173 Frame::RetireConnectionId(frame::RetireConnectionId { path_id, sequence }) => {
5174 if let Some(ref path_id) = path_id {
5175 span.record("path", tracing::field::display(&path_id));
5176 }
5177 let path_id = path_id.unwrap_or_default();
5178 match self.local_cid_state.get_mut(&path_id) {
5179 None => debug!(?path_id, "RETIRE_CONNECTION_ID for unknown path"),
5180 Some(cid_state) => {
5181 let allow_more_cids = cid_state
5182 .on_cid_retirement(sequence, self.peer_params.issue_cids_limit())?;
5183
5184 let has_path = !self.abandoned_paths.contains(&path_id);
5188 let allow_more_cids = allow_more_cids && has_path;
5189
5190 debug_assert!(!self.state.is_drained()); self.endpoint_events
5192 .push_back(EndpointEventInner::RetireConnectionId(
5193 now,
5194 path_id,
5195 sequence,
5196 allow_more_cids,
5197 ));
5198 }
5199 }
5200 }
5201 Frame::NewConnectionId(frame) => {
5202 let path_id = if let Some(path_id) = frame.path_id {
5203 if !self.is_multipath_negotiated() {
5204 return Err(TransportError::PROTOCOL_VIOLATION(
5205 "received PATH_NEW_CONNECTION_ID frame when multipath was not negotiated",
5206 ));
5207 }
5208 if path_id > self.local_max_path_id {
5209 return Err(TransportError::PROTOCOL_VIOLATION(
5210 "PATH_NEW_CONNECTION_ID contains path_id exceeding current max",
5211 ));
5212 }
5213 path_id
5214 } else {
5215 PathId::ZERO
5216 };
5217
5218 if let Some(ref path_id) = frame.path_id {
5219 span.record("path", tracing::field::display(&path_id));
5220 }
5221
5222 if self.abandoned_paths.contains(&path_id) {
5223 trace!("ignoring issued CID for abandoned path");
5224 continue;
5225 }
5226 let remote_cids = self
5227 .remote_cids
5228 .entry(path_id)
5229 .or_insert_with(|| CidQueue::new(frame.id));
5230 if remote_cids.active().is_empty() {
5231 return Err(TransportError::PROTOCOL_VIOLATION(
5232 "NEW_CONNECTION_ID when CIDs aren't in use",
5233 ));
5234 }
5235 if frame.retire_prior_to > frame.sequence {
5236 return Err(TransportError::PROTOCOL_VIOLATION(
5237 "NEW_CONNECTION_ID retiring unissued CIDs",
5238 ));
5239 }
5240
5241 use crate::cid_queue::InsertError;
5242 match remote_cids.insert(frame) {
5243 Ok(None) => {
5244 self.open_nat_traversed_paths(now);
5245 }
5246 Ok(Some((retired, reset_token))) => {
5247 let pending_retired =
5248 &mut self.spaces[SpaceId::Data].pending.retire_cids;
5249 const MAX_PENDING_RETIRED_CIDS: u64 = CidQueue::LEN as u64 * 10;
5252 if (pending_retired.len() as u64)
5255 .saturating_add(retired.end.saturating_sub(retired.start))
5256 > MAX_PENDING_RETIRED_CIDS
5257 {
5258 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR(
5259 "queued too many retired CIDs",
5260 ));
5261 }
5262 pending_retired.extend(retired.map(|seq| (path_id, seq)));
5263 self.set_reset_token(path_id, network_path.remote, reset_token);
5264 self.open_nat_traversed_paths(now);
5265 }
5266 Err(InsertError::ExceedsLimit) => {
5267 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR(""));
5268 }
5269 Err(InsertError::Retired) => {
5270 trace!("discarding already-retired");
5271 self.spaces[SpaceId::Data]
5275 .pending
5276 .retire_cids
5277 .push((path_id, frame.sequence));
5278 continue;
5279 }
5280 };
5281
5282 if self.side.is_server()
5283 && path_id == PathId::ZERO
5284 && self
5285 .remote_cids
5286 .get(&PathId::ZERO)
5287 .map(|cids| cids.active_seq() == 0)
5288 .unwrap_or_default()
5289 {
5290 self.update_remote_cid(PathId::ZERO);
5293 }
5294 }
5295 Frame::NewToken(NewToken { token }) => {
5296 let ConnectionSide::Client {
5297 token_store,
5298 server_name,
5299 ..
5300 } = &self.side
5301 else {
5302 return Err(TransportError::PROTOCOL_VIOLATION("client sent NEW_TOKEN"));
5303 };
5304 if token.is_empty() {
5305 return Err(TransportError::FRAME_ENCODING_ERROR("empty token"));
5306 }
5307 trace!("got new token");
5308 token_store.insert(server_name, token);
5309 }
5310 Frame::Datagram(datagram) => {
5311 if self
5312 .datagrams
5313 .received(datagram, &self.config.datagram_receive_buffer_size)?
5314 {
5315 self.events.push_back(Event::DatagramReceived);
5316 }
5317 }
5318 Frame::AckFrequency(ack_frequency) => {
5319 if !self.ack_frequency.ack_frequency_received(&ack_frequency)? {
5322 continue;
5325 }
5326
5327 for (path_id, space) in self.spaces[SpaceId::Data].number_spaces.iter_mut() {
5329 space.pending_acks.set_ack_frequency_params(&ack_frequency);
5330
5331 if !self.abandoned_paths.contains(path_id)
5335 && let Some(timeout) = space
5336 .pending_acks
5337 .max_ack_delay_timeout(self.ack_frequency.max_ack_delay)
5338 {
5339 self.timers.set(
5340 Timer::PerPath(*path_id, PathTimer::MaxAckDelay),
5341 timeout,
5342 self.qlog.with_time(now),
5343 );
5344 }
5345 }
5346 }
5347 Frame::ImmediateAck => {
5348 for pns in self.spaces[SpaceId::Data].iter_paths_mut() {
5350 pns.pending_acks.set_immediate_ack_required();
5351 }
5352 }
5353 Frame::HandshakeDone => {
5354 if self.side.is_server() {
5355 return Err(TransportError::PROTOCOL_VIOLATION(
5356 "client sent HANDSHAKE_DONE",
5357 ));
5358 }
5359 if self.crypto_state.has_keys(EncryptionLevel::Handshake) {
5360 self.discard_space(now, SpaceKind::Handshake);
5361 self.events.push_back(Event::HandshakeConfirmed);
5362 trace!("handshake confirmed");
5363 }
5364 }
5365 Frame::ObservedAddr(observed) => {
5366 trace!(seq_no = %observed.seq_no, ip = %observed.ip, port = observed.port);
5368 if !self
5369 .peer_params
5370 .address_discovery_role
5371 .should_report(&self.config.address_discovery_role)
5372 {
5373 return Err(TransportError::PROTOCOL_VIOLATION(
5374 "received OBSERVED_ADDRESS frame when not negotiated",
5375 ));
5376 }
5377 if packet.header.space() != SpaceKind::Data {
5379 return Err(TransportError::PROTOCOL_VIOLATION(
5380 "OBSERVED_ADDRESS frame outside data space",
5381 ));
5382 }
5383
5384 let space_open_status =
5385 self.spaces[SpaceKind::Data].for_path(path_id).open_status;
5386 let path = self.path_data_mut(path_id);
5387 if path.network_path.remote == network_path.remote {
5388 if let Some(updated) = path.update_observed_addr_report(observed)
5389 && space_open_status == OpenStatus::Informed
5390 {
5391 self.events.push_back(Event::Path(PathEvent::ObservedAddr {
5392 id: path_id,
5393 addr: updated,
5394 }));
5395 }
5397 } else {
5398 migration_observed_addr = Some(observed)
5400 }
5401 }
5402 Frame::PathAbandon(frame::PathAbandon {
5403 path_id,
5404 error_code,
5405 }) => {
5406 span.record("path", tracing::field::display(&path_id));
5407 match self.close_path_inner(
5408 now,
5409 path_id,
5410 PathAbandonReason::RemoteAbandoned {
5411 error_code: error_code.into(),
5412 },
5413 ) {
5414 Ok(()) => {
5415 trace!("peer abandoned path");
5416 }
5417 Err(ClosePathError::ClosedPath) => {
5418 trace!("peer abandoned already closed path");
5419 }
5420 Err(ClosePathError::MultipathNotNegotiated) => {
5421 return Err(TransportError::PROTOCOL_VIOLATION(
5422 "received PATH_ABANDON frame when multipath was not negotiated",
5423 ));
5424 }
5425 Err(ClosePathError::LastOpenPath) => {
5426 error!(
5429 "peer abandoned last path but close_path_inner returned LastOpenPath"
5430 );
5431 }
5432 };
5433
5434 if let Some(path) = self.paths.get_mut(&path_id)
5436 && !mem::replace(&mut path.data.draining, true)
5437 {
5438 let ack_delay = self.ack_frequency.max_ack_delay_for_pto();
5439 let pto = path.data.rtt.pto_base() + ack_delay;
5440 self.timers.set(
5441 Timer::PerPath(path_id, PathTimer::PathDrained),
5442 now + 3 * pto,
5443 self.qlog.with_time(now),
5444 );
5445
5446 self.set_max_path_id(now, self.local_max_path_id.saturating_add(1u8));
5447 }
5448 }
5449 Frame::PathStatusAvailable(info) => {
5450 span.record("path", tracing::field::display(&info.path_id));
5451 if self.is_multipath_negotiated() {
5452 self.on_path_status(
5453 info.path_id,
5454 PathStatus::Available,
5455 info.status_seq_no,
5456 );
5457 } else {
5458 return Err(TransportError::PROTOCOL_VIOLATION(
5459 "received PATH_STATUS_AVAILABLE frame when multipath was not negotiated",
5460 ));
5461 }
5462 }
5463 Frame::PathStatusBackup(info) => {
5464 span.record("path", tracing::field::display(&info.path_id));
5465 if self.is_multipath_negotiated() {
5466 self.on_path_status(info.path_id, PathStatus::Backup, info.status_seq_no);
5467 } else {
5468 return Err(TransportError::PROTOCOL_VIOLATION(
5469 "received PATH_STATUS_BACKUP frame when multipath was not negotiated",
5470 ));
5471 }
5472 }
5473 Frame::MaxPathId(frame::MaxPathId(path_id)) => {
5474 span.record("path", tracing::field::display(&path_id));
5475 if !self.is_multipath_negotiated() {
5476 return Err(TransportError::PROTOCOL_VIOLATION(
5477 "received MAX_PATH_ID frame when multipath was not negotiated",
5478 ));
5479 }
5480 if path_id > self.remote_max_path_id {
5482 self.remote_max_path_id = path_id;
5483 self.issue_first_path_cids(now);
5484 self.open_nat_traversed_paths(now);
5485 }
5486 }
5487 Frame::PathsBlocked(frame::PathsBlocked(max_path_id)) => {
5488 if self.is_multipath_negotiated() {
5493 if max_path_id > self.local_max_path_id {
5494 return Err(TransportError::PROTOCOL_VIOLATION(
5495 "PATHS_BLOCKED maximum path identifier was larger than local maximum",
5496 ));
5497 }
5498 } else {
5499 return Err(TransportError::PROTOCOL_VIOLATION(
5500 "received PATHS_BLOCKED frame when not multipath was not negotiated",
5501 ));
5502 }
5503 }
5504 Frame::PathCidsBlocked(frame::PathCidsBlocked { path_id, next_seq }) => {
5505 if self.is_multipath_negotiated() {
5514 if path_id > self.local_max_path_id {
5515 return Err(TransportError::PROTOCOL_VIOLATION(
5516 "PATH_CIDS_BLOCKED path identifier was larger than local maximum",
5517 ));
5518 }
5519 if self
5520 .local_cid_state
5521 .get(&path_id)
5522 .is_some_and(|cid_state| next_seq.0 > cid_state.active_seq().1 + 1)
5526 {
5527 return Err(TransportError::PROTOCOL_VIOLATION(
5528 "PATH_CIDS_BLOCKED next sequence number larger than in local state",
5529 ));
5530 }
5531 debug!(%path_id, %next_seq, "received PATH_CIDS_BLOCKED");
5532 } else {
5533 return Err(TransportError::PROTOCOL_VIOLATION(
5534 "received PATH_CIDS_BLOCKED frame when not multipath was not negotiated",
5535 ));
5536 }
5537 }
5538 Frame::AddAddress(addr) => {
5539 let client_state = match self.n0_nat_traversal.client_side_mut() {
5540 Ok(state) => state,
5541 Err(err) => {
5542 return Err(TransportError::PROTOCOL_VIOLATION(format!(
5543 "Nat traversal(ADD_ADDRESS): {err}"
5544 )));
5545 }
5546 };
5547
5548 if !client_state.check_remote_address(&addr) {
5549 warn!(?addr, "server sent illegal ADD_ADDRESS frame");
5551 }
5552
5553 match client_state.add_remote_address(addr) {
5554 Ok(maybe_added) => {
5555 if let Some(added) = maybe_added {
5556 self.events.push_back(Event::NatTraversal(
5557 n0_nat_traversal::Event::AddressAdded(added),
5558 ));
5559 }
5560 }
5561 Err(e) => {
5562 warn!(%e, "failed to add remote address")
5563 }
5564 }
5565 }
5566 Frame::RemoveAddress(addr) => {
5567 let client_state = match self.n0_nat_traversal.client_side_mut() {
5568 Ok(state) => state,
5569 Err(err) => {
5570 return Err(TransportError::PROTOCOL_VIOLATION(format!(
5571 "Nat traversal(REMOVE_ADDRESS): {err}"
5572 )));
5573 }
5574 };
5575 if let Some(removed_addr) = client_state.remove_remote_address(addr) {
5576 self.events.push_back(Event::NatTraversal(
5577 n0_nat_traversal::Event::AddressRemoved(removed_addr),
5578 ));
5579 }
5580 }
5581 Frame::ReachOut(reach_out) => {
5582 let ipv6 = self.is_ipv6();
5583 let server_state = match self.n0_nat_traversal.server_side_mut() {
5584 Ok(state) => state,
5585 Err(err) => {
5586 return Err(TransportError::PROTOCOL_VIOLATION(format!(
5587 "Nat traversal(REACH_OUT): {err}"
5588 )));
5589 }
5590 };
5591
5592 let round_before = server_state.current_round();
5593
5594 if let Err(err) = server_state.handle_reach_out(reach_out, ipv6) {
5595 return Err(TransportError::PROTOCOL_VIOLATION(format!(
5596 "Nat traversal(REACH_OUT): {err}"
5597 )));
5598 }
5599
5600 if server_state.current_round() > round_before {
5601 if let Some(delay) =
5603 self.n0_nat_traversal.retry_delay(self.config.initial_rtt)
5604 {
5605 self.timers.set(
5606 Timer::Conn(ConnTimer::NatTraversalProbeRetry),
5607 now + delay,
5608 self.qlog.with_time(now),
5609 );
5610 }
5611 }
5612 }
5613 }
5614 }
5615
5616 let space = self.spaces[SpaceId::Data].for_path(path_id);
5617 if space
5618 .pending_acks
5619 .packet_received(now, number, ack_eliciting, &space.dedup)
5620 {
5621 if self.abandoned_paths.contains(&path_id) {
5622 space.pending_acks.set_immediate_ack_required();
5625 } else {
5626 self.timers.set(
5627 Timer::PerPath(path_id, PathTimer::MaxAckDelay),
5628 now + self.ack_frequency.max_ack_delay,
5629 self.qlog.with_time(now),
5630 );
5631 }
5632 }
5633
5634 let pending = &mut self.spaces[SpaceId::Data].pending;
5639 self.streams.queue_max_stream_id(pending);
5640
5641 if let Some(reason) = close {
5642 self.state
5643 .move_to_draining(Some(reason.into()), &mut self.endpoint_events);
5644 self.connection_close_pending = true;
5645 }
5646
5647 let migrate_on_any_packet =
5650 self.is_multipath_negotiated() && !self.n0_nat_traversal.is_negotiated();
5651
5652 let is_largest_received_pn = Some(number)
5654 == self.spaces[SpaceId::Data]
5655 .for_path(path_id)
5656 .largest_received_packet_number;
5657
5658 if (migrate_on_any_packet || !is_probing_packet)
5663 && is_largest_received_pn
5664 && self.local_ip_may_migrate()
5665 && let Some(new_local_ip) = network_path.local_ip
5666 {
5667 let path_data = self.path_data_mut(path_id);
5668 if path_data
5669 .network_path
5670 .local_ip
5671 .is_some_and(|ip| ip != new_local_ip)
5672 {
5673 debug!(
5674 %path_id,
5675 new_4tuple = %network_path,
5676 prev_4tuple = %path_data.network_path,
5677 "local address passive migration"
5678 );
5679 }
5680 path_data.network_path.local_ip = Some(new_local_ip)
5681 }
5682
5683 if self.peer_may_migrate()
5685 && (migrate_on_any_packet || !is_probing_packet)
5686 && is_largest_received_pn
5687 && network_path.remote != self.path_data(path_id).network_path.remote
5688 {
5689 self.migrate(path_id, now, network_path, migration_observed_addr);
5690 self.update_remote_cid(path_id);
5692 self.spin = false;
5693 }
5694
5695 Ok(())
5696 }
5697
5698 fn handle_path_response_on_path(
5702 &mut self,
5703 now: Instant,
5704 response: frame::PathResponse,
5705 path_id: PathId,
5706 ) {
5707 let is_multipath_negotiated = self.is_multipath_negotiated();
5708 let path = self
5709 .paths
5710 .get_mut(&path_id)
5711 .expect("payload is processed only after the path becomes known");
5712 match path.data.on_path_response_received(now, response.0) {
5713 paths::OnPathResponseReceived::OnPath if !self.abandoned_paths.contains(&path_id) => {
5714 let qlog = self.qlog.with_time(now);
5715 self.timers.stop(
5716 Timer::PerPath(path_id, PathTimer::PathValidationFailed),
5717 qlog.clone(),
5718 );
5719 let next_challenge = path
5720 .data
5721 .earliest_on_path_expiring_challenge()
5722 .map(|time| time + self.ack_frequency.max_ack_delay_for_pto());
5723 self.timers.set_or_stop(
5724 Timer::PerPath(path_id, PathTimer::PathChallengeLost),
5725 next_challenge,
5726 qlog,
5727 );
5728 let pns = self.spaces[SpaceKind::Data].for_path(path_id);
5729 if !matches!(pns.open_status, OpenStatus::Informed) {
5730 if is_multipath_negotiated {
5731 self.events
5732 .push_back(Event::Path(PathEvent::Established { id: path_id }));
5733 }
5734 pns.open_status = OpenStatus::Informed;
5735 if let Some(observed) = path.data.last_observed_addr_report.as_ref() {
5736 self.events.push_back(Event::Path(PathEvent::ObservedAddr {
5737 id: path_id,
5738 addr: observed.socket_addr(),
5739 }));
5740 }
5741 }
5742 if let Some((_, ref mut prev)) = path.prev {
5743 prev.reset_on_path_challenges();
5748 }
5749 }
5750 paths::OnPathResponseReceived::OnPath => {
5751 trace!(
5752 %response,
5753 "ignoring PATH_RESPONSE received after path is abandoned"
5754 );
5755 }
5756 paths::OnPathResponseReceived::Unknown => {
5757 debug!(%response, "ignoring invalid PATH_RESPONSE");
5758 }
5759 paths::OnPathResponseReceived::Ignored {
5760 sent_on,
5761 current_path,
5762 } => {
5763 debug!(%sent_on, %current_path, %response, "ignoring valid PATH_RESPONSE");
5764 }
5765 }
5766 }
5767
5768 fn open_nat_traversed_paths(&mut self, now: Instant) {
5770 while let Some(network_path) = self
5771 .n0_nat_traversal
5772 .client_side_mut()
5773 .ok()
5774 .and_then(|s| s.pop_pending_path_open())
5775 {
5776 match self.open_path_ensure(network_path, PathStatus::Backup, now) {
5777 Ok((path_id, already_existed)) => {
5778 debug!(
5779 %path_id,
5780 ?network_path,
5781 new_path = !already_existed,
5782 "Opened NAT traversal path",
5783 );
5784 }
5785 Err(err) => match err {
5786 PathError::MultipathNotNegotiated
5787 | PathError::ServerSideNotAllowed
5788 | PathError::ValidationFailed
5789 | PathError::InvalidRemoteAddress(_) => {
5790 error!(
5791 ?err,
5792 ?network_path,
5793 "Failed to open path for successful NAT traversal"
5794 );
5795 }
5796 PathError::MaxPathIdReached | PathError::RemoteCidsExhausted => {
5797 self.n0_nat_traversal
5799 .client_side_mut()
5800 .map(|s| s.push_pending_path_open(network_path))
5801 .ok();
5802 debug!(
5803 ?err,
5804 ?network_path,
5805 "Blocked opening NAT traversal path, enqueued"
5806 );
5807 return;
5808 }
5809 },
5810 }
5811 }
5812 }
5813
5814 fn migrate(
5819 &mut self,
5820 path_id: PathId,
5821 now: Instant,
5822 network_path: FourTuple,
5823 observed_addr: Option<ObservedAddr>,
5824 ) {
5825 trace!(
5826 new_4tuple = %network_path,
5827 prev_4tuple = %self.path_data(path_id).network_path,
5828 %path_id,
5829 "migration initiated",
5830 );
5831 self.path_generation_counter = self.path_generation_counter.wrapping_add(1);
5832 let prev_pto = self.pto(SpaceKind::Data, path_id);
5839 let path = self.paths.get_mut(&path_id).expect("known path");
5840 let mut new_path_data = if network_path.remote.is_ipv4()
5841 && network_path.remote.ip() == path.data.network_path.remote.ip()
5842 {
5843 PathData::from_previous(network_path, &path.data, self.path_generation_counter, now)
5844 } else {
5845 let peer_max_udp_payload_size =
5846 u16::try_from(self.peer_params.max_udp_payload_size.into_inner())
5847 .unwrap_or(u16::MAX);
5848 PathData::new(
5849 network_path,
5850 self.allow_mtud,
5851 Some(peer_max_udp_payload_size),
5852 self.path_generation_counter,
5853 now,
5854 &self.config,
5855 )
5856 };
5857 new_path_data.last_observed_addr_report = path.data.last_observed_addr_report.clone();
5858 if let Some(report) = observed_addr
5859 && let Some(updated) = new_path_data.update_observed_addr_report(report)
5860 {
5861 tracing::info!("adding observed addr event from migration");
5862 self.events.push_back(Event::Path(PathEvent::ObservedAddr {
5863 id: path_id,
5864 addr: updated,
5865 }));
5866 }
5867 new_path_data.pending_challenge = true;
5868 new_path_data.pending.observed_address = self
5869 .config
5870 .address_discovery_role
5871 .should_report(&self.peer_params.address_discovery_role);
5872
5873 let mut prev_path_data = mem::replace(&mut path.data, new_path_data);
5874
5875 if !prev_path_data.validated
5884 && let Some(cid) = self.remote_cids.get(&path_id).map(CidQueue::active)
5885 {
5886 prev_path_data.pending_challenge = true;
5887 path.prev = Some((cid, prev_path_data));
5890 }
5891
5892 self.qlog.emit_tuple_assigned(path_id, network_path, now);
5894
5895 self.timers.set(
5896 Timer::PerPath(path_id, PathTimer::PathValidationFailed),
5897 now + 3 * cmp::max(self.pto(SpaceKind::Data, path_id), prev_pto),
5898 self.qlog.with_time(now),
5899 );
5900 }
5901
5902 pub fn handle_network_change(&mut self, hint: Option<&dyn NetworkChangeHint>, now: Instant) {
5919 debug!("network changed");
5920 if self.state.is_drained() {
5921 return;
5922 }
5923 if self.highest_space < SpaceKind::Data {
5924 for path in self.paths.values_mut() {
5925 path.data.network_path.local_ip = None;
5927 }
5928
5929 self.update_remote_cid(PathId::ZERO);
5930 self.ping();
5931
5932 return;
5933 }
5934
5935 let mut non_recoverable_paths = Vec::default();
5938 let mut recoverable_paths = Vec::default();
5939 let mut open_paths = 0;
5940
5941 let is_multipath_negotiated = self.is_multipath_negotiated();
5942 let is_client = self.side().is_client();
5943 let immediate_ack_allowed = self.peer_supports_ack_frequency();
5944
5945 for (path_id, path) in self.paths.iter_mut() {
5946 if self.abandoned_paths.contains(path_id) {
5947 continue;
5948 }
5949 open_paths += 1;
5950
5951 let network_path = path.data.network_path;
5954
5955 path.data.network_path.local_ip = None;
5958 let remote = network_path.remote;
5959
5960 let attempt_to_recover = if is_multipath_negotiated {
5964 hint.map(|h| h.is_path_recoverable(*path_id, network_path))
5968 .unwrap_or(!is_client)
5969 } else {
5970 true
5972 };
5973
5974 if attempt_to_recover {
5975 recoverable_paths.push((*path_id, remote));
5976 } else {
5977 non_recoverable_paths.push((*path_id, remote, path.data.local_status()))
5978 }
5979 }
5980
5981 let open_first = open_paths == non_recoverable_paths.len();
5990
5991 for (path_id, remote, status) in non_recoverable_paths.into_iter() {
5992 let network_path = FourTuple {
5993 remote,
5994 local_ip: None, };
5996
5997 if open_first && let Err(e) = self.open_path(network_path, status, now) {
5998 if self.side().is_client() {
5999 debug!(%e, "Failed to open new path for network change");
6000 }
6001 recoverable_paths.push((path_id, remote));
6003 continue;
6004 }
6005
6006 if let Err(e) =
6007 self.close_path_inner(now, path_id, PathAbandonReason::UnusableAfterNetworkChange)
6008 {
6009 debug!(%e,"Failed to close unrecoverable path after network change");
6010 recoverable_paths.push((path_id, remote));
6011 continue;
6012 }
6013
6014 if !open_first && let Err(e) = self.open_path(network_path, status, now) {
6015 debug!(%e,"Failed to open new path for network change");
6019 }
6020 }
6021
6022 for (path_id, remote) in recoverable_paths.into_iter() {
6025 if let Some(path_space) = self.spaces[SpaceId::Data].number_spaces.get_mut(&path_id) {
6027 path_space.pending_ping = true;
6028
6029 if immediate_ack_allowed {
6030 path_space.pending_immediate_ack = true;
6031 }
6032 }
6033
6034 if let Some(path) = self.paths.get_mut(&path_id) {
6039 path.data.pto_count = 0;
6040 }
6041 self.set_loss_detection_timer(now, path_id);
6042
6043 let Some((reset_token, retired)) =
6044 self.remote_cids.get_mut(&path_id).and_then(CidQueue::next)
6045 else {
6046 continue;
6047 };
6048
6049 self.spaces[SpaceId::Data]
6051 .pending
6052 .retire_cids
6053 .extend(retired.map(|seq| (path_id, seq)));
6054
6055 debug_assert!(!self.state.is_drained()); self.endpoint_events
6057 .push_back(EndpointEventInner::ResetToken(path_id, remote, reset_token));
6058 }
6059 }
6060
6061 fn update_remote_cid(&mut self, path_id: PathId) {
6063 let Some((reset_token, retired)) = self
6064 .remote_cids
6065 .get_mut(&path_id)
6066 .and_then(|cids| cids.next())
6067 else {
6068 return;
6069 };
6070
6071 self.spaces[SpaceId::Data]
6073 .pending
6074 .retire_cids
6075 .extend(retired.map(|seq| (path_id, seq)));
6076 let remote = self.path_data(path_id).network_path.remote;
6077 self.set_reset_token(path_id, remote, reset_token);
6078 }
6079
6080 fn set_reset_token(&mut self, path_id: PathId, remote: SocketAddr, reset_token: ResetToken) {
6089 debug_assert!(!self.state.is_drained()); self.endpoint_events
6091 .push_back(EndpointEventInner::ResetToken(path_id, remote, reset_token));
6092
6093 if path_id == PathId::ZERO {
6099 self.peer_params.stateless_reset_token = Some(reset_token);
6100 }
6101 }
6102
6103 fn issue_first_cids(&mut self, now: Instant) {
6105 if self
6106 .local_cid_state
6107 .get(&PathId::ZERO)
6108 .expect("PathId::ZERO exists when the connection is created")
6109 .cid_len()
6110 == 0
6111 {
6112 return;
6113 }
6114
6115 let mut n = self.peer_params.issue_cids_limit() - 1;
6117 if let ConnectionSide::Server { server_config } = &self.side
6118 && server_config.has_preferred_address()
6119 {
6120 n -= 1;
6122 }
6123 debug_assert!(!self.state.is_drained()); self.endpoint_events
6125 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n));
6126 }
6127
6128 fn issue_first_path_cids(&mut self, now: Instant) {
6132 if let Some(max_path_id) = self.max_path_id() {
6133 let mut path_id = self.max_path_id_with_cids.next();
6134 while path_id <= max_path_id {
6135 self.endpoint_events
6136 .push_back(EndpointEventInner::NeedIdentifiers(
6137 path_id,
6138 now,
6139 self.peer_params.issue_cids_limit(),
6140 ));
6141 path_id = path_id.next();
6142 }
6143 self.max_path_id_with_cids = max_path_id;
6144 }
6145 }
6146
6147 fn populate_packet<'a, 'b>(
6155 &mut self,
6156 now: Instant,
6157 space_id: SpaceId,
6158 path_id: PathId,
6159 scheduling_info: &PathSchedulingInfo,
6160 builder: &mut PacketBuilder<'a, 'b>,
6161 ) {
6162 let is_multipath_negotiated = self.is_multipath_negotiated();
6163 let space_has_keys = self.crypto_state.has_keys(space_id.encryption_level());
6164 let is_0rtt = space_id == SpaceId::Data && !space_has_keys;
6165 let stats = &mut self.path_stats.get_mut(path_id).frame_tx;
6166 let space = &mut self.spaces[space_id];
6167 let path = &mut self.paths.get_mut(&path_id).expect("known path").data;
6168 space
6169 .for_path(path_id)
6170 .pending_acks
6171 .maybe_ack_non_eliciting();
6172
6173 if !is_0rtt
6175 && !scheduling_info.is_abandoned
6176 && scheduling_info.may_send_data
6177 && mem::replace(&mut space.pending.handshake_done, false)
6178 {
6179 builder.write_frame(frame::HandshakeDone, stats);
6180 }
6181
6182 if !scheduling_info.is_abandoned
6184 && mem::replace(&mut space.for_path(path_id).pending_ping, false)
6185 {
6186 builder.write_frame(frame::Ping, stats);
6187 }
6188
6189 if !scheduling_info.is_abandoned
6191 && mem::replace(&mut space.for_path(path_id).pending_immediate_ack, false)
6192 {
6193 debug_assert_eq!(
6194 space_id,
6195 SpaceId::Data,
6196 "immediate acks must be sent in the data space"
6197 );
6198 builder.write_frame(frame::ImmediateAck, stats);
6199 }
6200
6201 if !scheduling_info.is_abandoned && scheduling_info.may_send_data {
6207 for path_id in space
6208 .number_spaces
6209 .iter_mut()
6210 .filter(|(_, pns)| {
6211 pns.pending_acks.can_send()
6212 || (space_id != SpaceId::Data && !pns.pending_acks.ranges().is_empty())
6213 })
6214 .map(|(&path_id, _)| path_id)
6215 .collect::<Vec<_>>()
6216 {
6217 Self::populate_acks(
6218 now,
6219 self.receiving_ecn,
6220 path_id,
6221 space_id,
6222 space,
6223 is_multipath_negotiated,
6224 builder,
6225 stats,
6226 space_has_keys,
6227 );
6228 }
6229 }
6230
6231 if !scheduling_info.is_abandoned
6233 && scheduling_info.may_send_data
6234 && mem::replace(&mut space.pending.ack_frequency, false)
6235 {
6236 let sequence_number = self.ack_frequency.next_sequence_number();
6237
6238 let config = self.config.ack_frequency_config.as_ref().unwrap();
6240
6241 let max_ack_delay = self.ack_frequency.candidate_max_ack_delay(
6243 path.rtt.get(),
6244 config,
6245 &self.peer_params,
6246 );
6247
6248 let frame = frame::AckFrequency {
6249 sequence: sequence_number,
6250 ack_eliciting_threshold: config.ack_eliciting_threshold,
6251 request_max_ack_delay: max_ack_delay.as_micros().try_into().unwrap_or(VarInt::MAX),
6252 reordering_threshold: config.reordering_threshold,
6253 };
6254 builder.write_frame(frame, stats);
6255
6256 self.ack_frequency
6257 .ack_frequency_sent(path_id, builder.packet_number, max_ack_delay);
6258 path.congestion.on_ack_frequency_update(
6259 config.ack_eliciting_threshold.into_inner(),
6260 max_ack_delay,
6261 );
6262 }
6263
6264 if !scheduling_info.is_abandoned
6266 && space_id == SpaceId::Data
6267 && path.pending_challenge
6268 && !self.state.is_closed()
6270 && builder.frame_space_remaining() > frame::PathChallenge::SIZE_BOUND
6271 && builder.buf.segment_size() >= usize::from(MIN_INITIAL_SIZE)
6274 {
6275 path.pending_challenge = false;
6276
6277 let token = self.rng.random();
6278 path.record_path_challenge_sent(now, token, path.network_path);
6279 let challenge = frame::PathChallenge(token);
6281 builder.write_frame(challenge, stats);
6282 builder.require_padding();
6283
6284 self.timers.set(
6289 Timer::PerPath(path_id, PathTimer::PathChallengeLost),
6290 now + path.on_path_challenge_pto(),
6291 self.qlog.with_time(now),
6292 );
6293
6294 if is_multipath_negotiated && !path.validated && path.pending_challenge {
6295 space.pending.path_status.insert(path_id);
6297 }
6298
6299 path.pending.observed_address = self
6302 .config
6303 .address_discovery_role
6304 .should_report(&self.peer_params.address_discovery_role);
6305 }
6306
6307 if !scheduling_info.is_abandoned
6309 && space_id == SpaceId::Data
6310 && builder.frame_space_remaining() > frame::PathResponse::SIZE_BOUND
6311 && builder.buf.segment_size() >= usize::from(MIN_INITIAL_SIZE)
6314 && let Some(token) = space.for_path(path_id).pending_path_responses.pop_on_path(path.network_path)
6315 {
6316 let response = frame::PathResponse(token);
6317 builder.write_frame(response, stats);
6318 builder.require_padding();
6319
6320 path.pending.observed_address = self
6324 .config
6325 .address_discovery_role
6326 .should_report(&self.peer_params.address_discovery_role);
6327 }
6328
6329 while space_id == SpaceId::Data
6331 && !scheduling_info.is_abandoned
6332 && scheduling_info.may_send_data
6333 && frame::AddAddress::SIZE_BOUND <= builder.frame_space_remaining()
6334 {
6335 if let Some(added_address) = space.pending.add_address.pop_last() {
6336 builder.write_frame(added_address, stats);
6337 } else {
6338 break;
6339 }
6340 }
6341
6342 while space_id == SpaceId::Data
6344 && !scheduling_info.is_abandoned
6345 && scheduling_info.may_send_data
6346 && frame::RemoveAddress::SIZE_BOUND <= builder.frame_space_remaining()
6347 {
6348 if let Some(removed_address) = space.pending.remove_address.pop_last() {
6349 builder.write_frame(removed_address, stats);
6350 } else {
6351 break;
6352 }
6353 }
6354
6355 while !scheduling_info.is_abandoned
6357 && scheduling_info.may_send_data
6358 && let Some(reach_out) = space
6359 .pending
6360 .reach_out
6361 .pop_if(|frame| builder.frame_space_remaining() >= frame.size())
6362 {
6363 builder.write_frame(reach_out, stats);
6364 }
6365
6366 if space_id == SpaceId::Data
6368 && scheduling_info.is_abandoned
6369 && scheduling_info.may_self_abandon
6370 && frame::PathAbandon::SIZE_BOUND <= builder.frame_space_remaining()
6371 && let Some(error_code) = space.pending.path_abandon.remove(&path_id)
6372 {
6373 let frame = frame::PathAbandon {
6374 path_id,
6375 error_code,
6376 };
6377 builder.write_frame(frame, stats);
6378
6379 self.remote_cids.remove(&path_id);
6382 }
6383 while space_id == SpaceId::Data
6384 && scheduling_info.may_send_data
6385 && frame::PathAbandon::SIZE_BOUND <= builder.frame_space_remaining()
6386 && let Some((abandoned_path_id, error_code)) = space.pending.path_abandon.pop_first()
6387 {
6388 let frame = frame::PathAbandon {
6389 path_id: abandoned_path_id,
6390 error_code,
6391 };
6392 builder.write_frame(frame, stats);
6393
6394 self.remote_cids.remove(&abandoned_path_id);
6397 }
6398
6399 if !scheduling_info.is_abandoned
6401 && space_id == SpaceId::Data
6402 && path.pending.observed_address
6403 {
6404 let frame = ObservedAddr::new(path.network_path.remote, self.next_observed_addr_seq_no);
6405 if builder.frame_space_remaining() > frame.size() {
6406 builder.write_frame(frame, stats);
6407
6408 self.next_observed_addr_seq_no = self.next_observed_addr_seq_no.saturating_add(1u8);
6409 path.pending.observed_address = false;
6410 }
6411 }
6412
6413 while !is_0rtt
6415 && !scheduling_info.is_abandoned
6416 && scheduling_info.may_send_data
6417 && builder.frame_space_remaining() > frame::Crypto::SIZE_BOUND
6418 {
6419 let Some(mut frame) = space.pending.crypto.pop_front() else {
6420 break;
6421 };
6422
6423 let max_crypto_data_size = builder.frame_space_remaining()
6428 - 1 - VarInt::size(unsafe { VarInt::from_u64_unchecked(frame.offset) })
6430 - 2; let len = frame
6433 .data
6434 .len()
6435 .min(2usize.pow(14) - 1)
6436 .min(max_crypto_data_size);
6437
6438 let data = frame.data.split_to(len);
6439 let offset = frame.offset;
6440 let truncated = frame::Crypto { offset, data };
6441 builder.write_frame(truncated, stats);
6442
6443 if !frame.data.is_empty() {
6444 frame.offset += len as u64;
6445 space.pending.crypto.push_front(frame);
6446 }
6447 }
6448
6449 while space_id == SpaceId::Data
6451 && !scheduling_info.is_abandoned
6452 && scheduling_info.may_send_data
6453 && frame::PathStatusAvailable::SIZE_BOUND <= builder.frame_space_remaining()
6454 {
6455 let Some(path_id) = space.pending.path_status.pop_first() else {
6456 break;
6457 };
6458 let Some(path) = self.paths.get(&path_id).map(|path_state| &path_state.data) else {
6459 trace!(%path_id, "discarding queued path status for unknown path");
6460 continue;
6461 };
6462
6463 let seq = path.status.seq();
6464 match path.local_status() {
6465 PathStatus::Available => {
6466 let frame = frame::PathStatusAvailable {
6467 path_id,
6468 status_seq_no: seq,
6469 };
6470 builder.write_frame(frame, stats);
6471 }
6472 PathStatus::Backup => {
6473 let frame = frame::PathStatusBackup {
6474 path_id,
6475 status_seq_no: seq,
6476 };
6477 builder.write_frame(frame, stats);
6478 }
6479 }
6480 }
6481
6482 if space_id == SpaceId::Data
6484 && !scheduling_info.is_abandoned
6485 && scheduling_info.may_send_data
6486 && space.pending.max_path_id
6487 && frame::MaxPathId::SIZE_BOUND <= builder.frame_space_remaining()
6488 {
6489 let frame = frame::MaxPathId(self.local_max_path_id);
6490 builder.write_frame(frame, stats);
6491 space.pending.max_path_id = false;
6492 }
6493
6494 if space_id == SpaceId::Data
6496 && !scheduling_info.is_abandoned
6497 && scheduling_info.may_send_data
6498 && frame::PathsBlocked::SIZE_BOUND <= builder.frame_space_remaining()
6499 && let Some(remote_max_path_id) = space.pending.paths_blocked.take()
6500 {
6501 let frame = frame::PathsBlocked(remote_max_path_id);
6502 builder.write_frame(frame, stats);
6503 }
6504
6505 while space_id == SpaceId::Data
6507 && !scheduling_info.is_abandoned
6508 && scheduling_info.may_send_data
6509 && frame::PathCidsBlocked::SIZE_BOUND <= builder.frame_space_remaining()
6510 {
6511 let Some((path_id, next_seq)) = space.pending.path_cids_blocked.pop_first() else {
6512 break;
6513 };
6514 let frame = frame::PathCidsBlocked { path_id, next_seq };
6515 builder.write_frame(frame, stats);
6516 }
6517
6518 if space_id == SpaceId::Data
6520 && !scheduling_info.is_abandoned
6521 && scheduling_info.may_send_data
6522 {
6523 self.streams
6524 .write_control_frames(builder, &mut space.pending, stats);
6525 }
6526
6527 let cid_len = self
6529 .local_cid_state
6530 .values()
6531 .map(|cid_state| cid_state.cid_len())
6532 .max()
6533 .expect("some local CID state must exist");
6534 let new_cid_size_bound =
6535 frame::NewConnectionId::size_bound(is_multipath_negotiated, cid_len);
6536 while !scheduling_info.is_abandoned
6537 && scheduling_info.may_send_data
6538 && builder.frame_space_remaining() > new_cid_size_bound
6539 {
6540 let Some(issued) = space.pending.new_cids.pop() else {
6541 break;
6542 };
6543 let Some(cid_state) = self.local_cid_state.get(&issued.path_id) else {
6545 debug!(
6546 path = %issued.path_id, seq = issued.sequence,
6547 "dropping queued NEW_CONNECTION_ID for discarded path",
6548 );
6549 continue;
6550 };
6551 let retire_prior_to = cid_state.retire_prior_to();
6552
6553 let cid_path_id = match is_multipath_negotiated {
6554 true => Some(issued.path_id),
6555 false => {
6556 debug_assert_eq!(issued.path_id, PathId::ZERO);
6557 None
6558 }
6559 };
6560 let frame = frame::NewConnectionId {
6561 path_id: cid_path_id,
6562 sequence: issued.sequence,
6563 retire_prior_to,
6564 id: issued.id,
6565 reset_token: issued.reset_token,
6566 };
6567 builder.write_frame(frame, stats);
6568 }
6569
6570 let retire_cid_bound = frame::RetireConnectionId::size_bound(is_multipath_negotiated);
6572 while !scheduling_info.is_abandoned
6573 && scheduling_info.may_send_data
6574 && builder.frame_space_remaining() > retire_cid_bound
6575 {
6576 let (path_id, sequence) = match space.pending.retire_cids.pop() {
6577 Some((PathId::ZERO, seq)) if !is_multipath_negotiated => (None, seq),
6578 Some((path_id, seq)) => (Some(path_id), seq),
6579 None => break,
6580 };
6581 let frame = frame::RetireConnectionId { path_id, sequence };
6582 builder.write_frame(frame, stats);
6583 }
6584
6585 let mut sent_datagrams = false;
6587 while !scheduling_info.is_abandoned
6588 && scheduling_info.may_send_data
6589 && builder.frame_space_remaining() > Datagram::SIZE_BOUND
6590 && space_id == SpaceId::Data
6591 {
6592 match self.datagrams.write(builder, stats) {
6593 true => {
6594 sent_datagrams = true;
6595 }
6596 false => break,
6597 }
6598 }
6599 if self.datagrams.send_blocked && sent_datagrams {
6600 self.events.push_back(Event::DatagramsUnblocked);
6601 self.datagrams.send_blocked = false;
6602 }
6603
6604 let path = &mut self.paths.get_mut(&path_id).expect("known path").data;
6605
6606 if !scheduling_info.is_abandoned && scheduling_info.may_send_data {
6608 while let Some(network_path) = space.pending.new_tokens.pop() {
6609 debug_assert_eq!(space_id, SpaceId::Data);
6610 let ConnectionSide::Server { server_config } = &self.side else {
6611 panic!("NEW_TOKEN frames should not be enqueued by clients");
6612 };
6613
6614 if !network_path.is_probably_same_path(&path.network_path) {
6615 continue;
6620 }
6621
6622 let token = Token::new(
6623 TokenPayload::Validation {
6624 ip: network_path.remote.ip(),
6625 issued: server_config.time_source.now(),
6626 },
6627 &mut self.rng,
6628 );
6629 let new_token = NewToken {
6630 token: token.encode(&*server_config.token_key).into(),
6631 };
6632
6633 if builder.frame_space_remaining() < new_token.size() {
6634 space.pending.new_tokens.push(network_path);
6635 break;
6636 }
6637
6638 builder.write_frame(new_token, stats);
6639 builder.retransmits_mut().new_tokens.push(network_path);
6640 }
6641 }
6642
6643 if !scheduling_info.is_abandoned
6645 && scheduling_info.may_send_data
6646 && space_id == SpaceId::Data
6647 {
6648 self.streams
6649 .write_stream_frames(builder, self.config.send_fairness, stats);
6650 }
6651 }
6652
6653 fn populate_acks<'a, 'b>(
6655 now: Instant,
6656 receiving_ecn: bool,
6657 path_id: PathId,
6658 space_id: SpaceId,
6659 space: &mut PacketSpace,
6660 is_multipath_negotiated: bool,
6661 builder: &mut PacketBuilder<'a, 'b>,
6662 stats: &mut FrameStats,
6663 space_has_keys: bool,
6664 ) {
6665 debug_assert!(space_has_keys, "tried to send ACK in 0-RTT");
6667
6668 debug_assert!(
6669 is_multipath_negotiated || path_id == PathId::ZERO,
6670 "Only PathId::ZERO allowed without multipath (have {path_id:?})"
6671 );
6672 if is_multipath_negotiated {
6673 debug_assert!(
6674 space_id == SpaceId::Data || path_id == PathId::ZERO,
6675 "path acks must be sent in 1RTT space (have {space_id:?})"
6676 );
6677 }
6678
6679 let pns = space.for_path(path_id);
6680 let ranges = pns.pending_acks.ranges();
6681 debug_assert!(!ranges.is_empty(), "can not send empty ACK range");
6682 let ecn = if receiving_ecn {
6683 Some(&pns.ecn_counters)
6684 } else {
6685 None
6686 };
6687
6688 let delay_micros = pns.pending_acks.ack_delay(now).as_micros() as u64;
6689 let ack_delay_exp = TransportParameters::default().ack_delay_exponent;
6691 let delay = delay_micros >> ack_delay_exp.into_inner();
6692
6693 if is_multipath_negotiated && space_id == SpaceId::Data {
6694 if !ranges.is_empty() {
6695 let frame = frame::PathAck::encoder(path_id, delay, ranges, ecn);
6696 builder.write_frame(frame, stats);
6697 }
6698 } else {
6699 builder.write_frame(frame::Ack::encoder(delay, ranges, ecn), stats);
6700 }
6701 }
6702
6703 fn close_common(&mut self) {
6704 trace!("connection closed");
6705 self.timers.reset();
6706 }
6707
6708 fn set_close_timer(&mut self, now: Instant) {
6709 let pto_max = self.max_pto_for_space(self.highest_space);
6712 self.timers.set(
6713 Timer::Conn(ConnTimer::Close),
6714 now + 3 * pto_max,
6715 self.qlog.with_time(now),
6716 );
6717 }
6718
6719 fn handle_peer_params(
6724 &mut self,
6725 params: TransportParameters,
6726 local_cid: ConnectionId,
6727 remote_cid: ConnectionId,
6728 now: Instant,
6729 ) -> Result<(), TransportError> {
6730 if Some(self.original_remote_cid) != params.initial_src_cid
6731 || (self.side.is_client()
6732 && (Some(self.initial_dst_cid) != params.original_dst_cid
6733 || self.retry_src_cid != params.retry_src_cid))
6734 {
6735 return Err(TransportError::TRANSPORT_PARAMETER_ERROR(
6736 "CID authentication failure",
6737 ));
6738 }
6739 if params.initial_max_path_id.is_some() && (local_cid.is_empty() || remote_cid.is_empty()) {
6740 return Err(TransportError::PROTOCOL_VIOLATION(
6741 "multipath must not use zero-length CIDs",
6742 ));
6743 }
6744
6745 self.set_peer_params(params);
6746 self.qlog.emit_peer_transport_params_received(self, now);
6747
6748 Ok(())
6749 }
6750
6751 fn set_peer_params(&mut self, params: TransportParameters) {
6752 self.streams.set_params(¶ms);
6753 self.idle_timeout =
6754 negotiate_max_idle_timeout(self.config.max_idle_timeout, Some(params.max_idle_timeout));
6755 trace!("negotiated max idle timeout {:?}", self.idle_timeout);
6756
6757 if let Some(ref info) = params.preferred_address {
6758 self.remote_cids.get_mut(&PathId::ZERO).expect("not yet abandoned").insert(frame::NewConnectionId {
6760 path_id: None,
6761 sequence: 1,
6762 id: info.connection_id,
6763 reset_token: info.stateless_reset_token,
6764 retire_prior_to: 0,
6765 })
6766 .expect(
6767 "preferred address CID is the first received, and hence is guaranteed to be legal",
6768 );
6769 let remote = self.path_data(PathId::ZERO).network_path.remote;
6770 self.set_reset_token(PathId::ZERO, remote, info.stateless_reset_token);
6771 }
6772 self.ack_frequency.peer_max_ack_delay = get_max_ack_delay(¶ms);
6773
6774 let mut multipath_enabled = false;
6775 if let (Some(local_max_path_id), Some(remote_max_path_id)) = (
6776 self.config.get_initial_max_path_id(),
6777 params.initial_max_path_id,
6778 ) {
6779 self.local_max_path_id = local_max_path_id;
6781 self.remote_max_path_id = remote_max_path_id;
6782 let initial_max_path_id = local_max_path_id.min(remote_max_path_id);
6783 debug!(%initial_max_path_id, "multipath negotiated");
6784 multipath_enabled = true;
6785 }
6786
6787 if let Some((max_locally_allowed_remote_addresses, max_remotely_allowed_remote_addresses)) =
6788 self.config
6789 .max_remote_nat_traversal_addresses
6790 .zip(params.max_remote_nat_traversal_addresses)
6791 {
6792 if multipath_enabled {
6793 let max_local_addresses = max_remotely_allowed_remote_addresses.get();
6794 let max_remote_addresses = max_locally_allowed_remote_addresses.get();
6795 self.n0_nat_traversal = n0_nat_traversal::State::new(
6796 max_remote_addresses,
6797 max_local_addresses,
6798 self.side(),
6799 );
6800 debug!(
6801 %max_remote_addresses, %max_local_addresses,
6802 "n0's nat traversal negotiated"
6803 );
6804 } else {
6805 debug!("n0 nat traversal enabled for both endpoints, but multipath is missing")
6806 }
6807 }
6808
6809 self.peer_params = params;
6810 let peer_max_udp_payload_size =
6811 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()).unwrap_or(u16::MAX);
6812 let address_discovery_negotiated = self
6813 .config
6814 .address_discovery_role
6815 .should_report(&self.peer_params.address_discovery_role);
6816
6817 let path = self.path_data_mut(PathId::ZERO);
6818 path.pending.observed_address = address_discovery_negotiated;
6819 path.mtud
6820 .on_peer_max_udp_payload_size_received(peer_max_udp_payload_size);
6821 }
6822
6823 fn decrypt_packet(
6825 &mut self,
6826 now: Instant,
6827 path_id: PathId,
6828 packet: &mut Packet,
6829 ) -> Result<Option<u64>, Option<TransportError>> {
6830 let result = self
6831 .crypto_state
6832 .decrypt_packet_body(packet, path_id, &self.spaces)?;
6833
6834 let Some(result) = result else {
6835 return Ok(None);
6836 };
6837
6838 if result.outgoing_key_update_acked
6839 && let Some(prev) = self.crypto_state.prev_crypto.as_mut()
6840 {
6841 prev.end_packet = Some((result.packet_number, now));
6842 self.set_key_discard_timer(now, packet.header.space());
6843 }
6844
6845 if result.incoming_key_update {
6846 trace!("key update authenticated");
6847 self.crypto_state
6848 .update_keys(Some((result.packet_number, now)), true);
6849 self.set_key_discard_timer(now, packet.header.space());
6850 }
6851
6852 Ok(Some(result.packet_number))
6853 }
6854
6855 fn peer_supports_ack_frequency(&self) -> bool {
6856 self.peer_params.min_ack_delay.is_some()
6857 }
6858
6859 pub(crate) fn immediate_ack(&mut self, path_id: PathId) {
6864 debug_assert_eq!(
6865 self.highest_space,
6866 SpaceKind::Data,
6867 "immediate ack must be written in the data space"
6868 );
6869 self.spaces[SpaceId::Data]
6870 .for_path(path_id)
6871 .pending_immediate_ack = true;
6872 }
6873
6874 #[cfg(test)]
6876 pub(crate) fn decode_packet(&self, event: &ConnectionEvent) -> Option<Vec<u8>> {
6877 let ConnectionEventInner::Datagram(DatagramConnectionEvent {
6878 path_id,
6879 first_decode,
6880 remaining,
6881 ..
6882 }) = &event.0
6883 else {
6884 return None;
6885 };
6886
6887 if remaining.is_some() {
6888 panic!("Packets should never be coalesced in tests");
6889 }
6890
6891 let decrypted_header = self
6892 .crypto_state
6893 .unprotect_header(first_decode.clone(), self.peer_params.stateless_reset_token)?;
6894
6895 let mut packet = decrypted_header.packet?;
6896 self.crypto_state
6897 .decrypt_packet_body(&mut packet, *path_id, &self.spaces)
6898 .ok()?;
6899
6900 Some(packet.payload.to_vec())
6901 }
6902
6903 #[cfg(test)]
6906 pub(crate) fn bytes_in_flight(&self) -> u64 {
6907 self.path_data(PathId::ZERO).in_flight.bytes
6909 }
6910
6911 #[cfg(test)]
6913 pub(crate) fn congestion_window(&self) -> u64 {
6914 let path = self.path_data(PathId::ZERO);
6915 path.congestion
6916 .window()
6917 .saturating_sub(path.in_flight.bytes)
6918 }
6919
6920 #[cfg(test)]
6922 pub(crate) fn is_idle(&self) -> bool {
6923 let current_timers = self.timers.values();
6924 current_timers
6925 .into_iter()
6926 .filter(|(timer, _)| {
6927 !matches!(
6928 timer,
6929 Timer::Conn(ConnTimer::KeepAlive)
6930 | Timer::PerPath(_, PathTimer::PathKeepAlive)
6931 | Timer::Conn(ConnTimer::PushNewCid)
6932 | Timer::Conn(ConnTimer::KeyDiscard)
6933 )
6934 })
6935 .min_by_key(|(_, time)| *time)
6936 .is_none_or(|(timer, _)| {
6937 matches!(
6938 timer,
6939 Timer::Conn(ConnTimer::Idle) | Timer::PerPath(_, PathTimer::PathIdle)
6940 )
6941 })
6942 }
6943
6944 #[cfg(test)]
6946 pub(crate) fn using_ecn(&self) -> bool {
6947 self.path_data(PathId::ZERO).sending_ecn
6948 }
6949
6950 #[cfg(test)]
6952 pub(crate) fn total_recvd(&self) -> u64 {
6953 self.path_data(PathId::ZERO).total_recvd
6954 }
6955
6956 #[cfg(test)]
6957 pub(crate) fn active_local_cid_seq(&self) -> (u64, u64) {
6958 self.local_cid_state
6959 .get(&PathId::ZERO)
6960 .unwrap()
6961 .active_seq()
6962 }
6963
6964 #[cfg(test)]
6965 #[track_caller]
6966 pub(crate) fn active_local_path_cid_seq(&self, path_id: u32) -> (u64, u64) {
6967 self.local_cid_state
6968 .get(&PathId(path_id))
6969 .unwrap()
6970 .active_seq()
6971 }
6972
6973 #[cfg(test)]
6976 pub(crate) fn rotate_local_cid(&mut self, v: u64, now: Instant) {
6977 let n = self
6978 .local_cid_state
6979 .get_mut(&PathId::ZERO)
6980 .unwrap()
6981 .assign_retire_seq(v);
6982 debug_assert!(!self.state.is_drained()); self.endpoint_events
6984 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n));
6985 }
6986
6987 #[cfg(test)]
6989 pub(crate) fn active_remote_cid_seq(&self) -> u64 {
6990 self.remote_cids.get(&PathId::ZERO).unwrap().active_seq()
6991 }
6992
6993 #[cfg(test)]
6995 pub(crate) fn path_mtu(&self, path_id: PathId) -> u16 {
6996 self.path_data(path_id).current_mtu()
6997 }
6998
6999 #[cfg(test)]
7001 pub(crate) fn trigger_path_validation(&mut self) {
7002 for path in self.paths.values_mut() {
7003 path.data.pending_challenge = true;
7004 }
7005 }
7006
7007 #[cfg(test)]
7009 pub fn simulate_protocol_violation(&mut self, now: Instant) {
7010 if !self.state.is_closed() {
7011 self.state
7012 .move_to_closed(TransportError::PROTOCOL_VIOLATION("simulated violation"));
7013 self.close_common();
7014 if !self.state.is_drained() {
7015 self.set_close_timer(now);
7016 }
7017 self.connection_close_pending = true;
7018 }
7019 }
7020
7021 fn can_send_1rtt(&self, path_id: PathId, max_size: usize) -> SendableFrames {
7032 let network_path = self.path_data(path_id).network_path;
7033 let space_specific = self
7034 .paths
7035 .get(&path_id)
7036 .is_some_and(|path| path.data.pending_challenge || !path.data.pending.is_empty())
7037 || self.spaces[SpaceKind::Data]
7038 .number_spaces
7039 .get(&path_id)
7040 .is_some_and(|pns| pns.pending_path_responses.has_pending_on_path(network_path));
7041
7042 let other = self.streams.can_send_stream_data()
7044 || self
7045 .datagrams
7046 .outgoing
7047 .front()
7048 .is_some_and(|x| x.size(true) <= max_size);
7049
7050 SendableFrames {
7052 acks: false,
7053 close: false,
7054 space_specific,
7055 other,
7056 }
7057 }
7058
7059 fn kill(&mut self, reason: ConnectionError) {
7061 self.close_common();
7062 self.state
7063 .move_to_drained(Some(reason), &mut self.endpoint_events);
7064 }
7065
7066 pub fn current_mtu(&self) -> u16 {
7073 self.paths
7074 .iter()
7075 .filter(|&(path_id, _path_state)| !self.abandoned_paths.contains(path_id))
7076 .map(|(_path_id, path_state)| path_state.data.current_mtu())
7077 .min()
7078 .unwrap_or(INITIAL_MTU)
7079 }
7080
7081 fn predict_1rtt_overhead(&mut self, pn: u64, path: PathId) -> usize {
7088 let pn_len = PacketNumber::new(
7089 pn,
7090 self.spaces[SpaceId::Data]
7091 .for_path(path)
7092 .largest_acked_packet_pn
7093 .unwrap_or(0),
7094 )
7095 .len();
7096
7097 1 + self
7099 .remote_cids
7100 .get(&path)
7101 .map(|cids| cids.active().len())
7102 .unwrap_or(20) + pn_len
7104 + self.tag_len_1rtt()
7105 }
7106
7107 fn predict_1rtt_overhead_no_pn(&self) -> usize {
7108 let pn_len = 4;
7109
7110 let cid_len = self
7111 .remote_cids
7112 .values()
7113 .map(|cids| cids.active().len())
7114 .max()
7115 .unwrap_or(20); 1 + cid_len + pn_len + self.tag_len_1rtt()
7119 }
7120
7121 fn tag_len_1rtt(&self) -> usize {
7122 let packet_crypto = self
7124 .crypto_state
7125 .encryption_keys(SpaceKind::Data, self.side.side())
7126 .map(|(_header, packet, _level)| packet);
7127 packet_crypto.map_or(16, |x| x.tag_len())
7131 }
7132
7133 fn on_path_validated(&mut self, path_id: PathId) {
7135 self.path_data_mut(path_id).validated = true;
7136 let ConnectionSide::Server { server_config } = &self.side else {
7137 return;
7138 };
7139 let network_path = self.path_data(path_id).network_path;
7140 let new_tokens = &mut self.spaces[SpaceId::Data as usize].pending.new_tokens;
7141 new_tokens.clear();
7142 for _ in 0..server_config.validation_token.sent {
7143 new_tokens.push(network_path);
7144 }
7145 }
7146
7147 fn on_path_status(&mut self, path_id: PathId, status: PathStatus, status_seq_no: VarInt) {
7149 if let Some(path) = self.paths.get_mut(&path_id) {
7150 path.data.status.remote_update(status, status_seq_no);
7151 } else {
7152 debug!("PATH_STATUS_AVAILABLE received unknown path {:?}", path_id);
7153 }
7154 self.events.push_back(
7155 PathEvent::RemoteStatus {
7156 id: path_id,
7157 status,
7158 }
7159 .into(),
7160 );
7161 }
7162
7163 fn max_path_id(&self) -> Option<PathId> {
7172 if self.is_multipath_negotiated() {
7173 Some(self.remote_max_path_id.min(self.local_max_path_id))
7174 } else {
7175 None
7176 }
7177 }
7178
7179 pub(crate) fn is_ipv6(&self) -> bool {
7184 self.paths
7185 .values()
7186 .any(|p| p.data.network_path.remote.is_ipv6())
7187 }
7188
7189 pub fn add_nat_traversal_address(
7191 &mut self,
7192 address: SocketAddr,
7193 ) -> Result<(), n0_nat_traversal::Error> {
7194 if let Some(added) = self.n0_nat_traversal.add_local_address(address)? {
7195 self.spaces[SpaceId::Data].pending.add_address.insert(added);
7196 };
7197 Ok(())
7198 }
7199
7200 pub fn remove_nat_traversal_address(
7204 &mut self,
7205 address: SocketAddr,
7206 ) -> Result<(), n0_nat_traversal::Error> {
7207 if let Some(removed) = self.n0_nat_traversal.remove_local_address(address)? {
7208 self.spaces[SpaceId::Data]
7209 .pending
7210 .remove_address
7211 .insert(removed);
7212 }
7213 Ok(())
7214 }
7215
7216 pub fn get_local_nat_traversal_addresses(
7218 &self,
7219 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> {
7220 self.n0_nat_traversal.get_local_nat_traversal_addresses()
7221 }
7222
7223 pub fn get_remote_nat_traversal_addresses(
7225 &self,
7226 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> {
7227 Ok(self
7228 .n0_nat_traversal
7229 .client_side()?
7230 .get_remote_nat_traversal_addresses())
7231 }
7232
7233 pub fn initiate_nat_traversal_round(
7245 &mut self,
7246 now: Instant,
7247 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> {
7248 if self.state.is_closed() {
7249 return Err(n0_nat_traversal::Error::Closed);
7250 }
7251
7252 let ipv6 = self.is_ipv6();
7253 let client_state = self.n0_nat_traversal.client_side_mut()?;
7254 let (mut reach_out_frames, probed_addrs) =
7255 client_state.initiate_nat_traversal_round(ipv6)?;
7256 if let Some(delay) = self.n0_nat_traversal.retry_delay(self.config.initial_rtt) {
7257 self.timers.set(
7258 Timer::Conn(ConnTimer::NatTraversalProbeRetry),
7259 now + delay,
7260 self.qlog.with_time(now),
7261 );
7262 }
7263
7264 self.spaces[SpaceId::Data]
7265 .pending
7266 .reach_out
7267 .append(&mut reach_out_frames);
7268
7269 Ok(probed_addrs)
7270 }
7271
7272 fn is_handshake_confirmed(&self) -> bool {
7281 !self.is_handshaking() && !self.crypto_state.has_keys(EncryptionLevel::Handshake)
7282 }
7283}
7284
7285impl fmt::Debug for Connection {
7286 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7287 f.debug_struct("Connection")
7288 .field("handshake_cid", &self.handshake_cid)
7289 .finish()
7290 }
7291}
7292
7293#[derive(Debug, Default)]
7299struct AbandonedPaths(ArrayRangeSet<ABANDONED_PATH_INLINE_RANGES, u32>);
7300
7301const ABANDONED_PATH_INLINE_RANGES: usize = 16;
7306
7307impl AbandonedPaths {
7308 fn len(&self) -> u32 {
7310 self.0.elts_count()
7311 }
7312
7313 fn max(&self) -> Option<PathId> {
7315 self.0.max().map(PathId::from)
7316 }
7317
7318 fn contains(&self, val: &PathId) -> bool {
7320 self.0.contains(val.as_u32())
7321 }
7322
7323 fn insert(&mut self, val: PathId) {
7325 self.0.insert_one(val.as_u32());
7326 }
7327}
7328
7329pub trait NetworkChangeHint: fmt::Debug + 'static {
7331 fn is_path_recoverable(&self, path_id: PathId, network_path: FourTuple) -> bool;
7340}
7341
7342#[derive(Debug)]
7344enum PollPathSpaceStatus {
7345 NothingToSend {
7347 path_blocked: PathBlocked,
7350 },
7351 WrotePacket {
7353 last_packet_number: u64,
7355 pad_datagram: PadDatagram,
7369 },
7370 Send {
7377 last_packet_number: u64,
7379 },
7380}
7381
7382#[derive(Debug, Copy, Clone)]
7388struct PathSchedulingInfo {
7389 is_abandoned: bool,
7395 may_send_data: bool,
7413 may_send_close: bool,
7419 may_self_abandon: bool,
7420}
7421
7422#[derive(Debug, Copy, Clone, PartialEq, Eq)]
7423enum PathBlocked {
7424 No,
7425 AntiAmplification,
7426 Congestion,
7427 Pacing,
7428}
7429
7430enum ConnectionSide {
7432 Client {
7433 token: Bytes,
7435 token_store: Arc<dyn TokenStore>,
7436 server_name: String,
7437 },
7438 Server {
7439 server_config: Arc<ServerConfig>,
7440 },
7441}
7442
7443impl ConnectionSide {
7444 fn is_client(&self) -> bool {
7445 self.side().is_client()
7446 }
7447
7448 fn is_server(&self) -> bool {
7449 self.side().is_server()
7450 }
7451
7452 fn side(&self) -> Side {
7453 match *self {
7454 Self::Client { .. } => Side::Client,
7455 Self::Server { .. } => Side::Server,
7456 }
7457 }
7458}
7459
7460impl From<SideArgs> for ConnectionSide {
7461 fn from(side: SideArgs) -> Self {
7462 match side {
7463 SideArgs::Client {
7464 token_store,
7465 server_name,
7466 } => Self::Client {
7467 token: token_store.take(&server_name).unwrap_or_default(),
7468 token_store,
7469 server_name,
7470 },
7471 SideArgs::Server {
7472 server_config,
7473 pref_addr_cid: _,
7474 path_validated: _,
7475 } => Self::Server { server_config },
7476 }
7477 }
7478}
7479
7480pub(crate) enum SideArgs {
7482 Client {
7483 token_store: Arc<dyn TokenStore>,
7484 server_name: String,
7485 },
7486 Server {
7487 server_config: Arc<ServerConfig>,
7488 pref_addr_cid: Option<ConnectionId>,
7489 path_validated: bool,
7490 },
7491}
7492
7493impl SideArgs {
7494 pub(crate) fn pref_addr_cid(&self) -> Option<ConnectionId> {
7495 match *self {
7496 Self::Client { .. } => None,
7497 Self::Server { pref_addr_cid, .. } => pref_addr_cid,
7498 }
7499 }
7500
7501 pub(crate) fn path_validated(&self) -> bool {
7502 match *self {
7503 Self::Client { .. } => true,
7504 Self::Server { path_validated, .. } => path_validated,
7505 }
7506 }
7507
7508 pub(crate) fn side(&self) -> Side {
7509 match *self {
7510 Self::Client { .. } => Side::Client,
7511 Self::Server { .. } => Side::Server,
7512 }
7513 }
7514}
7515
7516#[derive(Debug, Error, Clone, PartialEq, Eq)]
7518pub enum ConnectionError {
7519 #[error("peer doesn't implement any supported version")]
7521 VersionMismatch,
7522 #[error(transparent)]
7524 TransportError(#[from] TransportError),
7525 #[error("aborted by peer: {0}")]
7527 ConnectionClosed(frame::ConnectionClose),
7528 #[error("closed by peer: {0}")]
7530 ApplicationClosed(frame::ApplicationClose),
7531 #[error("reset by peer")]
7533 Reset,
7534 #[error("timed out")]
7540 TimedOut,
7541 #[error("closed")]
7543 LocallyClosed,
7544 #[error("CIDs exhausted")]
7548 CidsExhausted,
7549}
7550
7551impl From<Close> for ConnectionError {
7552 fn from(x: Close) -> Self {
7553 match x {
7554 Close::Connection(reason) => Self::ConnectionClosed(reason),
7555 Close::Application(reason) => Self::ApplicationClosed(reason),
7556 }
7557 }
7558}
7559
7560impl From<ConnectionError> for io::Error {
7562 fn from(x: ConnectionError) -> Self {
7563 use ConnectionError::*;
7564 let kind = match x {
7565 TimedOut => io::ErrorKind::TimedOut,
7566 Reset => io::ErrorKind::ConnectionReset,
7567 ApplicationClosed(_) | ConnectionClosed(_) => io::ErrorKind::ConnectionAborted,
7568 TransportError(_) | VersionMismatch | LocallyClosed | CidsExhausted => {
7569 io::ErrorKind::Other
7570 }
7571 };
7572 Self::new(kind, x)
7573 }
7574}
7575
7576#[derive(Debug, Error, PartialEq, Eq, Clone, Copy)]
7579pub enum PathError {
7580 #[error("multipath extension not negotiated")]
7582 MultipathNotNegotiated,
7583 #[error("the server side may not open a path")]
7585 ServerSideNotAllowed,
7586 #[error("maximum number of concurrent paths reached")]
7588 MaxPathIdReached,
7589 #[error("remoted CIDs exhausted")]
7591 RemoteCidsExhausted,
7592 #[error("path validation failed")]
7594 ValidationFailed,
7595 #[error("invalid remote address")]
7597 InvalidRemoteAddress(SocketAddr),
7598}
7599
7600#[derive(Debug, Error, Clone, Eq, PartialEq)]
7602pub enum ClosePathError {
7603 #[error("Multipath extension not negotiated")]
7605 MultipathNotNegotiated,
7606 #[error("closed path")]
7608 ClosedPath,
7609 #[error("last open path")]
7613 LastOpenPath,
7614}
7615
7616#[derive(Debug, Error, Clone, Copy)]
7618#[error("Multipath extension not negotiated")]
7619pub struct MultipathNotNegotiated {
7620 _private: (),
7621}
7622
7623#[derive(Debug)]
7625pub enum Event {
7626 HandshakeDataReady,
7628 Connected,
7630 HandshakeConfirmed,
7632 ConnectionLost {
7639 reason: ConnectionError,
7641 },
7642 Stream(StreamEvent),
7644 DatagramReceived,
7646 DatagramsUnblocked,
7648 Path(PathEvent),
7650 NatTraversal(n0_nat_traversal::Event),
7652}
7653
7654impl From<PathEvent> for Event {
7655 fn from(source: PathEvent) -> Self {
7656 Self::Path(source)
7657 }
7658}
7659
7660fn get_max_ack_delay(params: &TransportParameters) -> Duration {
7661 Duration::from_micros(params.max_ack_delay.0 * 1000)
7662}
7663
7664const MAX_BACKOFF_EXPONENT: u32 = 16;
7666
7667const MAX_PTO_INTERVAL: Duration = Duration::from_secs(2);
7671
7672const MIN_IDLE_FOR_FAST_PTO: Duration = Duration::from_secs(25);
7674
7675const MAX_PTO_FAST_INTERVAL: Duration = Duration::from_secs(1);
7680
7681const SLOW_RTT_THRESHOLD: Duration =
7686 Duration::from_millis((MAX_PTO_INTERVAL.as_millis() as u64 * 2) / 3);
7687
7688const MIN_PACKET_SPACE: usize = MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE + 32;
7696
7697const MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE: usize =
7703 1 + 4 + 1 + MAX_CID_SIZE + 1 + MAX_CID_SIZE + VarInt::from_u32(u16::MAX as u32).size() + 4;
7704
7705#[derive(Default)]
7706struct SentFrames {
7707 retransmits: ThinRetransmits,
7708 path_retransmits: PathRetransmits,
7709 largest_acked: FxHashMap<PathId, u64>,
7711 stream_frames: StreamMetaVec,
7712 non_retransmits: bool,
7714 requires_padding: bool,
7716}
7717
7718impl SentFrames {
7719 fn is_ack_only(&self, streams: &StreamsState) -> bool {
7721 !self.largest_acked.is_empty()
7722 && !self.non_retransmits
7723 && self.stream_frames.is_empty()
7724 && self.retransmits.is_empty(streams)
7725 }
7726
7727 fn retransmits_mut(&mut self) -> &mut Retransmits {
7728 self.retransmits.get_or_create()
7729 }
7730
7731 fn record_sent_frame(&mut self, frame: frame::EncodableFrame<'_>) {
7732 use frame::EncodableFrame::*;
7733 match frame {
7734 PathAck(path_ack_encoder) => {
7735 if let Some(max) = path_ack_encoder.ranges.max() {
7736 self.largest_acked.insert(path_ack_encoder.path_id, max);
7737 }
7738 }
7739 Ack(ack_encoder) => {
7740 if let Some(max) = ack_encoder.ranges.max() {
7741 self.largest_acked.insert(PathId::ZERO, max);
7742 }
7743 }
7744 Close(_) => { }
7745 PathResponse(_) => self.non_retransmits = true,
7746 HandshakeDone(_) => self.retransmits_mut().handshake_done = true,
7747 ReachOut(frame) => self.retransmits_mut().reach_out.push(frame),
7748 ObservedAddr(_) => self.path_retransmits.observed_address = true,
7749 Ping(_) => self.non_retransmits = true,
7750 ImmediateAck(_) => self.non_retransmits = true,
7751 AckFrequency(_) => self.retransmits_mut().ack_frequency = true,
7752 PathChallenge(_) => self.non_retransmits = true,
7753 Crypto(crypto) => self.retransmits_mut().crypto.push_back(crypto),
7754 PathAbandon(path_abandon) => {
7755 self.retransmits_mut()
7756 .path_abandon
7757 .entry(path_abandon.path_id)
7758 .or_insert(path_abandon.error_code);
7759 }
7760 PathStatusAvailable(frame::PathStatusAvailable { path_id, .. })
7761 | PathStatusBackup(frame::PathStatusBackup { path_id, .. }) => {
7762 self.retransmits_mut().path_status.insert(path_id);
7763 }
7764 MaxPathId(_) => self.retransmits_mut().max_path_id = true,
7765 PathsBlocked(frame::PathsBlocked(path_id)) => {
7766 let paths_blocked = &mut self.retransmits_mut().paths_blocked;
7767 *paths_blocked = cmp::max(*paths_blocked, Some(path_id));
7768 }
7769 PathCidsBlocked(path_cids_blocked) => {
7770 self.retransmits_mut()
7771 .path_cids_blocked
7772 .entry(path_cids_blocked.path_id)
7773 .and_modify(|next_seq| {
7774 *next_seq = cmp::max(*next_seq, path_cids_blocked.next_seq);
7775 })
7776 .or_insert(path_cids_blocked.next_seq);
7777 }
7778 ResetStream(reset) => self
7779 .retransmits_mut()
7780 .reset_stream
7781 .push((reset.id, reset.error_code)),
7782 StopSending(stop_sending) => self.retransmits_mut().stop_sending.push(stop_sending),
7783 NewConnectionId(new_cid) => self.retransmits_mut().new_cids.push(new_cid.issued()),
7784 RetireConnectionId(retire_cid) => self
7785 .retransmits_mut()
7786 .retire_cids
7787 .push((retire_cid.path_id.unwrap_or_default(), retire_cid.sequence)),
7788 Datagram(_) => self.non_retransmits = true,
7789 NewToken(_) => {}
7790 AddAddress(add_address) => {
7791 self.retransmits_mut().add_address.insert(add_address);
7792 }
7793 RemoveAddress(remove_address) => {
7794 self.retransmits_mut().remove_address.insert(remove_address);
7795 }
7796 StreamMeta(stream_meta_encoder) => self.stream_frames.push(stream_meta_encoder.meta),
7797 MaxData(_) => self.retransmits_mut().max_data = true,
7798 MaxStreamData(max) => {
7799 self.retransmits_mut().max_stream_data.insert(max.id);
7800 }
7801 MaxStreams(max_streams) => {
7802 self.retransmits_mut().max_stream_id[max_streams.dir as usize] = true
7803 }
7804 StreamsBlocked(streams_blocked) => {
7805 self.retransmits_mut().streams_blocked[streams_blocked.dir as usize] = true
7806 }
7807 }
7808 }
7809}
7810
7811fn negotiate_max_idle_timeout(x: Option<VarInt>, y: Option<VarInt>) -> Option<Duration> {
7823 match (x, y) {
7824 (Some(VarInt(0)) | None, Some(VarInt(0)) | None) => None,
7825 (Some(VarInt(0)) | None, Some(y)) => Some(Duration::from_millis(y.0)),
7826 (Some(x), Some(VarInt(0)) | None) => Some(Duration::from_millis(x.0)),
7827 (Some(x), Some(y)) => Some(Duration::from_millis(cmp::min(x, y).0)),
7828 }
7829}
7830
7831#[cfg(test)]
7832mod tests {
7833 use super::*;
7834
7835 #[test]
7836 fn negotiate_max_idle_timeout_commutative() {
7837 let test_params = [
7838 (None, None, None),
7839 (None, Some(VarInt(0)), None),
7840 (None, Some(VarInt(2)), Some(Duration::from_millis(2))),
7841 (Some(VarInt(0)), Some(VarInt(0)), None),
7842 (
7843 Some(VarInt(2)),
7844 Some(VarInt(0)),
7845 Some(Duration::from_millis(2)),
7846 ),
7847 (
7848 Some(VarInt(1)),
7849 Some(VarInt(4)),
7850 Some(Duration::from_millis(1)),
7851 ),
7852 ];
7853
7854 for (left, right, result) in test_params {
7855 assert_eq!(negotiate_max_idle_timeout(left, right), result);
7856 assert_eq!(negotiate_max_idle_timeout(right, left), result);
7857 }
7858 }
7859
7860 #[test]
7861 fn abandoned_paths() {
7862 let mut t = AbandonedPaths::default();
7863
7864 t.insert(PathId(0));
7865 t.insert(PathId(1));
7866 assert_eq!(t.len(), 2);
7867 assert_eq!(t.0.range_count(), 1); assert!(t.contains(&PathId(0)));
7869 assert!(t.contains(&PathId(1)));
7870 assert!(!t.contains(&PathId(2)));
7871 assert!(!t.contains(&PathId(3)));
7872 assert_eq!(t.max(), Some(PathId(1)));
7873
7874 t.insert(PathId(3));
7875 assert_eq!(t.len(), 3);
7876 assert_eq!(t.0.range_count(), 2); assert!(t.contains(&PathId(0)));
7878 assert!(t.contains(&PathId(1)));
7879 assert!(!t.contains(&PathId(2)));
7880 assert!(t.contains(&PathId(3)));
7881 assert_eq!(t.max(), Some(PathId(3)));
7882
7883 t.insert(PathId(2));
7884 assert_eq!(t.len(), 4);
7885 assert_eq!(t.0.range_count(), 1); assert!(t.contains(&PathId(0)));
7887 assert!(t.contains(&PathId(1)));
7888 assert!(t.contains(&PathId(2)));
7889 assert!(t.contains(&PathId(3)));
7890 assert_eq!(t.max(), Some(PathId(3)));
7891 }
7892}