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,
27 connection::{
28 qlog::{QlogRecvPacket, QlogSink},
29 spaces::LostPacket,
30 stats::PathStatsMap,
31 timer::{ConnTimer, PathTimer},
32 },
33 crypto::{self, Keys},
34 frame::{
35 self, Close, DataBlocked, Datagram, FrameStruct, NewToken, ObservedAddr, StreamDataBlocked,
36 StreamsBlocked,
37 },
38 n0_nat_traversal,
39 packet::{
40 FixedLengthConnectionIdParser, Header, InitialHeader, InitialPacket, LongType, Packet,
41 PacketNumber, PartialDecode, SpaceId,
42 },
43 range_set::ArrayRangeSet,
44 shared::{
45 ConnectionEvent, ConnectionEventInner, ConnectionId, DatagramConnectionEvent, EcnCodepoint,
46 EndpointEvent, EndpointEventInner,
47 },
48 token::{ResetToken, Token, TokenPayload},
49 transport_parameters::TransportParameters,
50};
51
52mod ack_frequency;
53use ack_frequency::AckFrequencyState;
54
55mod assembler;
56pub use assembler::Chunk;
57
58mod cid_state;
59use cid_state::CidState;
60
61mod datagrams;
62use datagrams::DatagramState;
63pub use datagrams::{Datagrams, SendDatagramError};
64
65mod mtud;
66mod pacing;
67
68mod packet_builder;
69use packet_builder::{PacketBuilder, PadDatagram};
70
71mod packet_crypto;
72use packet_crypto::CryptoState;
73pub(crate) use packet_crypto::EncryptionLevel;
74
75mod paths;
76pub use paths::{
77 ClosedPath, PathAbandonReason, PathEvent, PathId, PathStatus, RttEstimator, SetPathStatusError,
78};
79use paths::{PathData, PathState};
80
81pub(crate) mod qlog;
82pub(crate) mod send_buffer;
83
84pub(crate) mod spaces;
85#[cfg(fuzzing)]
86pub use spaces::Retransmits;
87#[cfg(not(fuzzing))]
88use spaces::Retransmits;
89pub(crate) use spaces::SpaceKind;
90use spaces::{PacketSpace, SendableFrames, SentPacket, ThinRetransmits};
91
92mod stats;
93pub use stats::{ConnectionStats, FrameStats, PathStats, UdpStats};
94
95mod streams;
96#[cfg(fuzzing)]
97pub use streams::StreamsState;
98#[cfg(not(fuzzing))]
99use streams::StreamsState;
100pub use streams::{
101 Chunks, ClosedStream, FinishError, ReadError, ReadableError, RecvStream, SendStream,
102 ShouldTransmit, StreamEvent, Streams, WriteError,
103};
104
105mod timer;
106use timer::{Timer, TimerTable};
107
108mod transmit_buf;
109use transmit_buf::TransmitBuf;
110
111mod state;
112
113#[cfg(not(fuzzing))]
114use state::State;
115#[cfg(fuzzing)]
116pub use state::State;
117use state::StateType;
118
119pub 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,
220
221 ack_frequency: AckFrequencyState,
225
226 receiving_ecn: bool,
231 total_authed_packets: u64,
233
234 next_observed_addr_seq_no: VarInt,
239
240 streams: StreamsState,
241 remote_cids: FxHashMap<PathId, CidQueue>,
247 local_cid_state: FxHashMap<PathId, CidState>,
254 datagrams: DatagramState,
256 path_stats: PathStatsMap,
258 partial_stats: ConnectionStats,
264 version: u32,
266
267 max_concurrent_paths: NonZeroU32,
276 local_max_path_id: PathId,
291 remote_max_path_id: PathId,
297 max_path_id_with_cids: PathId,
303 abandoned_paths: AbandonedPaths,
309
310 n0_nat_traversal: n0_nat_traversal::State,
312 qlog: QlogSink,
313}
314
315impl Connection {
316 pub(crate) fn new(
317 endpoint_config: Arc<EndpointConfig>,
318 config: Arc<TransportConfig>,
319 init_cid: ConnectionId,
320 local_cid: ConnectionId,
321 remote_cid: ConnectionId,
322 network_path: FourTuple,
323 crypto: Box<dyn crypto::Session>,
324 cid_gen: &dyn ConnectionIdGenerator,
325 now: Instant,
326 version: u32,
327 allow_mtud: bool,
328 rng_seed: [u8; 32],
329 side_args: SideArgs,
330 qlog: QlogSink,
331 ) -> Self {
332 let pref_addr_cid = side_args.pref_addr_cid();
333 let path_validated = side_args.path_validated();
334 let connection_side = ConnectionSide::from(side_args);
335 let side = connection_side.side();
336 let mut rng = StdRng::from_seed(rng_seed);
337 let initial_space = PacketSpace::new(now, SpaceId::Initial, &mut rng);
338 let handshake_space = PacketSpace::new(now, SpaceId::Handshake, &mut rng);
339 #[cfg(test)]
340 let data_space = match config.deterministic_packet_numbers {
341 true => PacketSpace::new_deterministic(now, SpaceId::Data),
342 false => PacketSpace::new(now, SpaceId::Data, &mut rng),
343 };
344 #[cfg(not(test))]
345 let data_space = PacketSpace::new(now, SpaceId::Data, &mut rng);
346 let state = State::handshake(state::Handshake {
347 remote_cid_set: side.is_server(),
348 expected_token: Bytes::new(),
349 client_hello: None,
350 allow_server_migration: side.is_client() && config.server_handshake_migration,
351 });
352 let local_cid_state = FxHashMap::from_iter([(
353 PathId::ZERO,
354 CidState::new(
355 cid_gen.cid_len(),
356 cid_gen.cid_lifetime(),
357 now,
358 if pref_addr_cid.is_some() { 2 } else { 1 },
359 ),
360 )]);
361
362 let mut path = PathData::new(network_path, allow_mtud, None, 0, now, &config);
363 path.open_status = paths::OpenStatus::Informed;
364 let mut this = Self {
365 endpoint_config,
366 crypto_state: CryptoState::new(crypto, init_cid, side, &mut rng),
367 handshake_cid: local_cid,
368 remote_handshake_cid: remote_cid,
369 local_cid_state,
370 paths: BTreeMap::from_iter([(
371 PathId::ZERO,
372 PathState {
373 data: path,
374 prev: None,
375 },
376 )]),
377 path_generation_counter: 0,
378 allow_mtud,
379 state,
380 side: connection_side,
381 peer_params: TransportParameters::default(),
382 original_remote_cid: remote_cid,
383 initial_dst_cid: init_cid,
384 retry_src_cid: None,
385 events: VecDeque::new(),
386 endpoint_events: VecDeque::new(),
387 spin_enabled: config.allow_spin && rng.random_ratio(7, 8),
388 spin: false,
389 spaces: [initial_space, handshake_space, data_space],
390 highest_space: SpaceKind::Initial,
391 idle_timeout: match config.max_idle_timeout {
392 None | Some(VarInt(0)) => None,
393 Some(dur) => Some(Duration::from_millis(dur.0)),
394 },
395 timers: TimerTable::default(),
396 authentication_failures: 0,
397 connection_close_pending: false,
398
399 ack_frequency: AckFrequencyState::new(get_max_ack_delay(
400 &TransportParameters::default(),
401 )),
402
403 receiving_ecn: false,
404 total_authed_packets: 0,
405
406 next_observed_addr_seq_no: 0u32.into(),
407
408 streams: StreamsState::new(
409 side,
410 config.max_concurrent_uni_streams,
411 config.max_concurrent_bidi_streams,
412 config.send_window,
413 config.receive_window,
414 config.stream_receive_window,
415 ),
416 datagrams: DatagramState::default(),
417 config,
418 remote_cids: FxHashMap::from_iter([(PathId::ZERO, CidQueue::new(remote_cid))]),
419 rng,
420 path_stats: Default::default(),
421 partial_stats: ConnectionStats::default(),
422 version,
423
424 max_concurrent_paths: NonZeroU32::MIN,
426 local_max_path_id: PathId::ZERO,
427 remote_max_path_id: PathId::ZERO,
428 max_path_id_with_cids: PathId::ZERO,
429 abandoned_paths: Default::default(),
430
431 n0_nat_traversal: Default::default(),
432 qlog,
433 };
434 if path_validated {
435 this.on_path_validated(PathId::ZERO);
436 }
437 if side.is_client() {
438 this.write_crypto();
440 this.init_0rtt(now);
441 }
442 this.qlog
443 .emit_tuple_assigned(PathId::ZERO, network_path, now);
444 this
445 }
446
447 #[must_use]
455 pub fn poll_timeout(&mut self) -> Option<Instant> {
456 self.timers.peek()
457 }
458
459 #[must_use]
465 pub fn poll(&mut self) -> Option<Event> {
466 if let Some(x) = self.events.pop_front() {
467 return Some(x);
468 }
469
470 if let Some(event) = self.streams.poll() {
471 return Some(Event::Stream(event));
472 }
473
474 if let Some(reason) = self.state.take_error() {
475 return Some(Event::ConnectionLost { reason });
476 }
477
478 None
479 }
480
481 #[must_use]
483 pub fn poll_endpoint_events(&mut self) -> Option<EndpointEvent> {
484 self.endpoint_events.pop_front().map(EndpointEvent)
485 }
486
487 #[must_use]
489 pub fn streams(&mut self) -> Streams<'_> {
490 Streams {
491 state: &mut self.streams,
492 conn_state: &self.state,
493 }
494 }
495
496 #[must_use]
498 pub fn recv_stream(&mut self, id: StreamId) -> RecvStream<'_> {
499 assert!(id.dir() == Dir::Bi || id.initiator() != self.side.side());
500 RecvStream {
501 id,
502 state: &mut self.streams,
503 pending: &mut self.spaces[SpaceId::Data].pending,
504 }
505 }
506
507 #[must_use]
509 pub fn send_stream(&mut self, id: StreamId) -> SendStream<'_> {
510 assert!(id.dir() == Dir::Bi || id.initiator() == self.side.side());
511 SendStream {
512 id,
513 state: &mut self.streams,
514 pending: &mut self.spaces[SpaceId::Data].pending,
515 conn_state: &self.state,
516 }
517 }
518
519 pub fn open_path_ensure(
536 &mut self,
537 network_path: FourTuple,
538 initial_status: PathStatus,
539 now: Instant,
540 ) -> Result<(PathId, bool), PathError> {
541 let existing_open_path = self.paths.iter().find(|(id, path)| {
542 network_path.is_probably_same_path(&path.data.network_path)
543 && !self.abandoned_paths.contains(id)
544 });
545 match existing_open_path {
546 Some((path_id, _state)) => Ok((*path_id, true)),
547 None => Ok((self.open_path(network_path, initial_status, now)?, false)),
548 }
549 }
550
551 pub fn open_path(
557 &mut self,
558 network_path: FourTuple,
559 initial_status: PathStatus,
560 now: Instant,
561 ) -> Result<PathId, PathError> {
562 if !self.is_multipath_negotiated() {
563 return Err(PathError::MultipathNotNegotiated);
564 }
565 if self.side().is_server() {
566 return Err(PathError::ServerSideNotAllowed);
567 }
568
569 let max_abandoned = self.abandoned_paths.max();
570 let max_used = self.paths.keys().last().copied();
571 let path_id = max_abandoned
572 .max(max_used)
573 .unwrap_or(PathId::ZERO)
574 .saturating_add(1u8);
575
576 if Some(path_id) > self.max_path_id() {
577 return Err(PathError::MaxPathIdReached);
578 }
579 if path_id > self.remote_max_path_id {
580 self.spaces[SpaceId::Data].pending.paths_blocked = true;
581 return Err(PathError::MaxPathIdReached);
582 }
583 if self
584 .remote_cids
585 .get(&path_id)
586 .map(CidQueue::active)
587 .is_none()
588 {
589 self.spaces[SpaceId::Data]
590 .pending
591 .path_cids_blocked
592 .insert(path_id);
593 return Err(PathError::RemoteCidsExhausted);
594 }
595
596 let path = self.ensure_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_cids_blocked.retain(|&id| id != path_id);
691 pending_space.path_status.retain(|&id| id != path_id);
692
693 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_cids_blocked.retain(|&id| id != path_id);
699 retransmits.path_status.retain(|&id| id != path_id);
700 }
701 }
702 }
703
704 self.spaces[SpaceId::Data].for_path(path_id).loss_probes = 0;
709
710 debug_assert!(!self.state.is_drained()); self.endpoint_events
715 .push_back(EndpointEventInner::RetireResetToken(path_id));
716
717 self.abandoned_paths.insert(path_id);
718
719 for timer in timer::PathTimer::VALUES {
720 let keep_timer = match timer {
722 PathTimer::PathValidationFailed
726 | PathTimer::PathChallengeLost
727 | PathTimer::AbandonFromValidation => false,
728 PathTimer::PathKeepAlive | PathTimer::PathIdle => false,
731 PathTimer::MaxAckDelay => false,
734 PathTimer::PathDrained => false,
737 PathTimer::LossDetection => true,
740 PathTimer::Pacing => true,
744 };
745
746 if !keep_timer {
747 let qlog = self.qlog.with_time(now);
748 self.timers.stop(Timer::PerPath(path_id, timer), qlog);
749 }
750 }
751
752 self.set_loss_detection_timer(now, path_id);
757
758 self.events.push_back(Event::Path(PathEvent::Abandoned {
760 id: path_id,
761 reason,
762 }));
763 }
764
765 #[track_caller]
769 fn path_data(&self, path_id: PathId) -> &PathData {
770 if let Some(data) = self.paths.get(&path_id) {
771 &data.data
772 } else {
773 panic!(
774 "unknown path: {path_id}, currently known paths: {:?}",
775 self.paths.keys().collect::<Vec<_>>()
776 );
777 }
778 }
779
780 #[track_caller]
784 fn path_data_mut(&mut self, path_id: PathId) -> &mut PathData {
785 &mut self.paths.get_mut(&path_id).expect("known path").data
786 }
787
788 fn path(&self, path_id: PathId) -> Option<&PathData> {
790 self.paths.get(&path_id).map(|path_state| &path_state.data)
791 }
792
793 fn path_mut(&mut self, path_id: PathId) -> Option<&mut PathData> {
795 self.paths
796 .get_mut(&path_id)
797 .map(|path_state| &mut path_state.data)
798 }
799
800 pub fn paths(&self) -> Vec<PathId> {
804 self.paths.keys().copied().collect()
805 }
806
807 pub fn path_status(&self, path_id: PathId) -> Result<PathStatus, ClosedPath> {
809 self.path(path_id)
810 .map(PathData::local_status)
811 .ok_or(ClosedPath { _private: () })
812 }
813
814 pub fn network_path(&self, path_id: PathId) -> Result<FourTuple, ClosedPath> {
816 self.path(path_id)
817 .map(|path| path.network_path)
818 .ok_or(ClosedPath { _private: () })
819 }
820
821 pub fn set_path_status(
825 &mut self,
826 path_id: PathId,
827 status: PathStatus,
828 ) -> Result<PathStatus, SetPathStatusError> {
829 if !self.is_multipath_negotiated() {
830 return Err(SetPathStatusError::MultipathNotNegotiated);
831 }
832 let path = self
833 .path_mut(path_id)
834 .ok_or(SetPathStatusError::ClosedPath)?;
835 let prev = match path.status.local_update(status) {
836 Some(prev) => {
837 self.spaces[SpaceId::Data]
838 .pending
839 .path_status
840 .insert(path_id);
841 prev
842 }
843 None => path.local_status(),
844 };
845 Ok(prev)
846 }
847
848 pub fn remote_path_status(&self, path_id: PathId) -> Option<PathStatus> {
853 self.path(path_id).and_then(|path| path.remote_status())
854 }
855
856 pub fn set_path_max_idle_timeout(
865 &mut self,
866 now: Instant,
867 path_id: PathId,
868 timeout: Option<Duration>,
869 ) -> Result<Option<Duration>, ClosedPath> {
870 let path = self
871 .paths
872 .get_mut(&path_id)
873 .ok_or(ClosedPath { _private: () })?;
874 let prev = std::mem::replace(&mut path.data.idle_timeout, timeout);
875
876 if !self.state.is_closed() {
878 if let Some(new_timeout) = timeout {
879 let timer = Timer::PerPath(path_id, PathTimer::PathIdle);
880 let deadline = match (prev, self.timers.get(timer)) {
881 (Some(old_timeout), Some(old_deadline)) => {
882 let last_activity = old_deadline.checked_sub(old_timeout).unwrap_or(now);
883 last_activity + new_timeout
884 }
885 _ => now + new_timeout,
886 };
887 self.timers.set(timer, deadline, self.qlog.with_time(now));
888 } else {
889 self.timers.stop(
890 Timer::PerPath(path_id, PathTimer::PathIdle),
891 self.qlog.with_time(now),
892 );
893 }
894 }
895
896 Ok(prev)
897 }
898
899 pub fn set_path_keep_alive_interval(
905 &mut self,
906 path_id: PathId,
907 interval: Option<Duration>,
908 ) -> Result<Option<Duration>, ClosedPath> {
909 let path = self
910 .paths
911 .get_mut(&path_id)
912 .ok_or(ClosedPath { _private: () })?;
913 Ok(std::mem::replace(&mut path.data.keep_alive, interval))
914 }
915
916 fn find_validated_path_on_network_path(
920 &self,
921 network_path: FourTuple,
922 ) -> Option<(&PathId, &PathState)> {
923 self.paths.iter().find(|(path_id, path_state)| {
924 path_state.data.validated
925 && network_path.is_probably_same_path(&path_state.data.network_path)
927 && !self.abandoned_paths.contains(path_id)
928 })
929 }
933
934 fn ensure_path(
938 &mut self,
939 path_id: PathId,
940 network_path: FourTuple,
941 now: Instant,
942 pn: Option<u64>,
943 ) -> &mut PathData {
944 let valid_path = self.find_validated_path_on_network_path(network_path);
945 let validated = valid_path.is_some();
946 let initial_rtt = valid_path.map(|(_, path)| path.data.rtt.conservative());
947 let vacant_entry = match self.paths.entry(path_id) {
948 btree_map::Entry::Vacant(vacant_entry) => vacant_entry,
949 btree_map::Entry::Occupied(occupied_entry) => {
950 return &mut occupied_entry.into_mut().data;
951 }
952 };
953
954 debug!(%validated, %path_id, %network_path, "path added");
955
956 self.timers.stop(
958 Timer::Conn(ConnTimer::NoAvailablePath),
959 self.qlog.with_time(now),
960 );
961 let peer_max_udp_payload_size =
962 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()).unwrap_or(u16::MAX);
963 self.path_generation_counter = self.path_generation_counter.wrapping_add(1);
964 let mut data = PathData::new(
965 network_path,
966 self.allow_mtud,
967 Some(peer_max_udp_payload_size),
968 self.path_generation_counter,
969 now,
970 &self.config,
971 );
972
973 data.validated = validated;
974 if let Some(initial_rtt) = initial_rtt {
975 data.rtt.reset_initial_rtt(initial_rtt);
976 }
977
978 data.pending_on_path_challenge = true;
981
982 let path = vacant_entry.insert(PathState { data, prev: None });
983
984 let mut pn_space = spaces::PacketNumberSpace::new(now, SpaceId::Data, &mut self.rng);
985 if let Some(pn) = pn {
986 pn_space.dedup.insert(pn);
987 }
988 self.spaces[SpaceId::Data]
989 .number_spaces
990 .insert(path_id, pn_space);
991 self.qlog.emit_tuple_assigned(path_id, network_path, now);
992
993 if !self.remote_cids.contains_key(&path_id) {
997 debug!(%path_id, "Remote opened path without issuing CIDs");
998 self.spaces[SpaceId::Data]
999 .pending
1000 .path_cids_blocked
1001 .insert(path_id);
1002 }
1005
1006 &mut path.data
1007 }
1008
1009 #[must_use]
1019 pub fn poll_transmit(
1020 &mut self,
1021 now: Instant,
1022 max_datagrams: NonZeroUsize,
1023 buf: &mut Vec<u8>,
1024 ) -> Option<Transmit> {
1025 let max_datagrams = match self.config.enable_segmentation_offload {
1026 false => NonZeroUsize::MIN,
1027 true => max_datagrams,
1028 };
1029
1030 let connection_close_pending = match self.state.as_type() {
1036 StateType::Drained => {
1037 for path in self.paths.values_mut() {
1038 path.data.app_limited = true;
1039 }
1040 return None;
1041 }
1042 StateType::Draining | StateType::Closed => {
1043 if !self.connection_close_pending {
1046 for path in self.paths.values_mut() {
1047 path.data.app_limited = true;
1048 }
1049 return None;
1050 }
1051 true
1052 }
1053 _ => false,
1054 };
1055
1056 if let Some(config) = &self.config.ack_frequency_config {
1058 let rtt = self
1059 .paths
1060 .values()
1061 .map(|p| p.data.rtt.get())
1062 .min()
1063 .expect("one path exists");
1064 self.spaces[SpaceId::Data].pending.ack_frequency = self
1065 .ack_frequency
1066 .should_send_ack_frequency(rtt, config, &self.peer_params)
1067 && self.highest_space == SpaceKind::Data
1068 && self.peer_supports_ack_frequency();
1069 }
1070
1071 let mut next_path_id = self.paths.first_entry().map(|e| *e.key());
1072 while let Some(path_id) = next_path_id {
1073 if !connection_close_pending
1074 && let Some(transmit) = self.poll_transmit_off_path(now, buf, path_id)
1075 {
1076 return Some(transmit);
1077 }
1078
1079 let info = self.scheduling_info(path_id);
1080 if let Some(transmit) = self.poll_transmit_on_path(
1081 now,
1082 buf,
1083 path_id,
1084 max_datagrams,
1085 &info,
1086 connection_close_pending,
1087 ) {
1088 return Some(transmit);
1089 }
1090
1091 debug_assert!(
1094 buf.is_empty(),
1095 "nothing to send on path but buffer not empty"
1096 );
1097
1098 next_path_id = self.paths.keys().find(|i| **i > path_id).copied();
1099 }
1100
1101 debug_assert!(
1103 buf.is_empty(),
1104 "there was data in the buffer, but it was not sent"
1105 );
1106
1107 if self.state.is_established() {
1108 let mut next_path_id = self.paths.first_entry().map(|e| *e.key());
1110 while let Some(path_id) = next_path_id {
1111 if let Some(transmit) = self.poll_transmit_mtu_probe(now, buf, path_id) {
1112 return Some(transmit);
1113 }
1114 next_path_id = self.paths.keys().find(|i| **i > path_id).copied();
1115 }
1116 }
1117
1118 None
1119 }
1120
1121 fn scheduling_info(&self, path_id: PathId) -> PathSchedulingInfo {
1139 let have_validated_status_available_space = self.paths.iter().any(|(path_id, path)| {
1141 self.remote_cids.contains_key(path_id)
1142 && !self.abandoned_paths.contains(path_id)
1143 && path.data.validated
1144 && path.data.local_status() == PathStatus::Available
1145 });
1146
1147 let have_validated_space = self.paths.iter().any(|(path_id, path)| {
1149 self.remote_cids.contains_key(path_id)
1150 && !self.abandoned_paths.contains(path_id)
1151 && path.data.validated
1152 });
1153
1154 let is_handshaking = self.is_handshaking();
1155 let has_cids = self.remote_cids.contains_key(&path_id);
1156 let is_abandoned = self.abandoned_paths.contains(&path_id);
1157 let path_data = self.path_data(path_id);
1158 let validated = path_data.validated;
1159 let status = path_data.local_status();
1160
1161 let may_send_data = has_cids
1164 && !is_abandoned
1165 && if is_handshaking {
1166 true
1170 } else if !validated {
1171 false
1178 } else {
1179 match status {
1180 PathStatus::Available => {
1181 true
1183 }
1184 PathStatus::Backup => {
1185 !have_validated_status_available_space
1187 }
1188 }
1189 };
1190
1191 let may_send_close = has_cids
1196 && !is_abandoned
1197 && if !validated && have_validated_status_available_space {
1198 false
1200 } else {
1201 true
1203 };
1204
1205 let may_self_abandon = has_cids && validated && !have_validated_space;
1209
1210 PathSchedulingInfo {
1211 is_abandoned,
1212 may_send_data,
1213 may_send_close,
1214 may_self_abandon,
1215 }
1216 }
1217
1218 fn build_transmit(&mut self, path_id: PathId, transmit: TransmitBuf<'_>) -> Transmit {
1219 debug_assert!(
1220 !transmit.is_empty(),
1221 "must not be called with an empty transmit buffer"
1222 );
1223
1224 let network_path = self.path_data(path_id).network_path;
1225 trace!(
1226 segment_size = transmit.segment_size(),
1227 last_datagram_len = transmit.len() % transmit.segment_size(),
1228 %network_path,
1229 "sending {} bytes in {} datagrams",
1230 transmit.len(),
1231 transmit.num_datagrams()
1232 );
1233 self.path_data_mut(path_id)
1234 .inc_total_sent(transmit.len() as u64);
1235
1236 self.path_stats
1237 .for_path(path_id)
1238 .udp_tx
1239 .on_sent(transmit.num_datagrams() as u64, transmit.len());
1240
1241 Transmit {
1242 destination: network_path.remote,
1243 size: transmit.len(),
1244 ecn: if self.path_data(path_id).sending_ecn {
1245 Some(EcnCodepoint::Ect0)
1246 } else {
1247 None
1248 },
1249 segment_size: match transmit.num_datagrams() {
1250 1 => None,
1251 _ => Some(transmit.segment_size()),
1252 },
1253 src_ip: network_path.local_ip,
1254 }
1255 }
1256
1257 fn poll_transmit_off_path(
1259 &mut self,
1260 now: Instant,
1261 buf: &mut Vec<u8>,
1262 path_id: PathId,
1263 ) -> Option<Transmit> {
1264 if let Some(challenge) = self.send_prev_path_challenge(now, buf, path_id) {
1265 return Some(challenge);
1266 }
1267 if let Some(response) = self.send_off_path_path_response(now, buf, path_id) {
1268 return Some(response);
1269 }
1270 if let Some(challenge) = self.send_nat_traversal_path_challenge(now, buf, path_id) {
1271 return Some(challenge);
1272 }
1273 None
1274 }
1275
1276 #[must_use]
1283 fn poll_transmit_on_path(
1284 &mut self,
1285 now: Instant,
1286 buf: &mut Vec<u8>,
1287 path_id: PathId,
1288 max_datagrams: NonZeroUsize,
1289 scheduling_info: &PathSchedulingInfo,
1290 connection_close_pending: bool,
1291 ) -> Option<Transmit> {
1292 let Some(remote_cid) = self.remote_cids.get(&path_id).map(CidQueue::active) else {
1294 if !self.abandoned_paths.contains(&path_id) {
1295 debug!(%path_id, "no remote CIDs for path");
1296 }
1297 return None;
1298 };
1299
1300 let mut pad_datagram = PadDatagram::No;
1306
1307 let mut last_packet_number = None;
1311
1312 let mut congestion_blocked = false;
1315
1316 let pmtu = self.path_data(path_id).current_mtu().into();
1318 let mut transmit = TransmitBuf::new(buf, max_datagrams, pmtu);
1319
1320 for space_id in SpaceId::iter() {
1322 if path_id != PathId::ZERO && space_id != SpaceId::Data {
1324 continue;
1325 }
1326 match self.poll_transmit_path_space(
1327 now,
1328 &mut transmit,
1329 path_id,
1330 space_id,
1331 remote_cid,
1332 scheduling_info,
1333 connection_close_pending,
1334 pad_datagram,
1335 ) {
1336 PollPathSpaceStatus::NothingToSend {
1337 congestion_blocked: cb,
1338 } => {
1339 congestion_blocked |= cb;
1340 }
1343 PollPathSpaceStatus::WrotePacket {
1344 last_packet_number: pn,
1345 pad_datagram: pad,
1346 } => {
1347 debug_assert!(!transmit.is_empty(), "transmit must contain packets");
1348 last_packet_number = Some(pn);
1349 pad_datagram = pad;
1350 continue;
1355 }
1356 PollPathSpaceStatus::Send {
1357 last_packet_number: pn,
1358 } => {
1359 debug_assert!(!transmit.is_empty(), "transmit must contain packets");
1360 last_packet_number = Some(pn);
1361 break;
1362 }
1363 }
1364 }
1365
1366 if last_packet_number.is_some() || congestion_blocked {
1367 self.qlog.emit_recovery_metrics(
1368 path_id,
1369 &mut self
1370 .paths
1371 .get_mut(&path_id)
1372 .expect("path_id was iterated from self.paths above")
1373 .data,
1374 now,
1375 );
1376 }
1377
1378 self.path_data_mut(path_id).app_limited =
1379 last_packet_number.is_none() && !congestion_blocked;
1380
1381 match last_packet_number {
1382 Some(last_packet_number) => {
1383 self.path_data_mut(path_id).congestion.on_sent(
1386 now,
1387 transmit.len() as u64,
1388 last_packet_number,
1389 );
1390 Some(self.build_transmit(path_id, transmit))
1391 }
1392 None => None,
1393 }
1394 }
1395
1396 #[must_use]
1398 fn poll_transmit_path_space(
1399 &mut self,
1400 now: Instant,
1401 transmit: &mut TransmitBuf<'_>,
1402 path_id: PathId,
1403 space_id: SpaceId,
1404 remote_cid: ConnectionId,
1405 scheduling_info: &PathSchedulingInfo,
1406 connection_close_pending: bool,
1408 mut pad_datagram: PadDatagram,
1410 ) -> PollPathSpaceStatus {
1411 let mut last_packet_number = None;
1414
1415 loop {
1431 let max_packet_size = if transmit.datagram_remaining_mut() > 0 {
1433 transmit.datagram_remaining_mut()
1435 } else {
1436 transmit.segment_size()
1438 };
1439 let can_send =
1440 self.space_can_send(space_id, path_id, max_packet_size, connection_close_pending);
1441 let needs_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0;
1442 let space_will_send = {
1443 if scheduling_info.is_abandoned {
1444 scheduling_info.may_self_abandon
1449 && self.spaces[space_id]
1450 .pending
1451 .path_abandon
1452 .contains_key(&path_id)
1453 } else if can_send.close && scheduling_info.may_send_close {
1454 true
1456 } else if needs_loss_probe || can_send.space_specific {
1457 true
1460 } else {
1461 !can_send.is_empty() && scheduling_info.may_send_data
1464 }
1465 };
1466
1467 if !space_will_send {
1468 return match last_packet_number {
1471 Some(pn) => PollPathSpaceStatus::WrotePacket {
1472 last_packet_number: pn,
1473 pad_datagram,
1474 },
1475 None => {
1476 if self.crypto_state.has_keys(space_id.encryption_level())
1478 || (space_id == SpaceId::Data
1479 && self.crypto_state.has_keys(EncryptionLevel::ZeroRtt))
1480 {
1481 trace!(?space_id, %path_id, "nothing to send in space");
1482 }
1483 PollPathSpaceStatus::NothingToSend {
1484 congestion_blocked: false,
1485 }
1486 }
1487 };
1488 }
1489
1490 if transmit.datagram_remaining_mut() == 0 {
1494 let congestion_blocked =
1495 self.path_congestion_check(space_id, path_id, transmit, &can_send, now);
1496 if congestion_blocked != PathBlocked::No {
1497 return match last_packet_number {
1499 Some(pn) => PollPathSpaceStatus::WrotePacket {
1500 last_packet_number: pn,
1501 pad_datagram,
1502 },
1503 None => {
1504 return PollPathSpaceStatus::NothingToSend {
1505 congestion_blocked: true,
1506 };
1507 }
1508 };
1509 }
1510
1511 if transmit.num_datagrams() >= transmit.max_datagrams().get() {
1514 return match last_packet_number {
1517 Some(pn) => PollPathSpaceStatus::WrotePacket {
1518 last_packet_number: pn,
1519 pad_datagram,
1520 },
1521 None => {
1522 return PollPathSpaceStatus::NothingToSend {
1523 congestion_blocked: false,
1524 };
1525 }
1526 };
1527 }
1528
1529 if needs_loss_probe {
1530 let request_immediate_ack =
1532 space_id == SpaceId::Data && self.peer_supports_ack_frequency();
1533 self.spaces[space_id].queue_tail_loss_probe(
1534 path_id,
1535 request_immediate_ack,
1536 &self.streams,
1537 );
1538
1539 self.spaces[space_id].for_path(path_id).loss_probes -= 1; transmit.start_new_datagram_with_size(std::cmp::min(
1545 usize::from(INITIAL_MTU),
1546 transmit.segment_size(),
1547 ));
1548 } else {
1549 transmit.start_new_datagram();
1550 }
1551 trace!(count = transmit.num_datagrams(), "new datagram started");
1552
1553 pad_datagram = PadDatagram::No;
1555 }
1556
1557 if transmit.datagram_start_offset() < transmit.len() {
1560 debug_assert!(transmit.datagram_remaining_mut() >= MIN_PACKET_SPACE);
1561 }
1562
1563 if self.crypto_state.has_keys(EncryptionLevel::Initial)
1568 && space_id == SpaceId::Handshake
1569 && self.side.is_client()
1570 {
1571 self.discard_space(now, SpaceKind::Initial);
1574 }
1575 if let Some(ref mut prev) = self.crypto_state.prev_crypto {
1576 prev.update_unacked = false;
1577 }
1578
1579 let Some(mut builder) =
1580 PacketBuilder::new(now, space_id, path_id, remote_cid, transmit, self)
1581 else {
1582 return PollPathSpaceStatus::NothingToSend {
1589 congestion_blocked: false,
1590 };
1591 };
1592 last_packet_number = Some(builder.packet_number);
1593
1594 if space_id == SpaceId::Initial
1595 && (self.side.is_client() || can_send.is_ack_eliciting() || needs_loss_probe)
1596 {
1597 pad_datagram |= PadDatagram::ToMinMtu;
1599 }
1600 if space_id == SpaceId::Data && self.config.pad_to_mtu {
1601 pad_datagram |= PadDatagram::ToSegmentSize;
1602 }
1603
1604 if scheduling_info.may_send_close && can_send.close {
1605 trace!("sending CONNECTION_CLOSE");
1606 let is_multipath_negotiated = self.is_multipath_negotiated();
1611 for path_id in self.spaces[space_id]
1612 .number_spaces
1613 .iter()
1614 .filter(|(_, pns)| !pns.pending_acks.ranges().is_empty())
1615 .map(|(&path_id, _)| path_id)
1616 .collect::<Vec<_>>()
1617 {
1618 Self::populate_acks(
1619 now,
1620 self.receiving_ecn,
1621 path_id,
1622 space_id,
1623 &mut self.spaces[space_id],
1624 is_multipath_negotiated,
1625 &mut builder,
1626 &mut self.path_stats.for_path(path_id).frame_tx,
1627 self.crypto_state.has_keys(space_id.encryption_level()),
1628 );
1629 }
1630
1631 debug_assert!(
1639 builder.frame_space_remaining() > frame::ConnectionClose::SIZE_BOUND,
1640 "ACKs should leave space for ConnectionClose"
1641 );
1642 let stats = &mut self.path_stats.for_path(path_id).frame_tx;
1643 if frame::ConnectionClose::SIZE_BOUND < builder.frame_space_remaining() {
1644 let max_frame_size = builder.frame_space_remaining();
1645 let close: Close = match self.state.as_type() {
1646 StateType::Closed => {
1647 let reason: Close =
1648 self.state.as_closed().expect("checked").clone().into();
1649 if space_id == SpaceId::Data || reason.is_transport_layer() {
1650 reason
1651 } else {
1652 TransportError::APPLICATION_ERROR("").into()
1653 }
1654 }
1655 StateType::Draining => TransportError::NO_ERROR("").into(),
1656 _ => unreachable!(
1657 "tried to make a close packet when the connection wasn't closed"
1658 ),
1659 };
1660 builder.write_frame(close.encoder(max_frame_size), stats);
1661 }
1662 let last_pn = builder.packet_number;
1663 builder.finish_and_track(now, self, path_id, pad_datagram);
1664 if space_id.kind() == self.highest_space {
1665 self.connection_close_pending = false;
1668 }
1669 return PollPathSpaceStatus::WrotePacket {
1682 last_packet_number: last_pn,
1683 pad_datagram,
1684 };
1685 }
1686
1687 self.populate_packet(now, space_id, path_id, scheduling_info, &mut builder);
1688
1689 debug_assert!(
1696 !(builder.sent_frames().is_ack_only(&self.streams)
1697 && !can_send.acks
1698 && (can_send.other || can_send.space_specific)
1699 && builder.buf.segment_size()
1700 == self.path_data(path_id).current_mtu() as usize
1701 && self.datagrams.outgoing.is_empty()),
1702 "SendableFrames was {can_send:?}, but only ACKs have been written"
1703 );
1704 if builder.sent_frames().requires_padding {
1705 pad_datagram |= PadDatagram::ToMinMtu;
1706 }
1707
1708 for (path_id, _pn) in builder.sent_frames().largest_acked.iter() {
1709 self.spaces[space_id]
1710 .for_path(*path_id)
1711 .pending_acks
1712 .acks_sent();
1713 self.timers.stop(
1714 Timer::PerPath(*path_id, PathTimer::MaxAckDelay),
1715 self.qlog.with_time(now),
1716 );
1717 }
1718
1719 if builder.can_coalesce && path_id == PathId::ZERO && {
1727 let max_packet_size = builder
1728 .buf
1729 .datagram_remaining_mut()
1730 .saturating_sub(builder.predict_packet_end());
1731 max_packet_size > MIN_PACKET_SPACE
1732 && self.has_pending_packet(space_id, max_packet_size, connection_close_pending)
1733 } {
1734 trace!("will coalesce with next packet");
1737 builder.finish_and_track(now, self, path_id, PadDatagram::No);
1738 } else {
1739 if builder.buf.num_datagrams() > 1 && matches!(pad_datagram, PadDatagram::No) {
1745 const MAX_PADDING: usize = 32;
1753 if builder.buf.datagram_remaining_mut()
1754 > builder.predict_packet_end() + MAX_PADDING
1755 {
1756 trace!(
1757 "GSO truncated by demand for {} padding bytes",
1758 builder.buf.datagram_remaining_mut() - builder.predict_packet_end()
1759 );
1760 let last_pn = builder.packet_number;
1761 builder.finish_and_track(now, self, path_id, PadDatagram::No);
1762 return PollPathSpaceStatus::Send {
1763 last_packet_number: last_pn,
1764 };
1765 }
1766
1767 builder.finish_and_track(now, self, path_id, PadDatagram::ToSegmentSize);
1770 } else {
1771 builder.finish_and_track(now, self, path_id, pad_datagram);
1772 }
1773
1774 if transmit.num_datagrams() == 1 {
1777 transmit.clip_segment_size();
1778 }
1779 }
1780 }
1781 }
1782
1783 fn poll_transmit_mtu_probe(
1784 &mut self,
1785 now: Instant,
1786 buf: &mut Vec<u8>,
1787 path_id: PathId,
1788 ) -> Option<Transmit> {
1789 let (active_cid, probe_size) = self.get_mtu_probe_data(now, path_id)?;
1790
1791 let mut transmit = TransmitBuf::new(buf, NonZeroUsize::MIN, probe_size as usize);
1793 transmit.start_new_datagram_with_size(probe_size as usize);
1794
1795 let mut builder =
1796 PacketBuilder::new(now, SpaceId::Data, path_id, active_cid, &mut transmit, self)?;
1797
1798 trace!(?probe_size, "writing MTUD probe");
1800 builder.write_frame(frame::Ping, &mut self.path_stats.for_path(path_id).frame_tx);
1801
1802 if self.peer_supports_ack_frequency() {
1804 builder.write_frame(
1805 frame::ImmediateAck,
1806 &mut self.path_stats.for_path(path_id).frame_tx,
1807 );
1808 }
1809
1810 builder.finish_and_track(now, self, path_id, PadDatagram::ToSize(probe_size));
1811
1812 self.path_stats.for_path(path_id).sent_plpmtud_probes += 1;
1813
1814 Some(self.build_transmit(path_id, transmit))
1815 }
1816
1817 fn get_mtu_probe_data(&mut self, now: Instant, path_id: PathId) -> Option<(ConnectionId, u16)> {
1825 let active_cid = self.remote_cids.get(&path_id).map(CidQueue::active)?;
1826 let is_eligible = self.path_data(path_id).validated
1827 && !self.path_data(path_id).is_validating_path()
1828 && !self.abandoned_paths.contains(&path_id);
1829
1830 if !is_eligible {
1831 return None;
1832 }
1833 let next_pn = self.spaces[SpaceId::Data]
1834 .for_path(path_id)
1835 .peek_tx_number();
1836 let probe_size = self
1837 .path_data_mut(path_id)
1838 .mtud
1839 .poll_transmit(now, next_pn)?;
1840
1841 Some((active_cid, probe_size))
1842 }
1843
1844 fn has_pending_packet(
1861 &mut self,
1862 current_space_id: SpaceId,
1863 max_packet_size: usize,
1864 connection_close_pending: bool,
1865 ) -> bool {
1866 let mut space_id = current_space_id;
1867 loop {
1868 let can_send = self.space_can_send(
1869 space_id,
1870 PathId::ZERO,
1871 max_packet_size,
1872 connection_close_pending,
1873 );
1874 if !can_send.is_empty() {
1875 return true;
1876 }
1877 match space_id.next() {
1878 Some(next_space_id) => space_id = next_space_id,
1879 None => break,
1880 }
1881 }
1882 false
1883 }
1884
1885 fn path_congestion_check(
1887 &mut self,
1888 space_id: SpaceId,
1889 path_id: PathId,
1890 transmit: &TransmitBuf<'_>,
1891 can_send: &SendableFrames,
1892 now: Instant,
1893 ) -> PathBlocked {
1894 if self.side().is_server()
1900 && self
1901 .path_data(path_id)
1902 .anti_amplification_blocked(transmit.len() as u64 + 1)
1903 {
1904 trace!(?space_id, %path_id, "blocked by anti-amplification");
1905 return PathBlocked::AntiAmplification;
1906 }
1907
1908 let bytes_to_send = transmit.segment_size() as u64;
1911 let need_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0;
1912
1913 if can_send.other && !need_loss_probe && !can_send.close {
1914 let path = self.path_data(path_id);
1915 if path.in_flight.bytes + bytes_to_send >= path.congestion.window() {
1916 trace!(
1917 ?space_id,
1918 %path_id,
1919 in_flight=%path.in_flight.bytes,
1920 congestion_window=%path.congestion.window(),
1921 "blocked by congestion control",
1922 );
1923 return PathBlocked::Congestion;
1924 }
1925 }
1926
1927 if let Some(delay) = self.path_data_mut(path_id).pacing_delay(bytes_to_send, now) {
1929 let resume_time = now + delay;
1930 self.timers.set(
1931 Timer::PerPath(path_id, PathTimer::Pacing),
1932 resume_time,
1933 self.qlog.with_time(now),
1934 );
1935 trace!(?space_id, %path_id, ?delay, "blocked by pacing");
1938 return PathBlocked::Pacing;
1939 }
1940
1941 PathBlocked::No
1942 }
1943
1944 fn send_prev_path_challenge(
1949 &mut self,
1950 now: Instant,
1951 buf: &mut Vec<u8>,
1952 path_id: PathId,
1953 ) -> Option<Transmit> {
1954 let (prev_cid, prev_path) = self.paths.get_mut(&path_id)?.prev.as_mut()?;
1955 if !prev_path.pending_on_path_challenge {
1956 return None;
1957 };
1958 prev_path.pending_on_path_challenge = false;
1959 let token = self.rng.random();
1960 let network_path = prev_path.network_path;
1961 prev_path.record_path_challenge_sent(now, token, network_path);
1962
1963 debug_assert_eq!(
1964 self.highest_space,
1965 SpaceKind::Data,
1966 "PATH_CHALLENGE queued without 1-RTT keys"
1967 );
1968 let buf = &mut TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into());
1969 buf.start_new_datagram();
1970
1971 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, *prev_cid, buf, self)?;
1977 let challenge = frame::PathChallenge(token);
1978 let stats = &mut self.path_stats.for_path(path_id).frame_tx;
1979 builder.write_frame_with_log_msg(challenge, stats, Some("validating previous path"));
1980
1981 builder.pad_to(MIN_INITIAL_SIZE);
1986
1987 builder.finish(self, now);
1988 self.path_stats
1989 .for_path(path_id)
1990 .udp_tx
1991 .on_sent(1, buf.len());
1992
1993 trace!(
1994 dst = ?network_path.remote,
1995 src = ?network_path.local_ip,
1996 len = buf.len(),
1997 "sending prev_path off-path challenge",
1998 );
1999 Some(Transmit {
2000 destination: network_path.remote,
2001 size: buf.len(),
2002 ecn: None,
2003 segment_size: None,
2004 src_ip: network_path.local_ip,
2005 })
2006 }
2007
2008 fn send_off_path_path_response(
2009 &mut self,
2010 now: Instant,
2011 buf: &mut Vec<u8>,
2012 path_id: PathId,
2013 ) -> Option<Transmit> {
2014 let path = self.paths.get_mut(&path_id).map(|state| &mut state.data)?;
2015 let cid_queue = self.remote_cids.get_mut(&path_id)?;
2016 let (token, network_path) = path.path_responses.pop_off_path(path.network_path)?;
2017
2018 let cid = cid_queue.active();
2020
2021 let frame = frame::PathResponse(token);
2022
2023 let buf = &mut TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into());
2024 buf.start_new_datagram();
2025
2026 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, cid, buf, self)?;
2027 let stats = &mut self.path_stats.for_path(path_id).frame_tx;
2028 builder.write_frame_with_log_msg(frame, stats, Some("(off-path)"));
2029
2030 if self
2035 .find_validated_path_on_network_path(network_path)
2036 .is_none()
2037 && self.n0_nat_traversal.client_side().is_ok()
2038 {
2039 let token = self.rng.random();
2040 let stats = &mut self.path_stats.for_path(path_id).frame_tx;
2041 builder.write_frame(frame::PathChallenge(token), stats);
2042 let ip_port = (network_path.remote.ip(), network_path.remote.port());
2043 self.n0_nat_traversal.mark_probe_sent(ip_port, token);
2044 }
2045
2046 builder.pad_to(MIN_INITIAL_SIZE);
2049 builder.finish(self, now);
2050
2051 let size = buf.len();
2052 self.path_stats.for_path(path_id).udp_tx.on_sent(1, size);
2053
2054 trace!(
2055 dst = ?network_path.remote,
2056 src = ?network_path.local_ip,
2057 len = buf.len(),
2058 "sending off-path PATH_RESPONSE",
2059 );
2060 Some(Transmit {
2061 destination: network_path.remote,
2062 size,
2063 ecn: None,
2064 segment_size: None,
2065 src_ip: network_path.local_ip,
2066 })
2067 }
2068
2069 fn send_nat_traversal_path_challenge(
2071 &mut self,
2072 now: Instant,
2073 buf: &mut Vec<u8>,
2074 path_id: PathId,
2075 ) -> Option<Transmit> {
2076 let remote = self.n0_nat_traversal.next_probe_addr()?;
2077
2078 if !self.paths.get(&path_id)?.data.validated {
2079 return None;
2081 }
2082
2083 let Some(cid) = self
2088 .remote_cids
2089 .get(&path_id)
2090 .map(|cid_queue| cid_queue.active())
2091 else {
2092 trace!(%path_id, "Not sending NAT traversal probe for path with no CIDs");
2093 return None;
2094 };
2095 let token = self.rng.random();
2096
2097 let frame = frame::PathChallenge(token);
2098
2099 let mut buf = TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into());
2100 buf.start_new_datagram();
2101
2102 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, cid, &mut buf, self)?;
2103 let stats = &mut self.path_stats.for_path(path_id).frame_tx;
2104 builder.write_frame_with_log_msg(frame, stats, Some("(nat-traversal)"));
2105 builder.finish(self, now);
2108
2109 self.n0_nat_traversal.mark_probe_sent(remote, token);
2111
2112 let size = buf.len();
2113 self.path_stats.for_path(path_id).udp_tx.on_sent(1, size);
2114
2115 trace!(dst = ?remote, len = buf.len(), "sending off-path NAT probe");
2116 Some(Transmit {
2117 destination: remote.into(),
2118 size,
2119 ecn: None,
2120 segment_size: None,
2121 src_ip: None,
2122 })
2123 }
2124
2125 fn space_can_send(
2133 &mut self,
2134 space_id: SpaceId,
2135 path_id: PathId,
2136 packet_size: usize,
2137 connection_close_pending: bool,
2138 ) -> SendableFrames {
2139 let space = &mut self.spaces[space_id];
2140 let space_has_crypto = self.crypto_state.has_keys(space_id.encryption_level());
2141
2142 if !space_has_crypto
2143 && (space_id != SpaceId::Data
2144 || !self.crypto_state.has_keys(EncryptionLevel::ZeroRtt)
2145 || self.side.is_server())
2146 {
2147 return SendableFrames::empty();
2149 }
2150
2151 let mut can_send = space.can_send(path_id, &self.streams);
2152
2153 if space_id == SpaceId::Data {
2155 let pn = space.for_path(path_id).peek_tx_number();
2156 let frame_space_1rtt =
2162 packet_size.saturating_sub(self.predict_1rtt_overhead(pn, path_id));
2163 can_send |= self.can_send_1rtt(path_id, frame_space_1rtt);
2164 }
2165
2166 can_send.close = connection_close_pending && space_has_crypto;
2167
2168 can_send
2169 }
2170
2171 pub fn handle_event(&mut self, event: ConnectionEvent) {
2177 use ConnectionEventInner::*;
2178 match event.0 {
2179 Datagram(DatagramConnectionEvent {
2180 now,
2181 network_path,
2182 path_id,
2183 ecn,
2184 first_decode,
2185 remaining,
2186 }) => {
2187 let span = trace_span!("pkt", %path_id);
2188 let _guard = span.enter();
2189
2190 if self.early_discard_packet(network_path, path_id) {
2191 return;
2193 }
2194
2195 let was_anti_amplification_blocked = self
2196 .path(path_id)
2197 .map(|path| path.anti_amplification_blocked(1))
2198 .unwrap_or(false);
2201
2202 let rx = &mut self.path_stats.for_path(path_id).udp_rx;
2203 rx.datagrams += 1;
2204 rx.bytes += first_decode.len() as u64;
2205 let data_len = first_decode.len();
2206
2207 self.handle_decode(now, network_path, path_id, ecn, first_decode);
2208 if let Some(path) = self.path_mut(path_id) {
2213 path.inc_total_recvd(data_len as u64);
2214 }
2215
2216 if let Some(data) = remaining {
2217 self.path_stats.for_path(path_id).udp_rx.bytes += data.len() as u64;
2218 self.handle_coalesced(now, network_path, path_id, ecn, data);
2219 }
2220
2221 if let Some(path) = self.paths.get_mut(&path_id) {
2222 self.qlog
2223 .emit_recovery_metrics(path_id, &mut path.data, now);
2224 }
2225
2226 if was_anti_amplification_blocked {
2227 self.set_loss_detection_timer(now, path_id);
2231 }
2232 }
2233 NewIdentifiers(ids, now, cid_len, cid_lifetime) => {
2234 let path_id = ids.first().map(|issued| issued.path_id).unwrap_or_default();
2235 debug_assert!(ids.iter().all(|issued| issued.path_id == path_id));
2236
2237 if self.abandoned_paths.contains(&path_id) {
2240 if !self.state.is_drained() {
2241 for issued in &ids {
2242 self.endpoint_events
2243 .push_back(EndpointEventInner::RetireConnectionId(
2244 now,
2245 path_id,
2246 issued.sequence,
2247 false,
2248 ));
2249 }
2250 }
2251 return;
2252 }
2253
2254 let cid_state = self
2255 .local_cid_state
2256 .entry(path_id)
2257 .or_insert_with(|| CidState::new(cid_len, cid_lifetime, now, 0));
2258 cid_state.new_cids(&ids, now);
2259
2260 ids.into_iter().rev().for_each(|frame| {
2261 self.spaces[SpaceId::Data].pending.new_cids.push(frame);
2262 });
2263 self.reset_cid_retirement(now);
2265 }
2266 }
2267 }
2268
2269 fn early_discard_packet(&mut self, network_path: FourTuple, path_id: PathId) -> bool {
2277 if self.is_handshaking() && path_id != PathId::ZERO {
2278 debug!(%network_path, %path_id, "discarding multipath packet during handshake");
2279 return true;
2280 }
2281
2282 let peer_may_probe = self.peer_may_probe();
2283 let local_ip_may_migrate = self.local_ip_may_migrate();
2284
2285 if let Some(known_path) = self.path_mut(path_id) {
2289 if network_path.remote != known_path.network_path.remote && !peer_may_probe {
2290 trace!(
2291 %path_id,
2292 %network_path,
2293 %known_path.network_path,
2294 "discarding packet from unrecognized peer"
2295 );
2296 return true;
2297 }
2298
2299 if known_path.network_path.local_ip.is_some()
2300 && network_path.local_ip.is_some()
2301 && known_path.network_path.local_ip != network_path.local_ip
2302 && !local_ip_may_migrate
2303 {
2304 trace!(
2305 %path_id,
2306 %network_path,
2307 %known_path.network_path,
2308 "discarding packet sent to incorrect interface"
2309 );
2310 return true;
2311 }
2312 }
2313 false
2314 }
2315
2316 fn peer_may_probe(&self) -> bool {
2327 match &self.side {
2328 ConnectionSide::Client { .. } => {
2329 if let Some(hs) = self.state.as_handshake() {
2330 hs.allow_server_migration
2331 } else {
2332 self.n0_nat_traversal.is_negotiated() && self.is_handshake_confirmed()
2333 }
2334 }
2335 ConnectionSide::Server { server_config } => {
2336 self.is_handshake_confirmed()
2337 && (server_config.migration || self.n0_nat_traversal.is_negotiated())
2338 }
2339 }
2340 }
2341
2342 fn peer_may_migrate(&self) -> bool {
2354 match &self.side {
2355 ConnectionSide::Server { server_config } => {
2356 server_config.migration && self.is_handshake_confirmed()
2357 }
2358 ConnectionSide::Client { .. } => false,
2359 }
2360 }
2361
2362 fn local_ip_may_migrate(&self) -> bool {
2375 (self.side.is_client() || self.n0_nat_traversal.is_negotiated())
2376 && self.is_handshake_confirmed()
2377 }
2378 pub fn handle_timeout(&mut self, now: Instant) {
2388 while let Some((timer, _time)) = self.timers.expire_before(now, &self.qlog) {
2389 let span = match timer {
2390 Timer::Conn(timer) => trace_span!("timeout", scope = "conn", ?timer),
2391 Timer::PerPath(path_id, timer) => {
2392 trace_span!("timer_fired", scope="path", %path_id, ?timer)
2393 }
2394 };
2395 let _guard = span.enter();
2396 trace!("timeout");
2397 match timer {
2398 Timer::Conn(timer) => match timer {
2399 ConnTimer::Close => {
2400 let was_draining = self.state.move_to_drained(None);
2401 if !was_draining {
2402 self.endpoint_events.push_back(EndpointEventInner::Draining);
2403 }
2404 self.endpoint_events.push_back(EndpointEventInner::Drained);
2407 }
2408 ConnTimer::Idle => {
2409 self.kill(ConnectionError::TimedOut);
2410 }
2411 ConnTimer::KeepAlive => {
2412 self.ping();
2413 }
2414 ConnTimer::KeyDiscard => {
2415 self.crypto_state.discard_temporary_keys();
2416 }
2417 ConnTimer::PushNewCid => {
2418 while let Some((path_id, when)) = self.next_cid_retirement() {
2419 if when > now {
2420 break;
2421 }
2422 match self.local_cid_state.get_mut(&path_id) {
2423 None => error!(%path_id, "No local CID state for path"),
2424 Some(cid_state) => {
2425 let num_new_cid = cid_state.on_cid_timeout().into();
2427 if !self.state.is_closed() {
2428 trace!(
2429 "push a new CID to peer RETIRE_PRIOR_TO field {}",
2430 cid_state.retire_prior_to()
2431 );
2432 self.endpoint_events.push_back(
2433 EndpointEventInner::NeedIdentifiers(
2434 path_id,
2435 now,
2436 num_new_cid,
2437 ),
2438 );
2439 }
2440 }
2441 }
2442 }
2443 }
2444 ConnTimer::NoAvailablePath => {
2445 if self.state.is_closed() || self.state.is_drained() {
2450 error!("no viable path timer fired, but connection already closing");
2453 } else {
2454 trace!("no viable path grace period expired, closing connection");
2455 let err = TransportError::NO_VIABLE_PATH(
2456 "last path abandoned, no new path opened",
2457 );
2458 self.close_common();
2459 self.set_close_timer(now);
2460 self.connection_close_pending = true;
2461 self.state.move_to_closed(err);
2462 }
2463 }
2464 ConnTimer::NatTraversalProbeRetry => {
2465 self.n0_nat_traversal.queue_retries(self.is_ipv6());
2466 if let Some(delay) =
2467 self.n0_nat_traversal.retry_delay(self.config.initial_rtt)
2468 {
2469 self.timers.set(
2470 Timer::Conn(ConnTimer::NatTraversalProbeRetry),
2471 now + delay,
2472 self.qlog.with_time(now),
2473 );
2474 trace!("re-queued NAT probes");
2475 } else {
2476 trace!("no more NAT probes remaining");
2477 }
2478 }
2479 },
2480 Timer::PerPath(path_id, timer) => {
2481 match timer {
2482 PathTimer::PathIdle => {
2483 if let Err(err) =
2484 self.close_path_inner(now, path_id, PathAbandonReason::TimedOut)
2485 {
2486 warn!(?err, "failed closing path");
2487 }
2488 }
2489
2490 PathTimer::PathKeepAlive => {
2491 self.ping_path(path_id).ok();
2492 }
2493 PathTimer::LossDetection => {
2494 self.on_loss_detection_timeout(now, path_id);
2495 if let Some(path) = self.paths.get_mut(&path_id) {
2496 self.qlog
2497 .emit_recovery_metrics(path_id, &mut path.data, now);
2498 } else {
2499 error!("LossDetection fired for unknown path");
2500 }
2501 }
2502 PathTimer::PathValidationFailed => {
2503 let Some(path) = self.paths.get_mut(&path_id) else {
2504 continue;
2505 };
2506 self.timers.stop(
2507 Timer::PerPath(path_id, PathTimer::PathChallengeLost),
2508 self.qlog.with_time(now),
2509 );
2510 debug!("path migration validation failed");
2511 if let Some((_, prev)) = path.prev.take() {
2512 path.data = prev;
2513 }
2514 path.data.reset_on_path_challenges();
2515 }
2516 PathTimer::PathChallengeLost => {
2517 let Some(path) = self.paths.get_mut(&path_id) else {
2518 continue;
2519 };
2520 trace!(?path.data.on_path_challenges_lost, "path challenge deemed lost");
2521 path.data.pending_on_path_challenge = true;
2522 path.data.on_path_challenges_lost += 1;
2523 }
2524 PathTimer::AbandonFromValidation => {
2525 let Some(path) = self.paths.get_mut(&path_id) else {
2526 continue;
2527 };
2528 path.data.reset_on_path_challenges();
2529 self.timers.stop(
2530 Timer::PerPath(path_id, PathTimer::PathChallengeLost),
2531 self.qlog.with_time(now),
2532 );
2533 debug!("new path validation failed");
2534 if let Err(err) = self.close_path_inner(
2535 now,
2536 path_id,
2537 PathAbandonReason::ValidationFailed,
2538 ) {
2539 warn!(?err, "failed closing path");
2540 }
2541 }
2542 PathTimer::Pacing => {}
2543 PathTimer::MaxAckDelay => {
2544 self.spaces[SpaceId::Data]
2546 .for_path(path_id)
2547 .pending_acks
2548 .on_max_ack_delay_timeout()
2549 }
2550 PathTimer::PathDrained => {
2551 self.timers.stop_per_path(path_id, self.qlog.with_time(now));
2554 if let Some(local_cid_state) = self.local_cid_state.remove(&path_id) {
2555 debug_assert!(!self.state.is_drained()); let (min_seq, max_seq) = local_cid_state.active_seq();
2557 for seq in min_seq..=max_seq {
2558 self.endpoint_events.push_back(
2559 EndpointEventInner::RetireConnectionId(
2560 now, path_id, seq, false,
2561 ),
2562 );
2563 }
2564 }
2565 self.discard_path(path_id, now);
2566 }
2567 }
2568 }
2569 }
2570 }
2571 }
2572
2573 pub fn close(&mut self, now: Instant, error_code: VarInt, reason: Bytes) {
2585 self.close_inner(
2586 now,
2587 Close::Application(frame::ApplicationClose { error_code, reason }),
2588 )
2589 }
2590
2591 fn close_inner(&mut self, now: Instant, reason: Close) {
2607 let was_closed = self.state.is_closed();
2608 if !was_closed {
2609 self.close_common();
2610 self.set_close_timer(now);
2611 self.connection_close_pending = true;
2612 self.state.move_to_closed_local(reason);
2613 }
2614 }
2615
2616 pub fn datagrams(&mut self) -> Datagrams<'_> {
2618 Datagrams { conn: self }
2619 }
2620
2621 pub fn stats(&mut self) -> ConnectionStats {
2623 let mut stats = self.partial_stats.clone();
2624
2625 for path_stats in self.path_stats.iter_stats() {
2626 stats += *path_stats;
2631 }
2632
2633 stats
2634 }
2635
2636 pub fn path_stats(&mut self, path_id: PathId) -> Option<PathStats> {
2638 let path = self.paths.get(&path_id)?;
2639 let stats = self.path_stats.for_path(path_id);
2640 stats.rtt = path.data.rtt.get();
2641 stats.cwnd = path.data.congestion.window();
2642 stats.current_mtu = path.data.mtud.current_mtu();
2643 Some(*stats)
2644 }
2645
2646 pub fn ping(&mut self) {
2650 for path_data in self.spaces[self.highest_space].number_spaces.values_mut() {
2653 path_data.ping_pending = true;
2654 }
2655 }
2656
2657 pub fn ping_path(&mut self, path: PathId) -> Result<(), ClosedPath> {
2661 let path_data = self.spaces[self.highest_space]
2662 .number_spaces
2663 .get_mut(&path)
2664 .ok_or(ClosedPath { _private: () })?;
2665 path_data.ping_pending = true;
2666 Ok(())
2667 }
2668
2669 pub fn force_key_update(&mut self) {
2673 if !self.state.is_established() {
2674 debug!("ignoring forced key update in illegal state");
2675 return;
2676 }
2677 if self.crypto_state.prev_crypto.is_some() {
2678 debug!("ignoring redundant forced key update");
2681 return;
2682 }
2683 self.crypto_state.update_keys(None, false);
2684 }
2685
2686 pub fn crypto_session(&self) -> &dyn crypto::Session {
2688 self.crypto_state.session.as_ref()
2689 }
2690
2691 pub fn is_handshaking(&self) -> bool {
2701 self.state.is_handshake()
2702 }
2703
2704 pub fn is_closed(&self) -> bool {
2715 self.state.is_closed()
2716 }
2717
2718 pub fn is_drained(&self) -> bool {
2723 self.state.is_drained()
2724 }
2725
2726 pub fn accepted_0rtt(&self) -> bool {
2730 self.crypto_state.accepted_0rtt
2731 }
2732
2733 pub fn has_0rtt(&self) -> bool {
2735 self.crypto_state.zero_rtt_enabled
2736 }
2737
2738 pub fn has_pending_retransmits(&self) -> bool {
2740 !self.spaces[SpaceId::Data].pending.is_empty(&self.streams)
2741 }
2742
2743 pub fn side(&self) -> Side {
2745 self.side.side()
2746 }
2747
2748 pub fn path_observed_address(&self, path_id: PathId) -> Result<Option<SocketAddr>, ClosedPath> {
2750 self.path(path_id)
2751 .map(|path_data| {
2752 path_data
2753 .last_observed_addr_report
2754 .as_ref()
2755 .map(|observed| observed.socket_addr())
2756 })
2757 .ok_or(ClosedPath { _private: () })
2758 }
2759
2760 pub fn rtt(&self, path_id: PathId) -> Option<Duration> {
2762 self.path(path_id).map(|d| d.rtt.get())
2763 }
2764
2765 pub fn congestion_state(&self, path_id: PathId) -> Option<&dyn Controller> {
2767 self.path(path_id).map(|d| d.congestion.as_ref())
2768 }
2769
2770 pub fn set_max_concurrent_streams(&mut self, dir: Dir, count: VarInt) {
2775 self.streams.set_max_concurrent(dir, count);
2776 let pending = &mut self.spaces[SpaceId::Data].pending;
2779 self.streams.queue_max_stream_id(pending);
2780 }
2781
2782 pub fn set_max_concurrent_paths(
2792 &mut self,
2793 now: Instant,
2794 count: NonZeroU32,
2795 ) -> Result<(), MultipathNotNegotiated> {
2796 if !self.is_multipath_negotiated() {
2797 return Err(MultipathNotNegotiated { _private: () });
2798 }
2799 self.max_concurrent_paths = count;
2800
2801 let in_use_count = self
2802 .local_max_path_id
2803 .next()
2804 .saturating_sub(self.abandoned_paths.len())
2805 .as_u32();
2806 let extra_needed = count.get().saturating_sub(in_use_count);
2807 let new_max_path_id = self.local_max_path_id.saturating_add(extra_needed);
2808
2809 self.set_max_path_id(now, new_max_path_id);
2810
2811 Ok(())
2812 }
2813
2814 fn set_max_path_id(&mut self, now: Instant, max_path_id: PathId) {
2816 if max_path_id <= self.local_max_path_id {
2817 return;
2818 }
2819
2820 self.local_max_path_id = max_path_id;
2821 self.spaces[SpaceId::Data].pending.max_path_id = true;
2822
2823 self.issue_first_path_cids(now);
2824 }
2825
2826 pub fn max_concurrent_streams(&self, dir: Dir) -> u64 {
2832 self.streams.max_concurrent(dir)
2833 }
2834
2835 pub fn set_send_window(&mut self, send_window: u64) {
2837 self.streams.set_send_window(send_window);
2838 }
2839
2840 pub fn set_receive_window(&mut self, receive_window: VarInt) {
2842 if self.streams.set_receive_window(receive_window) {
2843 self.spaces[SpaceId::Data].pending.max_data = true;
2844 }
2845 }
2846
2847 pub fn is_multipath_negotiated(&self) -> bool {
2852 !self.is_handshaking()
2853 && self.config.max_concurrent_multipath_paths.is_some()
2854 && self.peer_params.initial_max_path_id.is_some()
2855 }
2856
2857 fn on_ack_received(
2858 &mut self,
2859 now: Instant,
2860 space: SpaceId,
2861 ack: frame::Ack,
2862 ) -> Result<(), TransportError> {
2863 let path = PathId::ZERO;
2865 self.inner_on_ack_received(now, space, path, ack)
2866 }
2867
2868 fn on_path_ack_received(
2869 &mut self,
2870 now: Instant,
2871 space: SpaceId,
2872 path_ack: frame::PathAck,
2873 ) -> Result<(), TransportError> {
2874 let (ack, path) = path_ack.into_ack();
2875 self.inner_on_ack_received(now, space, path, ack)
2876 }
2877
2878 fn inner_on_ack_received(
2880 &mut self,
2881 now: Instant,
2882 space: SpaceId,
2883 path: PathId,
2884 ack: frame::Ack,
2885 ) -> Result<(), TransportError> {
2886 if !self.spaces[space].number_spaces.contains_key(&path) {
2887 if self.abandoned_paths.contains(&path) {
2888 trace!("silently ignoring PATH_ACK on discarded path");
2894 return Ok(());
2895 } else {
2896 return Err(TransportError::PROTOCOL_VIOLATION(
2897 "received PATH_ACK with path ID never used",
2898 ));
2899 }
2900 }
2901 if ack.largest >= self.spaces[space].for_path(path).next_packet_number {
2902 return Err(TransportError::PROTOCOL_VIOLATION("unsent packet acked"));
2903 }
2904 let new_largest_pn = {
2906 let space = &mut self.spaces[space].for_path(path);
2907 if space
2908 .largest_acked_packet_pn
2909 .is_none_or(|pn| ack.largest > pn)
2910 {
2911 space.largest_acked_packet_pn = Some(ack.largest);
2912 if let Some(info) = space.sent_packets.get(ack.largest) {
2913 space.largest_acked_packet_send_time = info.time_sent;
2917 }
2918 Some(ack.largest)
2919 } else {
2920 None
2921 }
2922 };
2923
2924 if self.detect_spurious_loss(&ack, space, path) {
2925 self.path_stats.for_path(path).spurious_congestion_events += 1;
2926 self.path_data_mut(path)
2927 .congestion
2928 .on_spurious_congestion_event();
2929 }
2930
2931 let mut newly_acked: ArrayRangeSet = ArrayRangeSet::new();
2933 for range in ack.iter() {
2934 self.spaces[space].for_path(path).check_ack(range.clone())?;
2935 for (pn, _) in self.spaces[space]
2936 .for_path(path)
2937 .sent_packets
2938 .iter_range(range)
2939 {
2940 newly_acked.insert_one(pn);
2941 }
2942 }
2943
2944 if newly_acked.is_empty() {
2945 return Ok(());
2946 }
2947
2948 let mut ack_eliciting_acked = false;
2949 for packet in newly_acked.elts() {
2950 if let Some(info) = self.spaces[space].for_path(path).take(packet) {
2951 for (acked_path_id, acked_pn) in info.largest_acked.iter() {
2952 if let Some(pns) = self.spaces[space].path_space_mut(*acked_path_id) {
2958 pns.pending_acks.subtract_below(*acked_pn);
2959 }
2960 }
2961 ack_eliciting_acked |= info.ack_eliciting;
2962
2963 let path_data = self.path_data_mut(path);
2965 let mtu_updated = path_data.mtud.on_acked(space.kind(), packet, info.size);
2966 if mtu_updated {
2967 path_data
2968 .congestion
2969 .on_mtu_update(path_data.mtud.current_mtu());
2970 }
2971
2972 self.ack_frequency.on_acked(path, packet);
2974
2975 self.on_packet_acked(now, path, packet, info);
2976 }
2977 }
2978
2979 let largest_ackd = self.spaces[space].for_path(path).largest_acked_packet_pn;
2980 let path_data = self.path_data_mut(path);
2981 let app_limited = path_data.app_limited;
2982 let in_flight = path_data.in_flight.bytes;
2983
2984 path_data
2985 .congestion
2986 .on_end_acks(now, in_flight, app_limited, largest_ackd);
2987
2988 if new_largest_pn.is_some() && ack_eliciting_acked {
2989 let ack_delay = if space != SpaceId::Data {
2990 Duration::from_micros(0)
2991 } else {
2992 cmp::min(
2993 self.ack_frequency.peer_max_ack_delay,
2994 Duration::from_micros(ack.delay << self.peer_params.ack_delay_exponent.0),
2995 )
2996 };
2997 let rtt = now.saturating_duration_since(
2998 self.spaces[space]
2999 .for_path(path)
3000 .largest_acked_packet_send_time,
3001 );
3002
3003 let next_pn = self.spaces[space].for_path(path).next_packet_number;
3004 let path_data = self.path_data_mut(path);
3005 path_data.rtt.update(ack_delay, rtt);
3007 if path_data.first_packet_after_rtt_sample.is_none() {
3008 path_data.first_packet_after_rtt_sample = Some((space.kind(), next_pn));
3009 }
3010 }
3011
3012 self.detect_lost_packets(now, space, path, true);
3014
3015 if self.peer_completed_handshake_address_validation() {
3020 self.path_data_mut(path).pto_count = 0;
3021 }
3022
3023 if self.path_data(path).sending_ecn {
3028 if let Some(ecn) = ack.ecn {
3029 if let Some(largest_sent_pn) = new_largest_pn {
3034 let sent = self.spaces[space]
3035 .for_path(path)
3036 .largest_acked_packet_send_time;
3037 self.process_ecn(
3038 now,
3039 space,
3040 path,
3041 newly_acked.range_count() as u64,
3042 ecn,
3043 sent,
3044 largest_sent_pn,
3045 );
3046 }
3047 } else {
3048 debug!("ECN not acknowledged by peer");
3050 self.path_data_mut(path).sending_ecn = false;
3051 }
3052 }
3053
3054 self.set_loss_detection_timer(now, path);
3055 Ok(())
3056 }
3057
3058 fn detect_spurious_loss(&mut self, ack: &frame::Ack, space: SpaceId, path: PathId) -> bool {
3059 let lost_packets = &mut self.spaces[space].for_path(path).lost_packets;
3060
3061 if lost_packets.is_empty() {
3062 return false;
3063 }
3064
3065 for range in ack.iter() {
3066 let spurious_losses: Vec<u64> = lost_packets
3067 .iter_range(range.clone())
3068 .map(|(pn, _info)| pn)
3069 .collect();
3070
3071 for pn in spurious_losses {
3072 lost_packets.remove(pn);
3073 }
3074 }
3075
3076 lost_packets.is_empty()
3081 }
3082
3083 fn drain_lost_packets(&mut self, now: Instant, space: SpaceId, path: PathId) {
3088 let two_pto = 2 * self.path_data(path).rtt.pto_base();
3089
3090 let lost_packets = &mut self.spaces[space].for_path(path).lost_packets;
3091 lost_packets.retain(|_pn, info| now.saturating_duration_since(info.time_sent) <= two_pto);
3092 }
3093
3094 fn process_ecn(
3096 &mut self,
3097 now: Instant,
3098 space: SpaceId,
3099 path: PathId,
3100 newly_acked_pn: u64,
3101 ecn: frame::EcnCounts,
3102 largest_sent_time: Instant,
3103 largest_sent_pn: u64,
3104 ) {
3105 match self.spaces[space]
3106 .for_path(path)
3107 .detect_ecn(newly_acked_pn, ecn)
3108 {
3109 Err(e) => {
3110 debug!("halting ECN due to verification failure: {}", e);
3111
3112 self.path_data_mut(path).sending_ecn = false;
3113 self.spaces[space].for_path(path).ecn_feedback = frame::EcnCounts::ZERO;
3116 }
3117 Ok(false) => {}
3118 Ok(true) => {
3119 self.path_stats.for_path(path).congestion_events += 1;
3120 self.path_data_mut(path).congestion.on_congestion_event(
3121 now,
3122 largest_sent_time,
3123 false,
3124 true,
3125 0,
3126 largest_sent_pn,
3127 );
3128 }
3129 }
3130 }
3131
3132 fn on_packet_acked(&mut self, now: Instant, path_id: PathId, pn: u64, info: SentPacket) {
3135 let path = self.path_data_mut(path_id);
3136 let app_limited = path.app_limited;
3137 path.remove_in_flight(&info);
3138 if info.ack_eliciting && info.path_generation == path.generation() {
3139 let rtt = path.rtt;
3143 path.congestion
3144 .on_ack(now, info.time_sent, info.size.into(), pn, app_limited, &rtt);
3145 }
3146
3147 if let Some(retransmits) = info.retransmits.get() {
3149 for (id, _) in retransmits.reset_stream.iter() {
3150 self.streams.reset_acked(*id);
3151 }
3152 }
3153
3154 for frame in info.stream_frames {
3155 self.streams.received_ack_of(frame);
3156 }
3157 }
3158
3159 fn set_key_discard_timer(&mut self, now: Instant, space: SpaceKind) {
3160 let start = if self.crypto_state.has_keys(EncryptionLevel::ZeroRtt) {
3161 now
3162 } else {
3163 self.crypto_state
3164 .prev_crypto
3165 .as_ref()
3166 .expect("no previous keys")
3167 .end_packet
3168 .as_ref()
3169 .expect("update not acknowledged yet")
3170 .1
3171 };
3172
3173 self.timers.set(
3175 Timer::Conn(ConnTimer::KeyDiscard),
3176 start + self.max_pto_for_space(space) * 3,
3177 self.qlog.with_time(now),
3178 );
3179 }
3180
3181 fn on_loss_detection_timeout(&mut self, now: Instant, path_id: PathId) {
3194 if let Some((_, pn_space)) = self.loss_time_and_space(path_id) {
3195 self.detect_lost_packets(now, pn_space, path_id, false);
3197 self.set_loss_detection_timer(now, path_id);
3198 return;
3199 }
3200
3201 let Some((_, space)) = self.pto_time_and_space(now, path_id) else {
3202 error!(%path_id, "PTO expired while unset");
3203 return;
3204 };
3205 trace!(
3206 in_flight = self.path_data(path_id).in_flight.bytes,
3207 count = self.path_data(path_id).pto_count,
3208 ?space,
3209 %path_id,
3210 "PTO fired"
3211 );
3212
3213 let count = match self.path_data(path_id).in_flight.ack_eliciting {
3214 0 => {
3217 debug_assert!(!self.peer_completed_handshake_address_validation());
3218 1
3219 }
3220 _ => 2,
3222 };
3223 let pns = self.spaces[space].for_path(path_id);
3224 pns.loss_probes = pns.loss_probes.saturating_add(count);
3225 let path_data = self.path_data_mut(path_id);
3226 path_data.pto_count = path_data.pto_count.saturating_add(1);
3227 self.set_loss_detection_timer(now, path_id);
3228 }
3229
3230 fn detect_lost_packets(
3247 &mut self,
3248 now: Instant,
3249 pn_space: SpaceId,
3250 path_id: PathId,
3251 due_to_ack: bool,
3252 ) {
3253 let mut lost_packets = Vec::<u64>::new();
3254 let mut lost_mtu_probe = None;
3255 let mut in_persistent_congestion = false;
3256 let mut size_of_lost_packets = 0u64;
3257 self.spaces[pn_space].for_path(path_id).loss_time = None;
3258
3259 let path = self.path_data(path_id);
3262 let in_flight_mtu_probe = path.mtud.in_flight_mtu_probe();
3263 let loss_delay = path
3264 .rtt
3265 .conservative()
3266 .mul_f32(self.config.time_threshold)
3267 .max(TIMER_GRANULARITY);
3268 let first_packet_after_rtt_sample = path.first_packet_after_rtt_sample;
3269
3270 let largest_acked_packet_pn = self.spaces[pn_space]
3271 .for_path(path_id)
3272 .largest_acked_packet_pn
3273 .expect("detect_lost_packets only to be called if path received at least one ACK");
3274 let packet_threshold = self.config.packet_threshold as u64;
3275
3276 let congestion_period = self
3280 .pto(SpaceKind::Data, path_id)
3281 .saturating_mul(self.config.persistent_congestion_threshold);
3282 let mut persistent_congestion_start: Option<Instant> = None;
3283 let mut prev_packet = None;
3284 let space = self.spaces[pn_space].for_path(path_id);
3285
3286 for (packet, info) in space.sent_packets.iter_range(0..largest_acked_packet_pn) {
3287 if prev_packet != Some(packet.wrapping_sub(1)) {
3288 persistent_congestion_start = None;
3290 }
3291
3292 let packet_too_old = now.saturating_duration_since(info.time_sent) >= loss_delay;
3296 if packet_too_old || largest_acked_packet_pn >= packet + packet_threshold {
3297 if Some(packet) == in_flight_mtu_probe {
3299 lost_mtu_probe = in_flight_mtu_probe;
3302 } else {
3303 lost_packets.push(packet);
3304 size_of_lost_packets += info.size as u64;
3305 if info.ack_eliciting && due_to_ack {
3306 match persistent_congestion_start {
3307 Some(start) if info.time_sent - start > congestion_period => {
3310 in_persistent_congestion = true;
3311 }
3312 None if first_packet_after_rtt_sample
3314 .is_some_and(|x| x < (pn_space.kind(), packet)) =>
3315 {
3316 persistent_congestion_start = Some(info.time_sent);
3317 }
3318 _ => {}
3319 }
3320 }
3321 }
3322 } else {
3323 if space.loss_time.is_none() {
3325 space.loss_time = Some(info.time_sent + loss_delay);
3328 }
3329 persistent_congestion_start = None;
3330 }
3331
3332 prev_packet = Some(packet);
3333 }
3334
3335 self.handle_lost_packets(
3336 pn_space,
3337 path_id,
3338 now,
3339 lost_packets,
3340 lost_mtu_probe,
3341 loss_delay,
3342 in_persistent_congestion,
3343 size_of_lost_packets,
3344 );
3345 }
3346
3347 fn discard_path(&mut self, path_id: PathId, now: Instant) {
3349 trace!(%path_id, "dropping path state");
3350 let path = self.path_data(path_id);
3351 let in_flight_mtu_probe = path.mtud.in_flight_mtu_probe();
3352
3353 let mut size_of_lost_packets = 0u64; let lost_pns: Vec<_> = self.spaces[SpaceId::Data]
3355 .for_path(path_id)
3356 .sent_packets
3357 .iter()
3358 .filter(|(pn, _info)| Some(*pn) != in_flight_mtu_probe)
3359 .map(|(pn, info)| {
3360 size_of_lost_packets += info.size as u64;
3361 pn
3362 })
3363 .collect();
3364
3365 if !lost_pns.is_empty() {
3366 trace!(
3367 %path_id,
3368 count = lost_pns.len(),
3369 lost_bytes = size_of_lost_packets,
3370 "packets lost on path abandon"
3371 );
3372 self.handle_lost_packets(
3373 SpaceId::Data,
3374 path_id,
3375 now,
3376 lost_pns,
3377 in_flight_mtu_probe,
3378 Duration::ZERO,
3379 false,
3380 size_of_lost_packets,
3381 );
3382 }
3383 let path_stats = self.path_stats.discard(&path_id);
3386 self.partial_stats += path_stats;
3387 self.paths.remove(&path_id);
3388 self.spaces[SpaceId::Data].number_spaces.remove(&path_id);
3389
3390 self.events.push_back(
3391 PathEvent::Discarded {
3392 id: path_id,
3393 path_stats: Box::new(path_stats),
3394 }
3395 .into(),
3396 );
3397 }
3398
3399 fn handle_lost_packets(
3400 &mut self,
3401 pn_space: SpaceId,
3402 path_id: PathId,
3403 now: Instant,
3404 lost_packets: Vec<u64>,
3405 lost_mtu_probe: Option<u64>,
3406 loss_delay: Duration,
3407 in_persistent_congestion: bool,
3408 size_of_lost_packets: u64,
3409 ) {
3410 debug_assert!(lost_packets.is_sorted(), "lost_packets must be sorted");
3411
3412 self.drain_lost_packets(now, pn_space, path_id);
3413
3414 if let Some(largest_lost) = lost_packets.last().cloned() {
3416 let old_bytes_in_flight = self.path_data_mut(path_id).in_flight.bytes;
3417 let largest_lost_sent = self.spaces[pn_space]
3418 .for_path(path_id)
3419 .sent_packets
3420 .get(largest_lost)
3421 .unwrap()
3422 .time_sent;
3423 let path_stats = self.path_stats.for_path(path_id);
3424 path_stats.lost_packets += lost_packets.len() as u64;
3425 path_stats.lost_bytes += size_of_lost_packets;
3426 trace!(
3427 %path_id,
3428 count = lost_packets.len(),
3429 lost_bytes = size_of_lost_packets,
3430 "packets lost",
3431 );
3432
3433 for &packet in &lost_packets {
3434 let Some(info) = self.spaces[pn_space].for_path(path_id).take(packet) else {
3435 continue;
3436 };
3437 self.qlog
3438 .emit_packet_lost(packet, &info, loss_delay, pn_space.kind(), now);
3439 self.paths
3440 .get_mut(&path_id)
3441 .unwrap()
3442 .remove_in_flight(&info);
3443
3444 for frame in info.stream_frames {
3445 self.streams.retransmit(frame);
3446 }
3447 self.spaces[pn_space].pending |= info.retransmits;
3448 let path = self.path_data_mut(path_id);
3449 path.mtud.on_non_probe_lost(packet, info.size);
3450 path.congestion.on_packet_lost(info.size, packet, now);
3451
3452 self.spaces[pn_space].for_path(path_id).lost_packets.insert(
3453 packet,
3454 LostPacket {
3455 time_sent: info.time_sent,
3456 },
3457 );
3458 }
3459
3460 let path = self.path_data_mut(path_id);
3461 if path.mtud.black_hole_detected(now) {
3462 path.congestion.on_mtu_update(path.mtud.current_mtu());
3463 if let Some(max_datagram_size) = self.datagrams().max_size()
3464 && self.datagrams.drop_oversized(max_datagram_size)
3465 && self.datagrams.send_blocked
3466 {
3467 self.datagrams.send_blocked = false;
3468 self.events.push_back(Event::DatagramsUnblocked);
3469 }
3470 self.path_stats.for_path(path_id).black_holes_detected += 1;
3471 }
3472
3473 let lost_ack_eliciting =
3475 old_bytes_in_flight != self.path_data_mut(path_id).in_flight.bytes;
3476
3477 if lost_ack_eliciting {
3478 self.path_stats.for_path(path_id).congestion_events += 1;
3479 self.path_data_mut(path_id).congestion.on_congestion_event(
3480 now,
3481 largest_lost_sent,
3482 in_persistent_congestion,
3483 false,
3484 size_of_lost_packets,
3485 largest_lost,
3486 );
3487 }
3488 }
3489
3490 if let Some(packet) = lost_mtu_probe {
3492 let info = self.spaces[SpaceId::Data]
3493 .for_path(path_id)
3494 .take(packet)
3495 .unwrap(); self.paths
3498 .get_mut(&path_id)
3499 .unwrap()
3500 .remove_in_flight(&info);
3501 self.path_data_mut(path_id).mtud.on_probe_lost();
3502 self.path_stats.for_path(path_id).lost_plpmtud_probes += 1;
3503 }
3504 }
3505
3506 fn loss_time_and_space(&self, path_id: PathId) -> Option<(Instant, SpaceId)> {
3512 SpaceId::iter()
3513 .filter_map(|id| {
3514 self.spaces[id]
3515 .number_spaces
3516 .get(&path_id)
3517 .and_then(|pns| pns.loss_time)
3518 .map(|time| (time, id))
3519 })
3520 .min_by_key(|&(time, _)| time)
3521 }
3522
3523 fn pto_time_and_space(&mut self, now: Instant, path_id: PathId) -> Option<(Instant, SpaceId)> {
3531 let path = self.path(path_id)?;
3532 let pto_count = path.pto_count;
3533
3534 let max_interval = if path.rtt.get() > SLOW_RTT_THRESHOLD {
3536 (path.rtt.get() * 3) / 2
3538 } else if let Some(idle) = path.idle_timeout.or(self.idle_timeout)
3539 && idle <= MIN_IDLE_FOR_FAST_PTO
3540 {
3541 MAX_PTO_FAST_INTERVAL
3544 } else {
3545 MAX_PTO_INTERVAL
3547 };
3548
3549 if path_id == PathId::ZERO
3550 && path.in_flight.ack_eliciting == 0
3551 && !self.peer_completed_handshake_address_validation()
3552 {
3553 let space = match self.highest_space {
3559 SpaceKind::Handshake => SpaceId::Handshake,
3560 _ => SpaceId::Initial,
3561 };
3562
3563 let backoff = 2u32.pow(path.pto_count.min(MAX_BACKOFF_EXPONENT));
3564 let duration = path.rtt.pto_base() * backoff;
3565 let duration = duration.min(max_interval);
3566 return Some((now + duration, space));
3567 }
3568
3569 let mut result = None;
3570 for space in SpaceId::iter() {
3571 let Some(pns) = self.spaces[space].number_spaces.get(&path_id) else {
3572 continue;
3573 };
3574
3575 if space == SpaceId::Data && !self.is_handshake_confirmed() {
3576 continue;
3580 }
3581
3582 if !pns.has_in_flight() {
3583 continue;
3584 }
3585
3586 let duration = {
3591 let max_ack_delay = if space == SpaceId::Data {
3592 self.ack_frequency.max_ack_delay_for_pto()
3593 } else {
3594 Duration::ZERO
3595 };
3596 let pto_base = path.rtt.pto_base() + max_ack_delay;
3597 let mut duration = pto_base;
3598 for i in 1..=pto_count {
3599 let exponential_duration = pto_base * 2u32.pow(i.min(MAX_BACKOFF_EXPONENT));
3600 let max_duration = duration + max_interval;
3601 duration = exponential_duration.min(max_duration);
3602 }
3603 duration
3604 };
3605
3606 let Some(last_ack_eliciting) = pns.time_of_last_ack_eliciting_packet else {
3607 continue;
3608 };
3609 let pto = last_ack_eliciting + duration;
3612 if result.is_none_or(|(earliest_pto, _)| pto < earliest_pto) {
3613 if path.anti_amplification_blocked(1) {
3614 continue;
3616 }
3617 if path.in_flight.ack_eliciting == 0 {
3618 continue;
3620 }
3621 result = Some((pto, space));
3622 }
3623 }
3624 result
3625 }
3626
3627 fn peer_completed_handshake_address_validation(&self) -> bool {
3629 if self.side.is_server() || self.state.is_closed() {
3630 return true;
3631 }
3632 self.spaces[SpaceId::Handshake]
3636 .path_space(PathId::ZERO)
3637 .and_then(|pns| pns.largest_acked_packet_pn)
3638 .is_some()
3639 || self.spaces[SpaceId::Data]
3640 .path_space(PathId::ZERO)
3641 .and_then(|pns| pns.largest_acked_packet_pn)
3642 .is_some()
3643 || (self.crypto_state.has_keys(EncryptionLevel::OneRtt)
3644 && !self.crypto_state.has_keys(EncryptionLevel::Handshake))
3645 }
3646
3647 fn set_loss_detection_timer(&mut self, now: Instant, path_id: PathId) {
3655 if self.state.is_closed() {
3656 return;
3660 }
3661
3662 if let Some((loss_time, _)) = self.loss_time_and_space(path_id) {
3663 self.timers.set(
3665 Timer::PerPath(path_id, PathTimer::LossDetection),
3666 loss_time,
3667 self.qlog.with_time(now),
3668 );
3669 return;
3670 }
3671
3672 if !self.abandoned_paths.contains(&path_id)
3675 && let Some((timeout, _)) = self.pto_time_and_space(now, path_id)
3676 {
3677 self.timers.set(
3678 Timer::PerPath(path_id, PathTimer::LossDetection),
3679 timeout,
3680 self.qlog.with_time(now),
3681 );
3682 } else {
3683 self.timers.stop(
3684 Timer::PerPath(path_id, PathTimer::LossDetection),
3685 self.qlog.with_time(now),
3686 );
3687 }
3688 }
3689
3690 fn max_pto_for_space(&self, space: SpaceKind) -> Duration {
3694 self.paths
3695 .keys()
3696 .map(|path_id| self.pto(space, *path_id))
3697 .max()
3698 .unwrap_or_else(|| {
3699 let rtt = self.config.initial_rtt;
3703 let max_ack_delay = match space {
3704 SpaceKind::Initial | SpaceKind::Handshake => Duration::ZERO,
3705 SpaceKind::Data => self.ack_frequency.max_ack_delay_for_pto(),
3706 };
3707 rtt + cmp::max(4 * (rtt / 2), TIMER_GRANULARITY) + max_ack_delay
3708 })
3709 }
3710
3711 fn pto(&self, space: SpaceKind, path_id: PathId) -> Duration {
3716 let max_ack_delay = match space {
3717 SpaceKind::Initial | SpaceKind::Handshake => Duration::ZERO,
3718 SpaceKind::Data => self.ack_frequency.max_ack_delay_for_pto(),
3719 };
3720 self.path_data(path_id).rtt.pto_base() + max_ack_delay
3721 }
3722
3723 fn on_packet_authenticated(
3724 &mut self,
3725 now: Instant,
3726 space_id: SpaceKind,
3727 path_id: PathId,
3728 ecn: Option<EcnCodepoint>,
3729 packet_number: Option<u64>,
3730 spin: bool,
3731 is_1rtt: bool,
3732 remote: &FourTuple,
3733 ) {
3734 let is_on_path = self
3741 .path_data(path_id)
3742 .network_path
3743 .is_probably_same_path(remote);
3744
3745 self.total_authed_packets += 1;
3746 self.reset_keep_alive(path_id, now);
3747 self.reset_idle_timeout(now, space_id, path_id);
3748 self.path_data_mut(path_id).permit_idle_reset = true;
3749
3750 if is_on_path {
3753 self.receiving_ecn |= ecn.is_some();
3754 if let Some(x) = ecn {
3755 let space = &mut self.spaces[space_id];
3756 space.for_path(path_id).ecn_counters += x;
3757
3758 if x.is_ce() {
3759 space
3760 .for_path(path_id)
3761 .pending_acks
3762 .set_immediate_ack_required();
3763 }
3764 }
3765 }
3766
3767 let Some(packet_number) = packet_number else {
3768 return;
3769 };
3770 match &self.side {
3771 ConnectionSide::Client { .. } => {
3772 if space_id == SpaceKind::Handshake
3776 && let Some(hs) = self.state.as_handshake_mut()
3777 {
3778 hs.allow_server_migration = false;
3779 }
3780 }
3781 ConnectionSide::Server { .. } => {
3782 if self.crypto_state.has_keys(EncryptionLevel::Initial)
3783 && space_id == SpaceKind::Handshake
3784 {
3785 self.discard_space(now, SpaceKind::Initial);
3787 }
3788 if self.crypto_state.has_keys(EncryptionLevel::ZeroRtt) && is_1rtt {
3789 self.set_key_discard_timer(now, space_id)
3791 }
3792 }
3793 }
3794 let space = self.spaces[space_id].for_path(path_id);
3795
3796 space.pending_acks.insert_one(packet_number, now);
3797 if packet_number >= space.largest_received_packet_number.unwrap_or_default() {
3798 space.largest_received_packet_number = Some(packet_number);
3799
3800 if is_on_path {
3802 self.spin = self.side.is_client() ^ spin;
3803 }
3804 }
3805 }
3806
3807 fn reset_idle_timeout(&mut self, now: Instant, space: SpaceKind, path_id: PathId) {
3812 if let Some(timeout) = self.idle_timeout {
3814 if self.state.is_closed() {
3815 self.timers
3816 .stop(Timer::Conn(ConnTimer::Idle), self.qlog.with_time(now));
3817 } else {
3818 let dt = cmp::max(timeout, 3 * self.max_pto_for_space(space));
3819 self.timers.set(
3820 Timer::Conn(ConnTimer::Idle),
3821 now + dt,
3822 self.qlog.with_time(now),
3823 );
3824 }
3825 }
3826
3827 if let Some(timeout) = self.path_data(path_id).idle_timeout {
3829 if self.state.is_closed() {
3830 self.timers.stop(
3831 Timer::PerPath(path_id, PathTimer::PathIdle),
3832 self.qlog.with_time(now),
3833 );
3834 } else {
3835 let dt = cmp::max(timeout, 3 * self.pto(space, path_id));
3836 self.timers.set(
3837 Timer::PerPath(path_id, PathTimer::PathIdle),
3838 now + dt,
3839 self.qlog.with_time(now),
3840 );
3841 }
3842 }
3843 }
3844
3845 fn reset_keep_alive(&mut self, path_id: PathId, now: Instant) {
3847 if !self.state.is_established() {
3848 return;
3849 }
3850
3851 if let Some(interval) = self.config.keep_alive_interval {
3852 self.timers.set(
3853 Timer::Conn(ConnTimer::KeepAlive),
3854 now + interval,
3855 self.qlog.with_time(now),
3856 );
3857 }
3858
3859 if let Some(interval) = self.path_data(path_id).keep_alive {
3860 self.timers.set(
3861 Timer::PerPath(path_id, PathTimer::PathKeepAlive),
3862 now + interval,
3863 self.qlog.with_time(now),
3864 );
3865 }
3866 }
3867
3868 fn reset_cid_retirement(&mut self, now: Instant) {
3870 if let Some((_path, t)) = self.next_cid_retirement() {
3871 self.timers.set(
3872 Timer::Conn(ConnTimer::PushNewCid),
3873 t,
3874 self.qlog.with_time(now),
3875 );
3876 }
3877 }
3878
3879 fn next_cid_retirement(&self) -> Option<(PathId, Instant)> {
3881 self.local_cid_state
3882 .iter()
3883 .filter_map(|(path_id, cid_state)| cid_state.next_timeout().map(|t| (*path_id, t)))
3884 .min_by_key(|(_path_id, timeout)| *timeout)
3885 }
3886
3887 pub(crate) fn handle_first_packet(
3892 &mut self,
3893 now: Instant,
3894 network_path: FourTuple,
3895 ecn: Option<EcnCodepoint>,
3896 packet_number: u64,
3897 packet: InitialPacket,
3898 remaining: Option<BytesMut>,
3899 ) -> Result<(), ConnectionError> {
3900 let span = trace_span!("first recv");
3901 let _guard = span.enter();
3902 debug_assert!(self.side.is_server());
3903 let len = packet.header_data.len() + packet.payload.len();
3904 let path_id = PathId::ZERO;
3905 self.path_data_mut(path_id).total_recvd = len as u64;
3906
3907 if let Some(hs) = self.state.as_handshake_mut() {
3908 hs.expected_token = packet.header.token.clone();
3909 } else {
3910 unreachable!("first packet must be delivered in Handshake state");
3911 }
3912
3913 self.on_packet_authenticated(
3915 now,
3916 SpaceKind::Initial,
3917 path_id,
3918 ecn,
3919 Some(packet_number),
3920 false,
3921 false,
3922 &network_path,
3923 );
3924
3925 let packet: Packet = packet.into();
3926
3927 let mut qlog = QlogRecvPacket::new(len);
3928 qlog.header(&packet.header, Some(packet_number), path_id);
3929
3930 self.process_decrypted_packet(
3931 now,
3932 network_path,
3933 path_id,
3934 Some(packet_number),
3935 packet,
3936 &mut qlog,
3937 )?;
3938 self.qlog.emit_packet_received(qlog, now);
3939 if let Some(data) = remaining {
3940 self.handle_coalesced(now, network_path, path_id, ecn, data);
3941 }
3942
3943 self.qlog.emit_recovery_metrics(
3944 path_id,
3945 &mut self
3946 .paths
3947 .get_mut(&path_id)
3948 .expect("path_id was supplied by the caller for an active path")
3949 .data,
3950 now,
3951 );
3952
3953 Ok(())
3954 }
3955
3956 fn init_0rtt(&mut self, now: Instant) {
3957 let Some((header, packet)) = self.crypto_state.session.early_crypto() else {
3958 return;
3959 };
3960 if self.side.is_client() {
3961 match self.crypto_state.session.transport_parameters() {
3962 Ok(params) => {
3963 let params = params
3964 .expect("crypto layer didn't supply transport parameters with ticket");
3965 let params = TransportParameters {
3967 initial_src_cid: None,
3968 original_dst_cid: None,
3969 preferred_address: None,
3970 retry_src_cid: None,
3971 stateless_reset_token: None,
3972 min_ack_delay: None,
3973 ack_delay_exponent: TransportParameters::default().ack_delay_exponent,
3974 max_ack_delay: TransportParameters::default().max_ack_delay,
3975 initial_max_path_id: None,
3976 ..params
3977 };
3978 self.set_peer_params(params);
3979 self.qlog.emit_peer_transport_params_restored(self, now);
3980 }
3981 Err(e) => {
3982 error!("session ticket has malformed transport parameters: {}", e);
3983 return;
3984 }
3985 }
3986 }
3987 trace!("0-RTT enabled");
3988 self.crypto_state.enable_zero_rtt(header, packet);
3989 }
3990
3991 fn read_crypto(
3992 &mut self,
3993 space: SpaceId,
3994 crypto: &frame::Crypto,
3995 payload_len: usize,
3996 ) -> Result<(), TransportError> {
3997 let expected = if !self.state.is_handshake() {
3998 SpaceId::Data
3999 } else if self.highest_space == SpaceKind::Initial {
4000 SpaceId::Initial
4001 } else {
4002 SpaceId::Handshake
4005 };
4006 debug_assert!(space <= expected, "received out-of-order CRYPTO data");
4010
4011 let end = crypto.offset + crypto.data.len() as u64;
4012 if space < expected
4013 && end
4014 > self.crypto_state.spaces[space.kind()]
4015 .crypto_stream
4016 .bytes_read()
4017 {
4018 warn!(
4019 "received new {:?} CRYPTO data when expecting {:?}",
4020 space, expected
4021 );
4022 return Err(TransportError::PROTOCOL_VIOLATION(
4023 "new data at unexpected encryption level",
4024 ));
4025 }
4026
4027 let crypto_space = &mut self.crypto_state.spaces[space.kind()];
4028 let max = end.saturating_sub(crypto_space.crypto_stream.bytes_read());
4029 if max > self.config.crypto_buffer_size as u64 {
4030 return Err(TransportError::CRYPTO_BUFFER_EXCEEDED(""));
4031 }
4032
4033 crypto_space
4034 .crypto_stream
4035 .insert(crypto.offset, crypto.data.clone(), payload_len);
4036 while let Some(chunk) = crypto_space.crypto_stream.read(usize::MAX, true) {
4037 trace!("consumed {} CRYPTO bytes", chunk.bytes.len());
4038 if self.crypto_state.session.read_handshake(&chunk.bytes)? {
4039 self.events.push_back(Event::HandshakeDataReady);
4040 }
4041 }
4042
4043 Ok(())
4044 }
4045
4046 fn write_crypto(&mut self) {
4047 loop {
4048 let space = self.highest_space;
4049 let mut outgoing = Vec::new();
4050 if let Some(crypto) = self.crypto_state.session.write_handshake(&mut outgoing) {
4051 match space {
4052 SpaceKind::Initial => {
4053 self.upgrade_crypto(SpaceKind::Handshake, crypto);
4054 }
4055 SpaceKind::Handshake => {
4056 self.upgrade_crypto(SpaceKind::Data, crypto);
4057 }
4058 SpaceKind::Data => unreachable!("got updated secrets during 1-RTT"),
4059 }
4060 }
4061 if outgoing.is_empty() {
4062 if space == self.highest_space {
4063 break;
4064 } else {
4065 continue;
4067 }
4068 }
4069 let offset = self.crypto_state.spaces[space].crypto_offset;
4070 let outgoing = Bytes::from(outgoing);
4071 if let Some(hs) = self.state.as_handshake_mut()
4072 && space == SpaceKind::Initial
4073 && offset == 0
4074 && self.side.is_client()
4075 {
4076 hs.client_hello = Some(outgoing.clone());
4077 }
4078 self.crypto_state.spaces[space].crypto_offset += outgoing.len() as u64;
4079 trace!("wrote {} {:?} CRYPTO bytes", outgoing.len(), space);
4080 self.spaces[space].pending.crypto.push_back(frame::Crypto {
4081 offset,
4082 data: outgoing,
4083 });
4084 }
4085 }
4086
4087 fn upgrade_crypto(&mut self, space: SpaceKind, crypto: Keys) {
4089 debug_assert!(
4090 !self.crypto_state.has_keys(space.encryption_level()),
4091 "already reached packet space {space:?}"
4092 );
4093 trace!("{:?} keys ready", space);
4094 if space == SpaceKind::Data {
4095 self.crypto_state.next_crypto = Some(
4097 self.crypto_state
4098 .session
4099 .next_1rtt_keys()
4100 .expect("handshake should be complete"),
4101 );
4102 }
4103
4104 self.crypto_state.spaces[space].keys = Some(crypto);
4105 debug_assert!(space > self.highest_space);
4106 self.highest_space = space;
4107 if space == SpaceKind::Data && self.side.is_client() {
4108 self.crypto_state.discard_zero_rtt();
4110 }
4111 }
4112
4113 fn discard_space(&mut self, now: Instant, space: SpaceKind) {
4114 debug_assert!(space != SpaceKind::Data);
4115 trace!("discarding {:?} keys", space);
4116 if space == SpaceKind::Initial {
4117 if let ConnectionSide::Client { token, .. } = &mut self.side {
4119 *token = Bytes::new();
4120 }
4121 }
4122 self.crypto_state.spaces[space].keys = None;
4123 let space = &mut self.spaces[space];
4124 let pns = space.for_path(PathId::ZERO);
4125 pns.time_of_last_ack_eliciting_packet = None;
4126 pns.loss_time = None;
4127 pns.loss_probes = 0;
4128 let sent_packets = mem::take(&mut pns.sent_packets);
4129 let path = self
4130 .paths
4131 .get_mut(&PathId::ZERO)
4132 .expect("PathId::ZERO is alive while Initial/Handshake spaces exist");
4133 for (_, packet) in sent_packets.into_iter() {
4134 path.data.remove_in_flight(&packet);
4135 }
4136
4137 self.set_loss_detection_timer(now, PathId::ZERO)
4138 }
4139
4140 fn handle_coalesced(
4141 &mut self,
4142 now: Instant,
4143 network_path: FourTuple,
4144 path_id: PathId,
4145 ecn: Option<EcnCodepoint>,
4146 data: BytesMut,
4147 ) {
4148 self.path_data_mut(path_id)
4149 .inc_total_recvd(data.len() as u64);
4150 let mut remaining = Some(data);
4151 let cid_len = self
4152 .local_cid_state
4153 .values()
4154 .map(|cid_state| cid_state.cid_len())
4155 .next()
4156 .expect("one cid_state must exist");
4157 while let Some(data) = remaining {
4158 match PartialDecode::new(
4159 data,
4160 &FixedLengthConnectionIdParser::new(cid_len),
4161 &[self.version],
4162 self.endpoint_config.grease_quic_bit,
4163 ) {
4164 Ok((partial_decode, rest)) => {
4165 remaining = rest;
4166 self.handle_decode(now, network_path, path_id, ecn, partial_decode);
4167 }
4168 Err(e) => {
4169 trace!("malformed header: {}", e);
4170 return;
4171 }
4172 }
4173 }
4174 }
4175
4176 fn handle_decode(
4182 &mut self,
4183 now: Instant,
4184 network_path: FourTuple,
4185 path_id: PathId,
4186 ecn: Option<EcnCodepoint>,
4187 partial_decode: PartialDecode,
4188 ) {
4189 let qlog = QlogRecvPacket::new(partial_decode.len());
4190 if let Some(decoded) = self
4191 .crypto_state
4192 .unprotect_header(partial_decode, self.peer_params.stateless_reset_token)
4193 {
4194 self.handle_packet(
4195 now,
4196 network_path,
4197 path_id,
4198 ecn,
4199 decoded.packet,
4200 decoded.stateless_reset,
4201 qlog,
4202 );
4203 }
4204 }
4205
4206 fn handle_packet(
4213 &mut self,
4214 now: Instant,
4215 network_path: FourTuple,
4216 path_id: PathId,
4217 ecn: Option<EcnCodepoint>,
4218 packet: Option<Packet>,
4219 stateless_reset: bool,
4220 mut qlog: QlogRecvPacket,
4221 ) {
4222 self.path_stats.for_path(path_id).udp_rx.ios += 1;
4223
4224 if let Some(ref packet) = packet {
4225 trace!(
4226 "got {:?} packet ({} bytes) from {} using id {}",
4227 packet.header.space(),
4228 packet.payload.len() + packet.header_data.len(),
4229 network_path,
4230 packet.header.dst_cid(),
4231 );
4232 }
4233
4234 let was_closed = self.state.is_closed();
4235 let was_drained = self.state.is_drained();
4236
4237 let decrypted = match packet {
4239 None => Err(None),
4240 Some(mut packet) => self
4241 .decrypt_packet(now, path_id, &mut packet)
4242 .map(move |number| (packet, number)),
4243 };
4244 let result = match decrypted {
4245 _ if stateless_reset => {
4246 debug!("got stateless reset");
4247 Err(ConnectionError::Reset)
4248 }
4249 Err(Some(e)) => {
4250 warn!("illegal packet: {}", e);
4251 Err(e.into())
4252 }
4253 Err(None) => {
4254 debug!("failed to authenticate packet");
4255 self.authentication_failures += 1;
4256 let integrity_limit = self
4257 .crypto_state
4258 .integrity_limit(self.highest_space)
4259 .unwrap();
4260 if self.authentication_failures > integrity_limit {
4261 Err(TransportError::AEAD_LIMIT_REACHED("integrity limit violated").into())
4262 } else {
4263 return;
4264 }
4265 }
4266 Ok((packet, pn)) => {
4267 qlog.header(&packet.header, pn, path_id);
4269 let span = match pn {
4270 Some(pn) => trace_span!("recv", space = ?packet.header.space(), pn),
4271 None => trace_span!("recv", space = ?packet.header.space()),
4272 };
4273 let _guard = span.enter();
4274
4275 if self.is_handshaking()
4283 && self
4284 .path(path_id)
4285 .map(|path_data| {
4286 !path_data.network_path.is_probably_same_path(&network_path)
4287 })
4288 .unwrap_or(false)
4289 {
4290 if let Some(hs) = self.state.as_handshake()
4291 && hs.allow_server_migration
4292 {
4293 trace!(
4294 %network_path,
4295 prev = %self.path_data(path_id).network_path,
4296 "server migrated to new remote",
4297 );
4298 self.path_data_mut(path_id).network_path = network_path;
4299 self.qlog.emit_tuple_assigned(path_id, network_path, now);
4300 } else {
4301 debug!(
4302 recv_path = %network_path,
4303 expected_path = %self.path_data_mut(path_id).network_path,
4304 "discarding packet with unexpected remote during handshake",
4305 );
4306 return;
4307 }
4308 }
4309
4310 let dedup = self.spaces[packet.header.space()]
4311 .path_space_mut(path_id)
4312 .map(|pns| &mut pns.dedup);
4313 if pn.zip(dedup).is_some_and(|(n, d)| d.insert(n)) {
4314 debug!("discarding possible duplicate packet");
4315 self.qlog.emit_packet_received(qlog, now);
4316 return;
4317 } else if self.state.is_handshake() && packet.header.is_short() {
4318 trace!("dropping short packet during handshake");
4320 self.qlog.emit_packet_received(qlog, now);
4321 return;
4322 } else {
4323 if let Header::Initial(InitialHeader { ref token, .. }) = packet.header
4324 && let Some(hs) = self.state.as_handshake()
4325 && self.side.is_server()
4326 && token != &hs.expected_token
4327 {
4328 warn!("discarding Initial with invalid retry token");
4332 self.qlog.emit_packet_received(qlog, now);
4333 return;
4334 }
4335
4336 if !self.state.is_closed() {
4337 let spin = match packet.header {
4338 Header::Short { spin, .. } => spin,
4339 _ => false,
4340 };
4341
4342 if self.side().is_server() && !self.abandoned_paths.contains(&path_id) {
4343 self.ensure_path(path_id, network_path, now, pn);
4345 }
4346 if self.paths.contains_key(&path_id) {
4347 self.on_packet_authenticated(
4348 now,
4349 packet.header.space(),
4350 path_id,
4351 ecn,
4352 pn,
4353 spin,
4354 packet.header.is_1rtt(),
4355 &network_path,
4356 );
4357 }
4358 }
4359
4360 let res = self.process_decrypted_packet(
4361 now,
4362 network_path,
4363 path_id,
4364 pn,
4365 packet,
4366 &mut qlog,
4367 );
4368
4369 self.qlog.emit_packet_received(qlog, now);
4370 res
4371 }
4372 }
4373 };
4374
4375 if let Err(conn_err) = result {
4377 match conn_err {
4378 ConnectionError::ApplicationClosed(reason) => self.state.move_to_closed(reason),
4379 ConnectionError::ConnectionClosed(reason) => self.state.move_to_closed(reason),
4380 ConnectionError::Reset
4381 | ConnectionError::TransportError(TransportError {
4382 code: TransportErrorCode::AEAD_LIMIT_REACHED,
4383 ..
4384 }) => {
4385 let was_draining = self.state.move_to_drained(Some(conn_err));
4386 if !was_draining {
4387 self.endpoint_events.push_back(EndpointEventInner::Draining);
4388 }
4389 }
4390 ConnectionError::TimedOut => {
4391 unreachable!("timeouts aren't generated by packet processing");
4392 }
4393 ConnectionError::TransportError(err) => {
4394 debug!("closing connection due to transport error: {}", err);
4395 self.state.move_to_closed(err);
4396 }
4397 ConnectionError::VersionMismatch => {
4398 self.state.move_to_draining(Some(conn_err));
4399 self.endpoint_events.push_back(EndpointEventInner::Draining);
4400 }
4401 ConnectionError::LocallyClosed => {
4402 unreachable!("LocallyClosed isn't generated by packet processing");
4403 }
4404 ConnectionError::CidsExhausted => {
4405 unreachable!("CidsExhausted isn't generated by packet processing");
4406 }
4407 };
4408 }
4409
4410 if !was_closed && self.state.is_closed() {
4411 self.close_common();
4412 if !self.state.is_drained() {
4413 self.set_close_timer(now);
4414 }
4415 }
4416 if !was_drained && self.state.is_drained() {
4417 self.endpoint_events.push_back(EndpointEventInner::Drained);
4418 self.timers
4421 .stop(Timer::Conn(ConnTimer::Close), self.qlog.with_time(now));
4422 }
4423
4424 if matches!(self.state.as_type(), StateType::Closed) {
4431 if self
4449 .paths
4450 .get(&path_id)
4451 .map(|p| p.data.validated && p.data.network_path == network_path)
4452 .unwrap_or(false)
4453 {
4454 self.connection_close_pending = true;
4455 }
4456 }
4457 }
4458
4459 fn process_decrypted_packet(
4460 &mut self,
4461 now: Instant,
4462 network_path: FourTuple,
4463 path_id: PathId,
4464 number: Option<u64>,
4465 packet: Packet,
4466 qlog: &mut QlogRecvPacket,
4467 ) -> Result<(), ConnectionError> {
4468 if !self.paths.contains_key(&path_id) {
4469 trace!(%path_id, ?number, "discarding packet for unknown path");
4473 return Ok(());
4474 }
4475 let state = match self.state.as_type() {
4476 StateType::Established => {
4477 match packet.header.space() {
4478 SpaceKind::Data => self.process_payload(
4479 now,
4480 network_path,
4481 path_id,
4482 number.unwrap(),
4483 packet,
4484 qlog,
4485 )?,
4486 _ if packet.header.has_frames() => {
4487 self.process_early_payload(now, path_id, packet, qlog)?
4488 }
4489 _ => {
4490 trace!("discarding unexpected pre-handshake packet");
4491 }
4492 }
4493 return Ok(());
4494 }
4495 StateType::Closed => {
4496 for result in frame::Iter::new(packet.payload.freeze())? {
4497 let frame = match result {
4498 Ok(frame) => frame,
4499 Err(err) => {
4500 debug!("frame decoding error: {err:?}");
4501 continue;
4502 }
4503 };
4504 qlog.frame(&frame);
4505
4506 if let Frame::Padding = frame {
4507 continue;
4508 };
4509
4510 trace!(?frame, "processing frame in closed state");
4511
4512 self.path_stats
4513 .for_path(path_id)
4514 .frame_rx
4515 .record(frame.ty());
4516
4517 if let Frame::Close(_error) = frame {
4518 self.state.move_to_draining(None);
4519 self.endpoint_events.push_back(EndpointEventInner::Draining);
4520 break;
4521 }
4522 }
4523 return Ok(());
4524 }
4525 StateType::Draining | StateType::Drained => return Ok(()),
4526 StateType::Handshake => self.state.as_handshake_mut().expect("checked"),
4527 };
4528
4529 match packet.header {
4530 Header::Retry {
4531 src_cid: remote_cid,
4532 ..
4533 } => {
4534 debug_assert_eq!(path_id, PathId::ZERO);
4535 if self.side.is_server() {
4536 return Err(TransportError::PROTOCOL_VIOLATION("client sent Retry").into());
4537 }
4538
4539 let is_valid_retry = self
4540 .remote_cids
4541 .get(&path_id)
4542 .map(|cids| cids.active())
4543 .map(|orig_dst_cid| {
4544 self.crypto_state.session.is_valid_retry(
4545 orig_dst_cid,
4546 &packet.header_data,
4547 &packet.payload,
4548 )
4549 })
4550 .unwrap_or_default();
4551 if self.total_authed_packets > 1
4552 || packet.payload.len() <= 16 || !is_valid_retry
4554 {
4555 trace!("discarding invalid Retry");
4556 return Ok(());
4564 }
4565
4566 trace!("retrying with CID {}", remote_cid);
4567 let client_hello = state.client_hello.take().unwrap();
4568 self.retry_src_cid = Some(remote_cid);
4569 self.remote_cids
4570 .get_mut(&path_id)
4571 .expect("PathId::ZERO not yet abandoned, is_valid_retry would have been false")
4572 .update_initial_cid(remote_cid);
4573 self.remote_handshake_cid = remote_cid;
4574
4575 let space = &mut self.spaces[SpaceId::Initial];
4576 if let Some(info) = space.for_path(PathId::ZERO).take(0) {
4577 self.on_packet_acked(now, PathId::ZERO, 0, info);
4578 };
4579
4580 self.discard_space(now, SpaceKind::Initial); let crypto_space = &mut self.crypto_state.spaces[SpaceKind::Initial];
4583 crypto_space.keys = Some(
4584 self.crypto_state
4585 .session
4586 .initial_keys(remote_cid, self.side.side()),
4587 );
4588 crypto_space.crypto_offset = client_hello.len() as u64;
4589
4590 let next_pn = self.spaces[SpaceId::Initial]
4591 .for_path(path_id)
4592 .next_packet_number;
4593 self.spaces[SpaceId::Initial] = {
4594 let mut space = PacketSpace::new(now, SpaceId::Initial, &mut self.rng);
4595 space.for_path(path_id).next_packet_number = next_pn;
4596 space.pending.crypto.push_back(frame::Crypto {
4597 offset: 0,
4598 data: client_hello,
4599 });
4600 space
4601 };
4602
4603 let zero_rtt = mem::take(
4605 &mut self.spaces[SpaceId::Data]
4606 .for_path(PathId::ZERO)
4607 .sent_packets,
4608 );
4609 for (_, info) in zero_rtt.into_iter() {
4610 self.paths
4611 .get_mut(&PathId::ZERO)
4612 .unwrap()
4613 .remove_in_flight(&info);
4614 self.spaces[SpaceId::Data].pending |= info.retransmits;
4615 }
4616 self.streams.retransmit_all_for_0rtt();
4617
4618 let token_len = packet.payload.len() - 16;
4619 let ConnectionSide::Client { ref mut token, .. } = self.side else {
4620 unreachable!("we already short-circuited if we're server");
4621 };
4622 *token = packet.payload.freeze().split_to(token_len);
4623
4624 self.state = State::handshake(state::Handshake {
4625 expected_token: Bytes::new(),
4626 remote_cid_set: false,
4627 client_hello: None,
4628 allow_server_migration: self.config.server_handshake_migration,
4629 });
4630 Ok(())
4631 }
4632 Header::Long {
4633 ty: LongType::Handshake,
4634 src_cid: remote_cid,
4635 dst_cid: local_cid,
4636 ..
4637 } => {
4638 debug_assert_eq!(path_id, PathId::ZERO);
4639 if remote_cid != self.remote_handshake_cid {
4640 debug!(
4641 "discarding packet with mismatched remote CID: {} != {}",
4642 self.remote_handshake_cid, remote_cid
4643 );
4644 return Ok(());
4645 }
4646 self.on_path_validated(path_id);
4647
4648 self.process_early_payload(now, path_id, packet, qlog)?;
4649 if self.state.is_closed() {
4650 return Ok(());
4651 }
4652
4653 if self.crypto_state.session.is_handshaking() {
4654 trace!("handshake ongoing");
4655 return Ok(());
4656 }
4657
4658 if self.side.is_client() {
4659 let params = self
4661 .crypto_state
4662 .session
4663 .transport_parameters()?
4664 .ok_or_else(|| {
4665 TransportError::new(
4666 TransportErrorCode::crypto(0x6d),
4667 "transport parameters missing".to_owned(),
4668 )
4669 })?;
4670
4671 if self.has_0rtt() {
4672 if !self.crypto_state.session.early_data_accepted().unwrap() {
4673 debug_assert!(self.side.is_client());
4674 debug!("0-RTT rejected");
4675 self.crypto_state.accepted_0rtt = false;
4676 self.streams.zero_rtt_rejected();
4677
4678 self.spaces[SpaceId::Data].pending = Retransmits::default();
4680
4681 let sent_packets = mem::take(
4683 &mut self.spaces[SpaceId::Data].for_path(path_id).sent_packets,
4684 );
4685 for (_, packet) in sent_packets.into_iter() {
4686 self.paths
4687 .get_mut(&path_id)
4688 .unwrap()
4689 .remove_in_flight(&packet);
4690 }
4691 } else {
4692 self.crypto_state.accepted_0rtt = true;
4693 params.validate_resumption_from(&self.peer_params)?;
4694 }
4695 }
4696 if let Some(token) = params.stateless_reset_token {
4697 let remote = self.path_data(path_id).network_path.remote;
4698 debug_assert!(!self.state.is_drained()); self.endpoint_events
4700 .push_back(EndpointEventInner::ResetToken(path_id, remote, token));
4701 }
4702 self.handle_peer_params(params, local_cid, remote_cid, now)?;
4703 self.issue_first_cids(now);
4704 } else {
4705 self.spaces[SpaceId::Data].pending.handshake_done = true;
4707 self.discard_space(now, SpaceKind::Handshake);
4708 self.events.push_back(Event::HandshakeConfirmed);
4709 trace!("handshake confirmed");
4710 }
4711
4712 self.events.push_back(Event::Connected);
4713 self.state.move_to_established();
4714 trace!("established");
4715
4716 self.issue_first_path_cids(now);
4719 Ok(())
4720 }
4721 Header::Initial(InitialHeader {
4722 src_cid: remote_cid,
4723 dst_cid: local_cid,
4724 ..
4725 }) => {
4726 debug_assert_eq!(path_id, PathId::ZERO);
4727 if !state.remote_cid_set {
4728 trace!("switching remote CID to {}", remote_cid);
4729 let mut state = state.clone();
4730 self.remote_cids
4731 .get_mut(&path_id)
4732 .expect("PathId::ZERO not yet abandoned")
4733 .update_initial_cid(remote_cid);
4734 self.remote_handshake_cid = remote_cid;
4735 self.original_remote_cid = remote_cid;
4736 state.remote_cid_set = true;
4737 self.state.move_to_handshake(state);
4738 } else if remote_cid != self.remote_handshake_cid {
4739 debug!(
4740 "discarding packet with mismatched remote CID: {} != {}",
4741 self.remote_handshake_cid, remote_cid
4742 );
4743 return Ok(());
4744 }
4745
4746 let starting_space = self.highest_space;
4747 self.process_early_payload(now, path_id, packet, qlog)?;
4748
4749 if self.side.is_server()
4750 && starting_space == SpaceKind::Initial
4751 && self.highest_space != SpaceKind::Initial
4752 {
4753 let params = self
4754 .crypto_state
4755 .session
4756 .transport_parameters()?
4757 .ok_or_else(|| {
4758 TransportError::new(
4759 TransportErrorCode::crypto(0x6d),
4760 "transport parameters missing".to_owned(),
4761 )
4762 })?;
4763 self.handle_peer_params(params, local_cid, remote_cid, now)?;
4764 self.issue_first_cids(now);
4765 self.init_0rtt(now);
4766 }
4767 Ok(())
4768 }
4769 Header::Long {
4770 ty: LongType::ZeroRtt,
4771 ..
4772 } => {
4773 self.process_payload(now, network_path, path_id, number.unwrap(), packet, qlog)?;
4774 Ok(())
4775 }
4776 Header::VersionNegotiate { .. } => {
4777 if self.total_authed_packets > 1 {
4778 return Ok(());
4779 }
4780 let supported = packet
4781 .payload
4782 .chunks(4)
4783 .any(|x| match <[u8; 4]>::try_from(x) {
4784 Ok(version) => self.version == u32::from_be_bytes(version),
4785 Err(_) => false,
4786 });
4787 if supported {
4788 return Ok(());
4789 }
4790 debug!("remote doesn't support our version");
4791 Err(ConnectionError::VersionMismatch)
4792 }
4793 Header::Short { .. } => unreachable!(
4794 "short packets received during handshake are discarded in handle_packet"
4795 ),
4796 }
4797 }
4798
4799 fn process_early_payload(
4801 &mut self,
4802 now: Instant,
4803 path_id: PathId,
4804 packet: Packet,
4805 #[allow(unused)] qlog: &mut QlogRecvPacket,
4806 ) -> Result<(), TransportError> {
4807 debug_assert_ne!(packet.header.space(), SpaceKind::Data);
4808 debug_assert_eq!(path_id, PathId::ZERO);
4809 let payload_len = packet.payload.len();
4810 let mut ack_eliciting = false;
4811 for result in frame::Iter::new(packet.payload.freeze())? {
4812 let frame = result?;
4813 qlog.frame(&frame);
4814 let span = match frame {
4815 Frame::Padding => continue,
4816 _ => Some(trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty)),
4817 };
4818
4819 self.path_stats
4820 .for_path(path_id)
4821 .frame_rx
4822 .record(frame.ty());
4823
4824 let _guard = span.as_ref().map(|x| x.enter());
4825 ack_eliciting |= frame.is_ack_eliciting();
4826
4827 if frame.is_1rtt() && packet.header.space() != SpaceKind::Data {
4829 return Err(TransportError::PROTOCOL_VIOLATION(
4830 "illegal frame type in handshake",
4831 ));
4832 }
4833
4834 match frame {
4835 Frame::Padding | Frame::Ping => {}
4836 Frame::Crypto(frame) => {
4837 self.read_crypto(packet.header.space().into(), &frame, payload_len)?;
4838 }
4839 Frame::Ack(ack) => {
4840 self.on_ack_received(now, packet.header.space().into(), ack)?;
4841 }
4842 Frame::PathAck(ack) => {
4843 span.as_ref()
4844 .map(|span| span.record("path", tracing::field::display(&ack.path_id)));
4845 self.on_path_ack_received(now, packet.header.space().into(), ack)?;
4846 }
4847 Frame::Close(reason) => {
4848 self.state.move_to_draining(Some(reason.into()));
4849 self.endpoint_events.push_back(EndpointEventInner::Draining);
4850 return Ok(());
4851 }
4852 _ => {
4853 let mut err =
4854 TransportError::PROTOCOL_VIOLATION("illegal frame type in handshake");
4855 err.frame = frame::MaybeFrame::Known(frame.ty());
4856 return Err(err);
4857 }
4858 }
4859 }
4860
4861 if ack_eliciting {
4862 self.spaces[packet.header.space()]
4864 .for_path(path_id)
4865 .pending_acks
4866 .set_immediate_ack_required();
4867 }
4868
4869 self.write_crypto();
4870 Ok(())
4871 }
4872
4873 fn process_payload(
4875 &mut self,
4876 now: Instant,
4877 network_path: FourTuple,
4878 path_id: PathId,
4879 number: u64,
4880 packet: Packet,
4881 #[allow(unused)] qlog: &mut QlogRecvPacket,
4882 ) -> Result<(), TransportError> {
4883 let is_multipath_negotiated = self.is_multipath_negotiated();
4884 let payload = packet.payload.freeze();
4885 let mut is_probing_packet = true;
4886 let mut close = None;
4887 let payload_len = payload.len();
4888 let mut ack_eliciting = false;
4889 let mut migration_observed_addr = None;
4892 for result in frame::Iter::new(payload)? {
4893 let frame = result?;
4894 qlog.frame(&frame);
4895 let span = match frame {
4896 Frame::Padding => continue,
4897 _ => trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty),
4898 };
4899
4900 self.path_stats
4901 .for_path(path_id)
4902 .frame_rx
4903 .record(frame.ty());
4904 match &frame {
4907 Frame::Crypto(f) => {
4908 trace!(offset = f.offset, len = f.data.len(), "got frame CRYPTO");
4909 }
4910 Frame::Stream(f) => {
4911 trace!(id = %f.id, offset = f.offset, len = f.data.len(), fin = f.fin, "got frame STREAM");
4912 }
4913 Frame::Datagram(f) => {
4914 trace!(len = f.data.len(), "got frame DATAGRAM");
4915 }
4916 f => {
4917 trace!("got frame {f}");
4918 }
4919 }
4920
4921 let _guard = span.enter();
4922 if packet.header.is_0rtt() {
4923 match frame {
4924 Frame::Crypto(_) | Frame::Close(Close::Application(_)) => {
4925 return Err(TransportError::PROTOCOL_VIOLATION(
4926 "illegal frame type in 0-RTT",
4927 ));
4928 }
4929 _ => {
4930 if frame.is_1rtt() {
4931 return Err(TransportError::PROTOCOL_VIOLATION(
4932 "illegal frame type in 0-RTT",
4933 ));
4934 }
4935 }
4936 }
4937 }
4938 ack_eliciting |= frame.is_ack_eliciting();
4939
4940 match frame {
4942 Frame::Padding
4943 | Frame::PathChallenge(_)
4944 | Frame::PathResponse(_)
4945 | Frame::NewConnectionId(_)
4946 | Frame::ObservedAddr(_) => {}
4947 _ => {
4948 is_probing_packet = false;
4949 }
4950 }
4951
4952 match frame {
4953 Frame::Crypto(frame) => {
4954 self.read_crypto(SpaceId::Data, &frame, payload_len)?;
4955 }
4956 Frame::Stream(frame) => {
4957 if self.streams.received(frame, payload_len)?.should_transmit() {
4958 self.spaces[SpaceId::Data].pending.max_data = true;
4959 }
4960 }
4961 Frame::Ack(ack) => {
4962 self.on_ack_received(now, SpaceId::Data, ack)?;
4963 }
4964 Frame::PathAck(ack) => {
4965 if !self.is_multipath_negotiated() {
4966 return Err(TransportError::PROTOCOL_VIOLATION(
4967 "received PATH_ACK frame when multipath was not negotiated",
4968 ));
4969 }
4970 span.record("path", tracing::field::display(&ack.path_id));
4971 self.on_path_ack_received(now, SpaceId::Data, ack)?;
4972 }
4973 Frame::Padding | Frame::Ping => {}
4974 Frame::Close(reason) => {
4975 close = Some(reason);
4976 }
4977 Frame::PathChallenge(challenge) => {
4978 let path = &mut self
4979 .path_mut(path_id)
4980 .expect("payload is processed only after the path becomes known");
4981 path.path_responses.push(number, challenge.0, network_path);
4982 if network_path.remote == path.network_path.remote {
4986 match self.peer_supports_ack_frequency() {
4994 true => self.immediate_ack(path_id),
4995 false => {
4996 self.ping_path(path_id).ok();
4997 }
4998 }
4999 }
5000 }
5001 Frame::PathResponse(response) => {
5002 if self
5004 .n0_nat_traversal
5005 .handle_path_response(network_path, response.0)
5006 {
5007 self.open_nat_traversed_paths(now);
5008 } else {
5009 let path = self
5012 .paths
5013 .get_mut(&path_id)
5014 .expect("payload is processed only after the path becomes known");
5015
5016 use PathTimer::*;
5017 use paths::OnPathResponseReceived::*;
5018 match path
5019 .data
5020 .on_path_response_received(now, response.0, network_path)
5021 {
5022 OnPath { was_open } if !self.abandoned_paths.contains(&path_id) => {
5023 let qlog = self.qlog.with_time(now);
5024
5025 self.timers.stop(
5026 Timer::PerPath(path_id, PathValidationFailed),
5027 qlog.clone(),
5028 );
5029 self.timers.stop(
5030 Timer::PerPath(path_id, AbandonFromValidation),
5031 qlog.clone(),
5032 );
5033
5034 let next_challenge = path
5035 .data
5036 .earliest_on_path_expiring_challenge()
5037 .map(|time| time + self.ack_frequency.max_ack_delay_for_pto());
5038 self.timers.set_or_stop(
5039 Timer::PerPath(path_id, PathChallengeLost),
5040 next_challenge,
5041 qlog,
5042 );
5043
5044 if !was_open {
5045 if is_multipath_negotiated {
5046 self.events.push_back(Event::Path(
5047 PathEvent::Established { id: path_id },
5048 ));
5049 }
5050 if let Some(observed) =
5051 path.data.last_observed_addr_report.as_ref()
5052 {
5053 self.events.push_back(Event::Path(
5054 PathEvent::ObservedAddr {
5055 id: path_id,
5056 addr: observed.socket_addr(),
5057 },
5058 ));
5059 }
5060 }
5061 if let Some((_, ref mut prev)) = path.prev {
5062 prev.reset_on_path_challenges();
5067 }
5068 }
5069 OnPath { .. } => {
5070 trace!(
5071 %response,
5072 "ignoring PATH_RESPONSE received after path is abandoned"
5073 );
5074 }
5075 Ignored {
5076 sent_on,
5077 current_path,
5078 } => {
5079 debug!(%sent_on, %current_path, %response, "ignoring valid PATH_RESPONSE")
5080 }
5081 Unknown => debug!(%response, "ignoring invalid PATH_RESPONSE"),
5082 }
5083 }
5084 }
5085 Frame::MaxData(frame::MaxData(bytes)) => {
5086 self.streams.received_max_data(bytes);
5087 }
5088 Frame::MaxStreamData(frame::MaxStreamData { id, offset }) => {
5089 self.streams.received_max_stream_data(id, offset)?;
5090 }
5091 Frame::MaxStreams(frame::MaxStreams { dir, count }) => {
5092 self.streams.received_max_streams(dir, count)?;
5093 }
5094 Frame::ResetStream(frame) => {
5095 if self.streams.received_reset(frame)?.should_transmit() {
5096 self.spaces[SpaceId::Data].pending.max_data = true;
5097 }
5098 }
5099 Frame::DataBlocked(DataBlocked(offset)) => {
5100 debug!(offset, "peer claims to be blocked at connection level");
5101 }
5102 Frame::StreamDataBlocked(StreamDataBlocked { id, offset }) => {
5103 if id.initiator() == self.side.side() && id.dir() == Dir::Uni {
5104 debug!("got STREAM_DATA_BLOCKED on send-only {}", id);
5105 return Err(TransportError::STREAM_STATE_ERROR(
5106 "STREAM_DATA_BLOCKED on send-only stream",
5107 ));
5108 }
5109 debug!(
5110 stream = %id,
5111 offset, "peer claims to be blocked at stream level"
5112 );
5113 }
5114 Frame::StreamsBlocked(StreamsBlocked { dir, limit }) => {
5115 if limit > MAX_STREAM_COUNT {
5116 return Err(TransportError::FRAME_ENCODING_ERROR(
5117 "unrepresentable stream limit",
5118 ));
5119 }
5120 debug!(
5121 "peer claims to be blocked opening more than {} {} streams",
5122 limit, dir
5123 );
5124 }
5125 Frame::StopSending(frame::StopSending { id, error_code }) => {
5126 if id.initiator() != self.side.side() {
5127 if id.dir() == Dir::Uni {
5128 debug!("got STOP_SENDING on recv-only {}", id);
5129 return Err(TransportError::STREAM_STATE_ERROR(
5130 "STOP_SENDING on recv-only stream",
5131 ));
5132 }
5133 } else if self.streams.is_local_unopened(id) {
5134 return Err(TransportError::STREAM_STATE_ERROR(
5135 "STOP_SENDING on unopened stream",
5136 ));
5137 }
5138 self.streams.received_stop_sending(id, error_code);
5139 }
5140 Frame::RetireConnectionId(frame::RetireConnectionId { path_id, sequence }) => {
5141 if let Some(ref path_id) = path_id {
5142 span.record("path", tracing::field::display(&path_id));
5143 }
5144 let path_id = path_id.unwrap_or_default();
5145 match self.local_cid_state.get_mut(&path_id) {
5146 None => debug!(?path_id, "RETIRE_CONNECTION_ID for unknown path"),
5147 Some(cid_state) => {
5148 let allow_more_cids = cid_state
5149 .on_cid_retirement(sequence, self.peer_params.issue_cids_limit())?;
5150
5151 let has_path = !self.abandoned_paths.contains(&path_id);
5155 let allow_more_cids = allow_more_cids && has_path;
5156
5157 debug_assert!(!self.state.is_drained()); self.endpoint_events
5159 .push_back(EndpointEventInner::RetireConnectionId(
5160 now,
5161 path_id,
5162 sequence,
5163 allow_more_cids,
5164 ));
5165 }
5166 }
5167 }
5168 Frame::NewConnectionId(frame) => {
5169 let path_id = if let Some(path_id) = frame.path_id {
5170 if !self.is_multipath_negotiated() {
5171 return Err(TransportError::PROTOCOL_VIOLATION(
5172 "received PATH_NEW_CONNECTION_ID frame when multipath was not negotiated",
5173 ));
5174 }
5175 if path_id > self.local_max_path_id {
5176 return Err(TransportError::PROTOCOL_VIOLATION(
5177 "PATH_NEW_CONNECTION_ID contains path_id exceeding current max",
5178 ));
5179 }
5180 path_id
5181 } else {
5182 PathId::ZERO
5183 };
5184
5185 if let Some(ref path_id) = frame.path_id {
5186 span.record("path", tracing::field::display(&path_id));
5187 }
5188
5189 if self.abandoned_paths.contains(&path_id) {
5190 trace!("ignoring issued CID for abandoned path");
5191 continue;
5192 }
5193 let remote_cids = self
5194 .remote_cids
5195 .entry(path_id)
5196 .or_insert_with(|| CidQueue::new(frame.id));
5197 if remote_cids.active().is_empty() {
5198 return Err(TransportError::PROTOCOL_VIOLATION(
5199 "NEW_CONNECTION_ID when CIDs aren't in use",
5200 ));
5201 }
5202 if frame.retire_prior_to > frame.sequence {
5203 return Err(TransportError::PROTOCOL_VIOLATION(
5204 "NEW_CONNECTION_ID retiring unissued CIDs",
5205 ));
5206 }
5207
5208 use crate::cid_queue::InsertError;
5209 match remote_cids.insert(frame) {
5210 Ok(None) => {
5211 self.open_nat_traversed_paths(now);
5212 }
5213 Ok(Some((retired, reset_token))) => {
5214 let pending_retired =
5215 &mut self.spaces[SpaceId::Data].pending.retire_cids;
5216 const MAX_PENDING_RETIRED_CIDS: u64 = CidQueue::LEN as u64 * 10;
5219 if (pending_retired.len() as u64)
5222 .saturating_add(retired.end.saturating_sub(retired.start))
5223 > MAX_PENDING_RETIRED_CIDS
5224 {
5225 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR(
5226 "queued too many retired CIDs",
5227 ));
5228 }
5229 pending_retired.extend(retired.map(|seq| (path_id, seq)));
5230 self.set_reset_token(path_id, network_path.remote, reset_token);
5231 self.open_nat_traversed_paths(now);
5232 }
5233 Err(InsertError::ExceedsLimit) => {
5234 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR(""));
5235 }
5236 Err(InsertError::Retired) => {
5237 trace!("discarding already-retired");
5238 self.spaces[SpaceId::Data]
5242 .pending
5243 .retire_cids
5244 .push((path_id, frame.sequence));
5245 continue;
5246 }
5247 };
5248
5249 if self.side.is_server()
5250 && path_id == PathId::ZERO
5251 && self
5252 .remote_cids
5253 .get(&PathId::ZERO)
5254 .map(|cids| cids.active_seq() == 0)
5255 .unwrap_or_default()
5256 {
5257 self.update_remote_cid(PathId::ZERO);
5260 }
5261 }
5262 Frame::NewToken(NewToken { token }) => {
5263 let ConnectionSide::Client {
5264 token_store,
5265 server_name,
5266 ..
5267 } = &self.side
5268 else {
5269 return Err(TransportError::PROTOCOL_VIOLATION("client sent NEW_TOKEN"));
5270 };
5271 if token.is_empty() {
5272 return Err(TransportError::FRAME_ENCODING_ERROR("empty token"));
5273 }
5274 trace!("got new token");
5275 token_store.insert(server_name, token);
5276 }
5277 Frame::Datagram(datagram) => {
5278 if self
5279 .datagrams
5280 .received(datagram, &self.config.datagram_receive_buffer_size)?
5281 {
5282 self.events.push_back(Event::DatagramReceived);
5283 }
5284 }
5285 Frame::AckFrequency(ack_frequency) => {
5286 if !self.ack_frequency.ack_frequency_received(&ack_frequency)? {
5289 continue;
5292 }
5293
5294 for (path_id, space) in self.spaces[SpaceId::Data].number_spaces.iter_mut() {
5296 space.pending_acks.set_ack_frequency_params(&ack_frequency);
5297
5298 if !self.abandoned_paths.contains(path_id)
5302 && let Some(timeout) = space
5303 .pending_acks
5304 .max_ack_delay_timeout(self.ack_frequency.max_ack_delay)
5305 {
5306 self.timers.set(
5307 Timer::PerPath(*path_id, PathTimer::MaxAckDelay),
5308 timeout,
5309 self.qlog.with_time(now),
5310 );
5311 }
5312 }
5313 }
5314 Frame::ImmediateAck => {
5315 for pns in self.spaces[SpaceId::Data].iter_paths_mut() {
5317 pns.pending_acks.set_immediate_ack_required();
5318 }
5319 }
5320 Frame::HandshakeDone => {
5321 if self.side.is_server() {
5322 return Err(TransportError::PROTOCOL_VIOLATION(
5323 "client sent HANDSHAKE_DONE",
5324 ));
5325 }
5326 if self.crypto_state.has_keys(EncryptionLevel::Handshake) {
5327 self.discard_space(now, SpaceKind::Handshake);
5328 self.events.push_back(Event::HandshakeConfirmed);
5329 trace!("handshake confirmed");
5330 }
5331 }
5332 Frame::ObservedAddr(observed) => {
5333 trace!(seq_no = %observed.seq_no, ip = %observed.ip, port = observed.port);
5335 if !self
5336 .peer_params
5337 .address_discovery_role
5338 .should_report(&self.config.address_discovery_role)
5339 {
5340 return Err(TransportError::PROTOCOL_VIOLATION(
5341 "received OBSERVED_ADDRESS frame when not negotiated",
5342 ));
5343 }
5344 if packet.header.space() != SpaceKind::Data {
5346 return Err(TransportError::PROTOCOL_VIOLATION(
5347 "OBSERVED_ADDRESS frame outside data space",
5348 ));
5349 }
5350
5351 let path = self.path_data_mut(path_id);
5352 if path.network_path.remote == network_path.remote {
5353 if let Some(updated) = path.update_observed_addr_report(observed)
5354 && path.open_status == paths::OpenStatus::Informed
5355 {
5356 self.events.push_back(Event::Path(PathEvent::ObservedAddr {
5357 id: path_id,
5358 addr: updated,
5359 }));
5360 }
5362 } else {
5363 migration_observed_addr = Some(observed)
5365 }
5366 }
5367 Frame::PathAbandon(frame::PathAbandon {
5368 path_id,
5369 error_code,
5370 }) => {
5371 span.record("path", tracing::field::display(&path_id));
5372 match self.close_path_inner(
5373 now,
5374 path_id,
5375 PathAbandonReason::RemoteAbandoned {
5376 error_code: error_code.into(),
5377 },
5378 ) {
5379 Ok(()) => {
5380 trace!("peer abandoned path");
5381 }
5382 Err(ClosePathError::ClosedPath) => {
5383 trace!("peer abandoned already closed path");
5384 }
5385 Err(ClosePathError::MultipathNotNegotiated) => {
5386 return Err(TransportError::PROTOCOL_VIOLATION(
5387 "received PATH_ABANDON frame when multipath was not negotiated",
5388 ));
5389 }
5390 Err(ClosePathError::LastOpenPath) => {
5391 error!(
5394 "peer abandoned last path but close_path_inner returned LastOpenPath"
5395 );
5396 }
5397 };
5398
5399 if let Some(path) = self.paths.get_mut(&path_id)
5401 && !mem::replace(&mut path.data.draining, true)
5402 {
5403 let ack_delay = self.ack_frequency.max_ack_delay_for_pto();
5404 let pto = path.data.rtt.pto_base() + ack_delay;
5405 self.timers.set(
5406 Timer::PerPath(path_id, PathTimer::PathDrained),
5407 now + 3 * pto,
5408 self.qlog.with_time(now),
5409 );
5410
5411 self.set_max_path_id(now, self.local_max_path_id.saturating_add(1u8));
5412 }
5413 }
5414 Frame::PathStatusAvailable(info) => {
5415 span.record("path", tracing::field::display(&info.path_id));
5416 if self.is_multipath_negotiated() {
5417 self.on_path_status(
5418 info.path_id,
5419 PathStatus::Available,
5420 info.status_seq_no,
5421 );
5422 } else {
5423 return Err(TransportError::PROTOCOL_VIOLATION(
5424 "received PATH_STATUS_AVAILABLE frame when multipath was not negotiated",
5425 ));
5426 }
5427 }
5428 Frame::PathStatusBackup(info) => {
5429 span.record("path", tracing::field::display(&info.path_id));
5430 if self.is_multipath_negotiated() {
5431 self.on_path_status(info.path_id, PathStatus::Backup, info.status_seq_no);
5432 } else {
5433 return Err(TransportError::PROTOCOL_VIOLATION(
5434 "received PATH_STATUS_BACKUP frame when multipath was not negotiated",
5435 ));
5436 }
5437 }
5438 Frame::MaxPathId(frame::MaxPathId(path_id)) => {
5439 span.record("path", tracing::field::display(&path_id));
5440 if !self.is_multipath_negotiated() {
5441 return Err(TransportError::PROTOCOL_VIOLATION(
5442 "received MAX_PATH_ID frame when multipath was not negotiated",
5443 ));
5444 }
5445 if path_id > self.remote_max_path_id {
5447 self.remote_max_path_id = path_id;
5448 self.issue_first_path_cids(now);
5449 self.open_nat_traversed_paths(now);
5450 }
5451 }
5452 Frame::PathsBlocked(frame::PathsBlocked(max_path_id)) => {
5453 if self.is_multipath_negotiated() {
5457 if max_path_id > self.local_max_path_id {
5458 return Err(TransportError::PROTOCOL_VIOLATION(
5459 "PATHS_BLOCKED maximum path identifier was larger than local maximum",
5460 ));
5461 }
5462 debug!("received PATHS_BLOCKED({:?})", max_path_id);
5463 } else {
5465 return Err(TransportError::PROTOCOL_VIOLATION(
5466 "received PATHS_BLOCKED frame when not multipath was not negotiated",
5467 ));
5468 }
5469 }
5470 Frame::PathCidsBlocked(frame::PathCidsBlocked { path_id, next_seq }) => {
5471 if self.is_multipath_negotiated() {
5479 if path_id > self.local_max_path_id {
5480 return Err(TransportError::PROTOCOL_VIOLATION(
5481 "PATH_CIDS_BLOCKED path identifier was larger than local maximum",
5482 ));
5483 }
5484 if next_seq.0
5485 > self
5486 .local_cid_state
5487 .get(&path_id)
5488 .map(|cid_state| cid_state.active_seq().1 + 1)
5489 .unwrap_or_default()
5490 {
5491 return Err(TransportError::PROTOCOL_VIOLATION(
5492 "PATH_CIDS_BLOCKED next sequence number larger than in local state",
5493 ));
5494 }
5495 debug!(%path_id, %next_seq, "received PATH_CIDS_BLOCKED");
5496 } else {
5497 return Err(TransportError::PROTOCOL_VIOLATION(
5498 "received PATH_CIDS_BLOCKED frame when not multipath was not negotiated",
5499 ));
5500 }
5501 }
5502 Frame::AddAddress(addr) => {
5503 let client_state = match self.n0_nat_traversal.client_side_mut() {
5504 Ok(state) => state,
5505 Err(err) => {
5506 return Err(TransportError::PROTOCOL_VIOLATION(format!(
5507 "Nat traversal(ADD_ADDRESS): {err}"
5508 )));
5509 }
5510 };
5511
5512 if !client_state.check_remote_address(&addr) {
5513 warn!(?addr, "server sent illegal ADD_ADDRESS frame");
5515 }
5516
5517 match client_state.add_remote_address(addr) {
5518 Ok(maybe_added) => {
5519 if let Some(added) = maybe_added {
5520 self.events.push_back(Event::NatTraversal(
5521 n0_nat_traversal::Event::AddressAdded(added),
5522 ));
5523 }
5524 }
5525 Err(e) => {
5526 warn!(%e, "failed to add remote address")
5527 }
5528 }
5529 }
5530 Frame::RemoveAddress(addr) => {
5531 let client_state = match self.n0_nat_traversal.client_side_mut() {
5532 Ok(state) => state,
5533 Err(err) => {
5534 return Err(TransportError::PROTOCOL_VIOLATION(format!(
5535 "Nat traversal(REMOVE_ADDRESS): {err}"
5536 )));
5537 }
5538 };
5539 if let Some(removed_addr) = client_state.remove_remote_address(addr) {
5540 self.events.push_back(Event::NatTraversal(
5541 n0_nat_traversal::Event::AddressRemoved(removed_addr),
5542 ));
5543 }
5544 }
5545 Frame::ReachOut(reach_out) => {
5546 let ipv6 = self.is_ipv6();
5547 let server_state = match self.n0_nat_traversal.server_side_mut() {
5548 Ok(state) => state,
5549 Err(err) => {
5550 return Err(TransportError::PROTOCOL_VIOLATION(format!(
5551 "Nat traversal(REACH_OUT): {err}"
5552 )));
5553 }
5554 };
5555
5556 let round_before = server_state.current_round();
5557
5558 if let Err(err) = server_state.handle_reach_out(reach_out, ipv6) {
5559 return Err(TransportError::PROTOCOL_VIOLATION(format!(
5560 "Nat traversal(REACH_OUT): {err}"
5561 )));
5562 }
5563
5564 if server_state.current_round() > round_before {
5565 if let Some(delay) =
5567 self.n0_nat_traversal.retry_delay(self.config.initial_rtt)
5568 {
5569 self.timers.set(
5570 Timer::Conn(ConnTimer::NatTraversalProbeRetry),
5571 now + delay,
5572 self.qlog.with_time(now),
5573 );
5574 }
5575 }
5576 }
5577 }
5578 }
5579
5580 let space = self.spaces[SpaceId::Data].for_path(path_id);
5581 if space
5582 .pending_acks
5583 .packet_received(now, number, ack_eliciting, &space.dedup)
5584 {
5585 if self.abandoned_paths.contains(&path_id) {
5586 space.pending_acks.set_immediate_ack_required();
5589 } else {
5590 self.timers.set(
5591 Timer::PerPath(path_id, PathTimer::MaxAckDelay),
5592 now + self.ack_frequency.max_ack_delay,
5593 self.qlog.with_time(now),
5594 );
5595 }
5596 }
5597
5598 let pending = &mut self.spaces[SpaceId::Data].pending;
5603 self.streams.queue_max_stream_id(pending);
5604
5605 if let Some(reason) = close {
5606 self.state.move_to_draining(Some(reason.into()));
5607 self.endpoint_events.push_back(EndpointEventInner::Draining);
5608 self.connection_close_pending = true;
5609 }
5610
5611 let migrate_on_any_packet =
5614 self.is_multipath_negotiated() && !self.n0_nat_traversal.is_negotiated();
5615
5616 let is_largest_received_pn = Some(number)
5618 == self.spaces[SpaceId::Data]
5619 .for_path(path_id)
5620 .largest_received_packet_number;
5621
5622 if (migrate_on_any_packet || !is_probing_packet)
5627 && is_largest_received_pn
5628 && self.local_ip_may_migrate()
5629 && let Some(new_local_ip) = network_path.local_ip
5630 {
5631 let path_data = self.path_data_mut(path_id);
5632 if path_data
5633 .network_path
5634 .local_ip
5635 .is_some_and(|ip| ip != new_local_ip)
5636 {
5637 debug!(
5638 %path_id,
5639 new_4tuple = %network_path,
5640 prev_4tuple = %path_data.network_path,
5641 "local address passive migration"
5642 );
5643 }
5644 path_data.network_path.local_ip = Some(new_local_ip)
5645 }
5646
5647 if self.peer_may_migrate()
5649 && (migrate_on_any_packet || !is_probing_packet)
5650 && is_largest_received_pn
5651 && network_path.remote != self.path_data(path_id).network_path.remote
5652 {
5653 self.migrate(path_id, now, network_path, migration_observed_addr);
5654 self.update_remote_cid(path_id);
5656 self.spin = false;
5657 }
5658
5659 Ok(())
5660 }
5661
5662 fn open_nat_traversed_paths(&mut self, now: Instant) {
5664 while let Some(network_path) = self
5665 .n0_nat_traversal
5666 .client_side_mut()
5667 .ok()
5668 .and_then(|s| s.pop_pending_path_open())
5669 {
5670 match self.open_path_ensure(network_path, PathStatus::Backup, now) {
5671 Ok((path_id, already_existed)) => {
5672 debug!(
5673 %path_id,
5674 ?network_path,
5675 new_path = !already_existed,
5676 "Opened NAT traversal path",
5677 );
5678 }
5679 Err(err) => match err {
5680 PathError::MultipathNotNegotiated
5681 | PathError::ServerSideNotAllowed
5682 | PathError::ValidationFailed
5683 | PathError::InvalidRemoteAddress(_) => {
5684 error!(
5685 ?err,
5686 ?network_path,
5687 "Failed to open path for successful NAT traversal"
5688 );
5689 }
5690 PathError::MaxPathIdReached | PathError::RemoteCidsExhausted => {
5691 self.n0_nat_traversal
5693 .client_side_mut()
5694 .map(|s| s.push_pending_path_open(network_path))
5695 .ok();
5696 debug!(
5697 ?err,
5698 ?network_path,
5699 "Blocked opening NAT traversal path, enqueued"
5700 );
5701 return;
5702 }
5703 },
5704 }
5705 }
5706 }
5707
5708 fn migrate(
5713 &mut self,
5714 path_id: PathId,
5715 now: Instant,
5716 network_path: FourTuple,
5717 observed_addr: Option<ObservedAddr>,
5718 ) {
5719 trace!(
5720 new_4tuple = %network_path,
5721 prev_4tuple = %self.path_data(path_id).network_path,
5722 %path_id,
5723 "migration initiated",
5724 );
5725 self.path_generation_counter = self.path_generation_counter.wrapping_add(1);
5726 let prev_pto = self.pto(SpaceKind::Data, path_id);
5733 let path = self.paths.get_mut(&path_id).expect("known path");
5734 let mut new_path_data = if network_path.remote.is_ipv4()
5735 && network_path.remote.ip() == path.data.network_path.remote.ip()
5736 {
5737 PathData::from_previous(network_path, &path.data, self.path_generation_counter, now)
5738 } else {
5739 let peer_max_udp_payload_size =
5740 u16::try_from(self.peer_params.max_udp_payload_size.into_inner())
5741 .unwrap_or(u16::MAX);
5742 PathData::new(
5743 network_path,
5744 self.allow_mtud,
5745 Some(peer_max_udp_payload_size),
5746 self.path_generation_counter,
5747 now,
5748 &self.config,
5749 )
5750 };
5751 new_path_data.last_observed_addr_report = path.data.last_observed_addr_report.clone();
5752 if let Some(report) = observed_addr
5753 && let Some(updated) = new_path_data.update_observed_addr_report(report)
5754 {
5755 tracing::info!("adding observed addr event from migration");
5756 self.events.push_back(Event::Path(PathEvent::ObservedAddr {
5757 id: path_id,
5758 addr: updated,
5759 }));
5760 }
5761 new_path_data.pending_on_path_challenge = true;
5762
5763 let mut prev_path_data = mem::replace(&mut path.data, new_path_data);
5764
5765 if !prev_path_data.validated
5774 && let Some(cid) = self.remote_cids.get(&path_id).map(CidQueue::active)
5775 {
5776 prev_path_data.pending_on_path_challenge = true;
5777 path.prev = Some((cid, prev_path_data));
5780 }
5781
5782 self.qlog.emit_tuple_assigned(path_id, network_path, now);
5784
5785 self.timers.set(
5786 Timer::PerPath(path_id, PathTimer::PathValidationFailed),
5787 now + 3 * cmp::max(self.pto(SpaceKind::Data, path_id), prev_pto),
5788 self.qlog.with_time(now),
5789 );
5790 }
5791
5792 pub fn handle_network_change(&mut self, hint: Option<&dyn NetworkChangeHint>, now: Instant) {
5809 debug!("network changed");
5810 if self.state.is_drained() {
5811 return;
5812 }
5813 if self.highest_space < SpaceKind::Data {
5814 for path in self.paths.values_mut() {
5815 path.data.network_path.local_ip = None;
5817 }
5818
5819 self.update_remote_cid(PathId::ZERO);
5820 self.ping();
5821
5822 return;
5823 }
5824
5825 let mut non_recoverable_paths = Vec::default();
5828 let mut recoverable_paths = Vec::default();
5829 let mut open_paths = 0;
5830
5831 let is_multipath_negotiated = self.is_multipath_negotiated();
5832 let is_client = self.side().is_client();
5833 let immediate_ack_allowed = self.peer_supports_ack_frequency();
5834
5835 for (path_id, path) in self.paths.iter_mut() {
5836 if self.abandoned_paths.contains(path_id) {
5837 continue;
5838 }
5839 open_paths += 1;
5840
5841 let network_path = path.data.network_path;
5844
5845 path.data.network_path.local_ip = None;
5848 let remote = network_path.remote;
5849
5850 let attempt_to_recover = if is_multipath_negotiated {
5854 hint.map(|h| h.is_path_recoverable(*path_id, network_path))
5858 .unwrap_or(!is_client)
5859 } else {
5860 true
5862 };
5863
5864 if attempt_to_recover {
5865 recoverable_paths.push((*path_id, remote));
5866 } else {
5867 non_recoverable_paths.push((*path_id, remote, path.data.local_status()))
5868 }
5869 }
5870
5871 let open_first = open_paths == non_recoverable_paths.len();
5880
5881 for (path_id, remote, status) in non_recoverable_paths.into_iter() {
5882 let network_path = FourTuple {
5883 remote,
5884 local_ip: None, };
5886
5887 if open_first && let Err(e) = self.open_path(network_path, status, now) {
5888 if self.side().is_client() {
5889 debug!(%e, "Failed to open new path for network change");
5890 }
5891 recoverable_paths.push((path_id, remote));
5893 continue;
5894 }
5895
5896 if let Err(e) =
5897 self.close_path_inner(now, path_id, PathAbandonReason::UnusableAfterNetworkChange)
5898 {
5899 debug!(%e,"Failed to close unrecoverable path after network change");
5900 recoverable_paths.push((path_id, remote));
5901 continue;
5902 }
5903
5904 if !open_first && let Err(e) = self.open_path(network_path, status, now) {
5905 debug!(%e,"Failed to open new path for network change");
5909 }
5910 }
5911
5912 for (path_id, remote) in recoverable_paths.into_iter() {
5915 if let Some(path_space) = self.spaces[SpaceId::Data].number_spaces.get_mut(&path_id) {
5917 path_space.ping_pending = true;
5918
5919 if immediate_ack_allowed {
5920 path_space.immediate_ack_pending = true;
5921 }
5922 }
5923
5924 if let Some(path) = self.paths.get_mut(&path_id) {
5929 path.data.pto_count = 0;
5930 }
5931 self.set_loss_detection_timer(now, path_id);
5932
5933 let Some((reset_token, retired)) =
5934 self.remote_cids.get_mut(&path_id).and_then(CidQueue::next)
5935 else {
5936 continue;
5937 };
5938
5939 self.spaces[SpaceId::Data]
5941 .pending
5942 .retire_cids
5943 .extend(retired.map(|seq| (path_id, seq)));
5944
5945 debug_assert!(!self.state.is_drained()); self.endpoint_events
5947 .push_back(EndpointEventInner::ResetToken(path_id, remote, reset_token));
5948 }
5949 }
5950
5951 fn update_remote_cid(&mut self, path_id: PathId) {
5953 let Some((reset_token, retired)) = self
5954 .remote_cids
5955 .get_mut(&path_id)
5956 .and_then(|cids| cids.next())
5957 else {
5958 return;
5959 };
5960
5961 self.spaces[SpaceId::Data]
5963 .pending
5964 .retire_cids
5965 .extend(retired.map(|seq| (path_id, seq)));
5966 let remote = self.path_data(path_id).network_path.remote;
5967 self.set_reset_token(path_id, remote, reset_token);
5968 }
5969
5970 fn set_reset_token(&mut self, path_id: PathId, remote: SocketAddr, reset_token: ResetToken) {
5979 debug_assert!(!self.state.is_drained()); self.endpoint_events
5981 .push_back(EndpointEventInner::ResetToken(path_id, remote, reset_token));
5982
5983 if path_id == PathId::ZERO {
5989 self.peer_params.stateless_reset_token = Some(reset_token);
5990 }
5991 }
5992
5993 fn issue_first_cids(&mut self, now: Instant) {
5995 if self
5996 .local_cid_state
5997 .get(&PathId::ZERO)
5998 .expect("PathId::ZERO exists when the connection is created")
5999 .cid_len()
6000 == 0
6001 {
6002 return;
6003 }
6004
6005 let mut n = self.peer_params.issue_cids_limit() - 1;
6007 if let ConnectionSide::Server { server_config } = &self.side
6008 && server_config.has_preferred_address()
6009 {
6010 n -= 1;
6012 }
6013 debug_assert!(!self.state.is_drained()); self.endpoint_events
6015 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n));
6016 }
6017
6018 fn issue_first_path_cids(&mut self, now: Instant) {
6022 if let Some(max_path_id) = self.max_path_id() {
6023 let mut path_id = self.max_path_id_with_cids.next();
6024 while path_id <= max_path_id {
6025 self.endpoint_events
6026 .push_back(EndpointEventInner::NeedIdentifiers(
6027 path_id,
6028 now,
6029 self.peer_params.issue_cids_limit(),
6030 ));
6031 path_id = path_id.next();
6032 }
6033 self.max_path_id_with_cids = max_path_id;
6034 }
6035 }
6036
6037 fn populate_packet<'a, 'b>(
6045 &mut self,
6046 now: Instant,
6047 space_id: SpaceId,
6048 path_id: PathId,
6049 scheduling_info: &PathSchedulingInfo,
6050 builder: &mut PacketBuilder<'a, 'b>,
6051 ) {
6052 let is_multipath_negotiated = self.is_multipath_negotiated();
6053 let space_has_keys = self.crypto_state.has_keys(space_id.encryption_level());
6054 let is_0rtt = space_id == SpaceId::Data && !space_has_keys;
6055 let stats = &mut self.path_stats.for_path(path_id).frame_tx;
6056 let space = &mut self.spaces[space_id];
6057 let path = &mut self.paths.get_mut(&path_id).expect("known path").data;
6058 space
6059 .for_path(path_id)
6060 .pending_acks
6061 .maybe_ack_non_eliciting();
6062
6063 if !is_0rtt
6065 && !scheduling_info.is_abandoned
6066 && scheduling_info.may_send_data
6067 && mem::replace(&mut space.pending.handshake_done, false)
6068 {
6069 builder.write_frame(frame::HandshakeDone, stats);
6070 }
6071
6072 if !scheduling_info.is_abandoned
6074 && mem::replace(&mut space.for_path(path_id).ping_pending, false)
6075 {
6076 builder.write_frame(frame::Ping, stats);
6077 }
6078
6079 if !scheduling_info.is_abandoned
6081 && mem::replace(&mut space.for_path(path_id).immediate_ack_pending, false)
6082 {
6083 debug_assert_eq!(
6084 space_id,
6085 SpaceId::Data,
6086 "immediate acks must be sent in the data space"
6087 );
6088 builder.write_frame(frame::ImmediateAck, stats);
6089 }
6090
6091 if !scheduling_info.is_abandoned && scheduling_info.may_send_data {
6093 for path_id in space
6094 .number_spaces
6095 .iter_mut()
6096 .filter(|(_, pns)| pns.pending_acks.can_send())
6097 .map(|(&path_id, _)| path_id)
6098 .collect::<Vec<_>>()
6099 {
6100 Self::populate_acks(
6101 now,
6102 self.receiving_ecn,
6103 path_id,
6104 space_id,
6105 space,
6106 is_multipath_negotiated,
6107 builder,
6108 stats,
6109 space_has_keys,
6110 );
6111 }
6112 }
6113
6114 if !scheduling_info.is_abandoned
6116 && scheduling_info.may_send_data
6117 && mem::replace(&mut space.pending.ack_frequency, false)
6118 {
6119 let sequence_number = self.ack_frequency.next_sequence_number();
6120
6121 let config = self.config.ack_frequency_config.as_ref().unwrap();
6123
6124 let max_ack_delay = self.ack_frequency.candidate_max_ack_delay(
6126 path.rtt.get(),
6127 config,
6128 &self.peer_params,
6129 );
6130
6131 let frame = frame::AckFrequency {
6132 sequence: sequence_number,
6133 ack_eliciting_threshold: config.ack_eliciting_threshold,
6134 request_max_ack_delay: max_ack_delay.as_micros().try_into().unwrap_or(VarInt::MAX),
6135 reordering_threshold: config.reordering_threshold,
6136 };
6137 builder.write_frame(frame, stats);
6138
6139 self.ack_frequency
6140 .ack_frequency_sent(path_id, builder.packet_number, max_ack_delay);
6141 }
6142
6143 if !scheduling_info.is_abandoned
6145 && space_id == SpaceId::Data
6146 && path.pending_on_path_challenge
6147 && !self.state.is_closed()
6149 && builder.frame_space_remaining() > frame::PathChallenge::SIZE_BOUND
6150 && !(builder.buf.num_datagrams() > 1 && builder.buf.segment_size() < usize::from(MIN_INITIAL_SIZE))
6154 {
6155 path.pending_on_path_challenge = false;
6156
6157 let token = self.rng.random();
6158 path.record_path_challenge_sent(now, token, path.network_path);
6159 let challenge = frame::PathChallenge(token);
6161 builder.write_frame(challenge, stats);
6162 builder.require_padding();
6163 let pto = self.ack_frequency.max_ack_delay_for_pto() + path.rtt.pto_base();
6164 match path.open_status {
6165 paths::OpenStatus::Sent | paths::OpenStatus::Informed => {}
6166 paths::OpenStatus::Pending => {
6167 path.open_status = paths::OpenStatus::Sent;
6168 self.timers.set(
6169 Timer::PerPath(path_id, PathTimer::AbandonFromValidation),
6170 now + 3 * pto,
6171 self.qlog.with_time(now),
6172 );
6173 }
6174 }
6175
6176 self.timers.set(
6177 Timer::PerPath(path_id, PathTimer::PathChallengeLost),
6178 now + path.on_path_challenge_expiry(),
6179 self.qlog.with_time(now),
6180 );
6181
6182 if is_multipath_negotiated && !path.validated && path.pending_on_path_challenge {
6183 space.pending.path_status.insert(path_id);
6185 }
6186
6187 if space_id == SpaceId::Data
6190 && self
6191 .config
6192 .address_discovery_role
6193 .should_report(&self.peer_params.address_discovery_role)
6194 {
6195 let frame = frame::ObservedAddr::new(
6196 path.network_path.remote,
6197 self.next_observed_addr_seq_no,
6198 );
6199 if builder.frame_space_remaining() > frame.size() {
6200 builder.write_frame(frame, stats);
6201
6202 self.next_observed_addr_seq_no =
6203 self.next_observed_addr_seq_no.saturating_add(1u8);
6204 path.observed_addr_sent = true;
6205
6206 space.pending.observed_addr = false;
6207 }
6208 }
6209 }
6210
6211 if !scheduling_info.is_abandoned
6213 && space_id == SpaceId::Data
6214 && builder.frame_space_remaining() > frame::PathResponse::SIZE_BOUND
6215 && let Some(token) = path.path_responses.pop_on_path(path.network_path)
6216 && !(builder.buf.num_datagrams() > 1 && builder.buf.segment_size() < usize::from(MIN_INITIAL_SIZE))
6220 {
6221 let response = frame::PathResponse(token);
6222 builder.write_frame(response, stats);
6223 builder.require_padding();
6224
6225 if space_id == SpaceId::Data
6229 && self
6230 .config
6231 .address_discovery_role
6232 .should_report(&self.peer_params.address_discovery_role)
6233 {
6234 let frame = frame::ObservedAddr::new(
6235 path.network_path.remote,
6236 self.next_observed_addr_seq_no,
6237 );
6238 if builder.frame_space_remaining() > frame.size() {
6239 builder.write_frame(frame, stats);
6240
6241 self.next_observed_addr_seq_no =
6242 self.next_observed_addr_seq_no.saturating_add(1u8);
6243 path.observed_addr_sent = true;
6244
6245 space.pending.observed_addr = false;
6246 }
6247 }
6248 }
6249
6250 while !scheduling_info.is_abandoned
6252 && scheduling_info.may_send_data
6253 && let Some(reach_out) = space
6254 .pending
6255 .reach_out
6256 .pop_if(|frame| builder.frame_space_remaining() >= frame.size())
6257 {
6258 builder.write_frame(reach_out, stats);
6259 }
6260
6261 if space_id == SpaceId::Data
6263 && scheduling_info.is_abandoned
6264 && scheduling_info.may_self_abandon
6265 && frame::PathAbandon::SIZE_BOUND <= builder.frame_space_remaining()
6266 && let Some(error_code) = space.pending.path_abandon.remove(&path_id)
6267 {
6268 let frame = frame::PathAbandon {
6269 path_id,
6270 error_code,
6271 };
6272 builder.write_frame(frame, stats);
6273
6274 self.remote_cids.remove(&path_id);
6277 }
6278 while space_id == SpaceId::Data
6279 && scheduling_info.may_send_data
6280 && frame::PathAbandon::SIZE_BOUND <= builder.frame_space_remaining()
6281 && let Some((abandoned_path_id, error_code)) = space.pending.path_abandon.pop_first()
6282 {
6283 let frame = frame::PathAbandon {
6284 path_id: abandoned_path_id,
6285 error_code,
6286 };
6287 builder.write_frame(frame, stats);
6288
6289 self.remote_cids.remove(&abandoned_path_id);
6292 }
6293
6294 if !scheduling_info.is_abandoned
6296 && scheduling_info.may_send_data
6297 && space_id == SpaceId::Data
6298 && self
6299 .config
6300 .address_discovery_role
6301 .should_report(&self.peer_params.address_discovery_role)
6302 && (!path.observed_addr_sent || space.pending.observed_addr)
6303 {
6304 let frame =
6305 frame::ObservedAddr::new(path.network_path.remote, self.next_observed_addr_seq_no);
6306 if builder.frame_space_remaining() > frame.size() {
6307 builder.write_frame(frame, stats);
6308
6309 self.next_observed_addr_seq_no = self.next_observed_addr_seq_no.saturating_add(1u8);
6310 path.observed_addr_sent = true;
6311
6312 space.pending.observed_addr = false;
6313 }
6314 }
6315
6316 while !is_0rtt
6318 && !scheduling_info.is_abandoned
6319 && scheduling_info.may_send_data
6320 && builder.frame_space_remaining() > frame::Crypto::SIZE_BOUND
6321 {
6322 let Some(mut frame) = space.pending.crypto.pop_front() else {
6323 break;
6324 };
6325
6326 let max_crypto_data_size = builder.frame_space_remaining()
6331 - 1 - VarInt::size(unsafe { VarInt::from_u64_unchecked(frame.offset) })
6333 - 2; let len = frame
6336 .data
6337 .len()
6338 .min(2usize.pow(14) - 1)
6339 .min(max_crypto_data_size);
6340
6341 let data = frame.data.split_to(len);
6342 let offset = frame.offset;
6343 let truncated = frame::Crypto { offset, data };
6344 builder.write_frame(truncated, stats);
6345
6346 if !frame.data.is_empty() {
6347 frame.offset += len as u64;
6348 space.pending.crypto.push_front(frame);
6349 }
6350 }
6351
6352 while space_id == SpaceId::Data
6354 && !scheduling_info.is_abandoned
6355 && scheduling_info.may_send_data
6356 && frame::PathStatusAvailable::SIZE_BOUND <= builder.frame_space_remaining()
6357 {
6358 let Some(path_id) = space.pending.path_status.pop_first() else {
6359 break;
6360 };
6361 let Some(path) = self.paths.get(&path_id).map(|path_state| &path_state.data) else {
6362 trace!(%path_id, "discarding queued path status for unknown path");
6363 continue;
6364 };
6365
6366 let seq = path.status.seq();
6367 match path.local_status() {
6368 PathStatus::Available => {
6369 let frame = frame::PathStatusAvailable {
6370 path_id,
6371 status_seq_no: seq,
6372 };
6373 builder.write_frame(frame, stats);
6374 }
6375 PathStatus::Backup => {
6376 let frame = frame::PathStatusBackup {
6377 path_id,
6378 status_seq_no: seq,
6379 };
6380 builder.write_frame(frame, stats);
6381 }
6382 }
6383 }
6384
6385 if space_id == SpaceId::Data
6387 && !scheduling_info.is_abandoned
6388 && scheduling_info.may_send_data
6389 && space.pending.max_path_id
6390 && frame::MaxPathId::SIZE_BOUND <= builder.frame_space_remaining()
6391 {
6392 let frame = frame::MaxPathId(self.local_max_path_id);
6393 builder.write_frame(frame, stats);
6394 space.pending.max_path_id = false;
6395 }
6396
6397 if space_id == SpaceId::Data
6399 && !scheduling_info.is_abandoned
6400 && scheduling_info.may_send_data
6401 && space.pending.paths_blocked
6402 && frame::PathsBlocked::SIZE_BOUND <= builder.frame_space_remaining()
6403 {
6404 let frame = frame::PathsBlocked(self.remote_max_path_id);
6405 builder.write_frame(frame, stats);
6406 space.pending.paths_blocked = false;
6407 }
6408
6409 while space_id == SpaceId::Data
6411 && !scheduling_info.is_abandoned
6412 && scheduling_info.may_send_data
6413 && frame::PathCidsBlocked::SIZE_BOUND <= builder.frame_space_remaining()
6414 {
6415 let Some(path_id) = space.pending.path_cids_blocked.pop_first() else {
6416 break;
6417 };
6418 let next_seq = match self.remote_cids.get(&path_id) {
6419 Some(cid_queue) => VarInt(cid_queue.active_seq() + 1),
6420 None => VarInt(0),
6421 };
6422 let frame = frame::PathCidsBlocked { path_id, next_seq };
6423 builder.write_frame(frame, stats);
6424 }
6425
6426 if space_id == SpaceId::Data
6428 && !scheduling_info.is_abandoned
6429 && scheduling_info.may_send_data
6430 {
6431 self.streams
6432 .write_control_frames(builder, &mut space.pending, stats);
6433 }
6434
6435 let cid_len = self
6437 .local_cid_state
6438 .values()
6439 .map(|cid_state| cid_state.cid_len())
6440 .max()
6441 .expect("some local CID state must exist");
6442 let new_cid_size_bound =
6443 frame::NewConnectionId::size_bound(is_multipath_negotiated, cid_len);
6444 while !scheduling_info.is_abandoned
6445 && scheduling_info.may_send_data
6446 && builder.frame_space_remaining() > new_cid_size_bound
6447 {
6448 let Some(issued) = space.pending.new_cids.pop() else {
6449 break;
6450 };
6451 let Some(cid_state) = self.local_cid_state.get(&issued.path_id) else {
6453 debug!(
6454 path = %issued.path_id, seq = issued.sequence,
6455 "dropping queued NEW_CONNECTION_ID for discarded path",
6456 );
6457 continue;
6458 };
6459 let retire_prior_to = cid_state.retire_prior_to();
6460
6461 let cid_path_id = match is_multipath_negotiated {
6462 true => Some(issued.path_id),
6463 false => {
6464 debug_assert_eq!(issued.path_id, PathId::ZERO);
6465 None
6466 }
6467 };
6468 let frame = frame::NewConnectionId {
6469 path_id: cid_path_id,
6470 sequence: issued.sequence,
6471 retire_prior_to,
6472 id: issued.id,
6473 reset_token: issued.reset_token,
6474 };
6475 builder.write_frame(frame, stats);
6476 }
6477
6478 let retire_cid_bound = frame::RetireConnectionId::size_bound(is_multipath_negotiated);
6480 while !scheduling_info.is_abandoned
6481 && scheduling_info.may_send_data
6482 && builder.frame_space_remaining() > retire_cid_bound
6483 {
6484 let (path_id, sequence) = match space.pending.retire_cids.pop() {
6485 Some((PathId::ZERO, seq)) if !is_multipath_negotiated => (None, seq),
6486 Some((path_id, seq)) => (Some(path_id), seq),
6487 None => break,
6488 };
6489 let frame = frame::RetireConnectionId { path_id, sequence };
6490 builder.write_frame(frame, stats);
6491 }
6492
6493 let mut sent_datagrams = false;
6495 while !scheduling_info.is_abandoned
6496 && scheduling_info.may_send_data
6497 && builder.frame_space_remaining() > Datagram::SIZE_BOUND
6498 && space_id == SpaceId::Data
6499 {
6500 match self.datagrams.write(builder, stats) {
6501 true => {
6502 sent_datagrams = true;
6503 }
6504 false => break,
6505 }
6506 }
6507 if self.datagrams.send_blocked && sent_datagrams {
6508 self.events.push_back(Event::DatagramsUnblocked);
6509 self.datagrams.send_blocked = false;
6510 }
6511
6512 let path = &mut self.paths.get_mut(&path_id).expect("known path").data;
6513
6514 if !scheduling_info.is_abandoned && scheduling_info.may_send_data {
6516 while let Some(network_path) = space.pending.new_tokens.pop() {
6517 debug_assert_eq!(space_id, SpaceId::Data);
6518 let ConnectionSide::Server { server_config } = &self.side else {
6519 panic!("NEW_TOKEN frames should not be enqueued by clients");
6520 };
6521
6522 if !network_path.is_probably_same_path(&path.network_path) {
6523 continue;
6528 }
6529
6530 let token = Token::new(
6531 TokenPayload::Validation {
6532 ip: network_path.remote.ip(),
6533 issued: server_config.time_source.now(),
6534 },
6535 &mut self.rng,
6536 );
6537 let new_token = NewToken {
6538 token: token.encode(&*server_config.token_key).into(),
6539 };
6540
6541 if builder.frame_space_remaining() < new_token.size() {
6542 space.pending.new_tokens.push(network_path);
6543 break;
6544 }
6545
6546 builder.write_frame(new_token, stats);
6547 builder.retransmits_mut().new_tokens.push(network_path);
6548 }
6549 }
6550
6551 while space_id == SpaceId::Data
6553 && !scheduling_info.is_abandoned
6554 && scheduling_info.may_send_data
6555 && frame::AddAddress::SIZE_BOUND <= builder.frame_space_remaining()
6556 {
6557 if let Some(added_address) = space.pending.add_address.pop_last() {
6558 builder.write_frame(added_address, stats);
6559 } else {
6560 break;
6561 }
6562 }
6563
6564 while space_id == SpaceId::Data
6566 && !scheduling_info.is_abandoned
6567 && scheduling_info.may_send_data
6568 && frame::RemoveAddress::SIZE_BOUND <= builder.frame_space_remaining()
6569 {
6570 if let Some(removed_address) = space.pending.remove_address.pop_last() {
6571 builder.write_frame(removed_address, stats);
6572 } else {
6573 break;
6574 }
6575 }
6576
6577 if !scheduling_info.is_abandoned
6579 && scheduling_info.may_send_data
6580 && space_id == SpaceId::Data
6581 {
6582 self.streams
6583 .write_stream_frames(builder, self.config.send_fairness, stats);
6584 }
6585 }
6586
6587 fn populate_acks<'a, 'b>(
6589 now: Instant,
6590 receiving_ecn: bool,
6591 path_id: PathId,
6592 space_id: SpaceId,
6593 space: &mut PacketSpace,
6594 is_multipath_negotiated: bool,
6595 builder: &mut PacketBuilder<'a, 'b>,
6596 stats: &mut FrameStats,
6597 space_has_keys: bool,
6598 ) {
6599 debug_assert!(space_has_keys, "tried to send ACK in 0-RTT");
6601
6602 debug_assert!(
6603 is_multipath_negotiated || path_id == PathId::ZERO,
6604 "Only PathId::ZERO allowed without multipath (have {path_id:?})"
6605 );
6606 if is_multipath_negotiated {
6607 debug_assert!(
6608 space_id == SpaceId::Data || path_id == PathId::ZERO,
6609 "path acks must be sent in 1RTT space (have {space_id:?})"
6610 );
6611 }
6612
6613 let pns = space.for_path(path_id);
6614 let ranges = pns.pending_acks.ranges();
6615 debug_assert!(!ranges.is_empty(), "can not send empty ACK range");
6616 let ecn = if receiving_ecn {
6617 Some(&pns.ecn_counters)
6618 } else {
6619 None
6620 };
6621
6622 let delay_micros = pns.pending_acks.ack_delay(now).as_micros() as u64;
6623 let ack_delay_exp = TransportParameters::default().ack_delay_exponent;
6625 let delay = delay_micros >> ack_delay_exp.into_inner();
6626
6627 if is_multipath_negotiated && space_id == SpaceId::Data {
6628 if !ranges.is_empty() {
6629 let frame = frame::PathAck::encoder(path_id, delay, ranges, ecn);
6630 builder.write_frame(frame, stats);
6631 }
6632 } else {
6633 builder.write_frame(frame::Ack::encoder(delay, ranges, ecn), stats);
6634 }
6635 }
6636
6637 fn close_common(&mut self) {
6638 trace!("connection closed");
6639 self.timers.reset();
6640 }
6641
6642 fn set_close_timer(&mut self, now: Instant) {
6643 let pto_max = self.max_pto_for_space(self.highest_space);
6646 self.timers.set(
6647 Timer::Conn(ConnTimer::Close),
6648 now + 3 * pto_max,
6649 self.qlog.with_time(now),
6650 );
6651 }
6652
6653 fn handle_peer_params(
6658 &mut self,
6659 params: TransportParameters,
6660 local_cid: ConnectionId,
6661 remote_cid: ConnectionId,
6662 now: Instant,
6663 ) -> Result<(), TransportError> {
6664 if Some(self.original_remote_cid) != params.initial_src_cid
6665 || (self.side.is_client()
6666 && (Some(self.initial_dst_cid) != params.original_dst_cid
6667 || self.retry_src_cid != params.retry_src_cid))
6668 {
6669 return Err(TransportError::TRANSPORT_PARAMETER_ERROR(
6670 "CID authentication failure",
6671 ));
6672 }
6673 if params.initial_max_path_id.is_some() && (local_cid.is_empty() || remote_cid.is_empty()) {
6674 return Err(TransportError::PROTOCOL_VIOLATION(
6675 "multipath must not use zero-length CIDs",
6676 ));
6677 }
6678
6679 self.set_peer_params(params);
6680 self.qlog.emit_peer_transport_params_received(self, now);
6681
6682 Ok(())
6683 }
6684
6685 fn set_peer_params(&mut self, params: TransportParameters) {
6686 self.streams.set_params(¶ms);
6687 self.idle_timeout =
6688 negotiate_max_idle_timeout(self.config.max_idle_timeout, Some(params.max_idle_timeout));
6689 trace!("negotiated max idle timeout {:?}", self.idle_timeout);
6690
6691 if let Some(ref info) = params.preferred_address {
6692 self.remote_cids.get_mut(&PathId::ZERO).expect("not yet abandoned").insert(frame::NewConnectionId {
6694 path_id: None,
6695 sequence: 1,
6696 id: info.connection_id,
6697 reset_token: info.stateless_reset_token,
6698 retire_prior_to: 0,
6699 })
6700 .expect(
6701 "preferred address CID is the first received, and hence is guaranteed to be legal",
6702 );
6703 let remote = self.path_data(PathId::ZERO).network_path.remote;
6704 self.set_reset_token(PathId::ZERO, remote, info.stateless_reset_token);
6705 }
6706 self.ack_frequency.peer_max_ack_delay = get_max_ack_delay(¶ms);
6707
6708 let mut multipath_enabled = false;
6709 if let (Some(local_max_path_id), Some(remote_max_path_id)) = (
6710 self.config.get_initial_max_path_id(),
6711 params.initial_max_path_id,
6712 ) {
6713 self.local_max_path_id = local_max_path_id;
6715 self.remote_max_path_id = remote_max_path_id;
6716 let initial_max_path_id = local_max_path_id.min(remote_max_path_id);
6717 debug!(%initial_max_path_id, "multipath negotiated");
6718 multipath_enabled = true;
6719 }
6720
6721 if let Some((max_locally_allowed_remote_addresses, max_remotely_allowed_remote_addresses)) =
6722 self.config
6723 .max_remote_nat_traversal_addresses
6724 .zip(params.max_remote_nat_traversal_addresses)
6725 {
6726 if multipath_enabled {
6727 let max_local_addresses = max_remotely_allowed_remote_addresses.get();
6728 let max_remote_addresses = max_locally_allowed_remote_addresses.get();
6729 self.n0_nat_traversal = n0_nat_traversal::State::new(
6730 max_remote_addresses,
6731 max_local_addresses,
6732 self.side(),
6733 );
6734 debug!(
6735 %max_remote_addresses, %max_local_addresses,
6736 "n0's nat traversal negotiated"
6737 );
6738 } else {
6739 debug!("n0 nat traversal enabled for both endpoints, but multipath is missing")
6740 }
6741 }
6742
6743 self.peer_params = params;
6744 let peer_max_udp_payload_size =
6745 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()).unwrap_or(u16::MAX);
6746 self.path_data_mut(PathId::ZERO)
6747 .mtud
6748 .on_peer_max_udp_payload_size_received(peer_max_udp_payload_size);
6749 }
6750
6751 fn decrypt_packet(
6753 &mut self,
6754 now: Instant,
6755 path_id: PathId,
6756 packet: &mut Packet,
6757 ) -> Result<Option<u64>, Option<TransportError>> {
6758 let result = self
6759 .crypto_state
6760 .decrypt_packet_body(packet, path_id, &self.spaces)?;
6761
6762 let Some(result) = result else {
6763 return Ok(None);
6764 };
6765
6766 if result.outgoing_key_update_acked
6767 && let Some(prev) = self.crypto_state.prev_crypto.as_mut()
6768 {
6769 prev.end_packet = Some((result.packet_number, now));
6770 self.set_key_discard_timer(now, packet.header.space());
6771 }
6772
6773 if result.incoming_key_update {
6774 trace!("key update authenticated");
6775 self.crypto_state
6776 .update_keys(Some((result.packet_number, now)), true);
6777 self.set_key_discard_timer(now, packet.header.space());
6778 }
6779
6780 Ok(Some(result.packet_number))
6781 }
6782
6783 fn peer_supports_ack_frequency(&self) -> bool {
6784 self.peer_params.min_ack_delay.is_some()
6785 }
6786
6787 pub(crate) fn immediate_ack(&mut self, path_id: PathId) {
6792 debug_assert_eq!(
6793 self.highest_space,
6794 SpaceKind::Data,
6795 "immediate ack must be written in the data space"
6796 );
6797 self.spaces[SpaceId::Data]
6798 .for_path(path_id)
6799 .immediate_ack_pending = true;
6800 }
6801
6802 #[cfg(test)]
6804 pub(crate) fn decode_packet(&self, event: &ConnectionEvent) -> Option<Vec<u8>> {
6805 let ConnectionEventInner::Datagram(DatagramConnectionEvent {
6806 path_id,
6807 first_decode,
6808 remaining,
6809 ..
6810 }) = &event.0
6811 else {
6812 return None;
6813 };
6814
6815 if remaining.is_some() {
6816 panic!("Packets should never be coalesced in tests");
6817 }
6818
6819 let decrypted_header = self
6820 .crypto_state
6821 .unprotect_header(first_decode.clone(), self.peer_params.stateless_reset_token)?;
6822
6823 let mut packet = decrypted_header.packet?;
6824 self.crypto_state
6825 .decrypt_packet_body(&mut packet, *path_id, &self.spaces)
6826 .ok()?;
6827
6828 Some(packet.payload.to_vec())
6829 }
6830
6831 #[cfg(test)]
6834 pub(crate) fn bytes_in_flight(&self) -> u64 {
6835 self.path_data(PathId::ZERO).in_flight.bytes
6837 }
6838
6839 #[cfg(test)]
6841 pub(crate) fn congestion_window(&self) -> u64 {
6842 let path = self.path_data(PathId::ZERO);
6843 path.congestion
6844 .window()
6845 .saturating_sub(path.in_flight.bytes)
6846 }
6847
6848 #[cfg(test)]
6850 pub(crate) fn is_idle(&self) -> bool {
6851 let current_timers = self.timers.values();
6852 current_timers
6853 .into_iter()
6854 .filter(|(timer, _)| {
6855 !matches!(
6856 timer,
6857 Timer::Conn(ConnTimer::KeepAlive)
6858 | Timer::PerPath(_, PathTimer::PathKeepAlive)
6859 | Timer::Conn(ConnTimer::PushNewCid)
6860 | Timer::Conn(ConnTimer::KeyDiscard)
6861 )
6862 })
6863 .min_by_key(|(_, time)| *time)
6864 .is_none_or(|(timer, _)| {
6865 matches!(
6866 timer,
6867 Timer::Conn(ConnTimer::Idle) | Timer::PerPath(_, PathTimer::PathIdle)
6868 )
6869 })
6870 }
6871
6872 #[cfg(test)]
6874 pub(crate) fn using_ecn(&self) -> bool {
6875 self.path_data(PathId::ZERO).sending_ecn
6876 }
6877
6878 #[cfg(test)]
6880 pub(crate) fn total_recvd(&self) -> u64 {
6881 self.path_data(PathId::ZERO).total_recvd
6882 }
6883
6884 #[cfg(test)]
6885 pub(crate) fn active_local_cid_seq(&self) -> (u64, u64) {
6886 self.local_cid_state
6887 .get(&PathId::ZERO)
6888 .unwrap()
6889 .active_seq()
6890 }
6891
6892 #[cfg(test)]
6893 #[track_caller]
6894 pub(crate) fn active_local_path_cid_seq(&self, path_id: u32) -> (u64, u64) {
6895 self.local_cid_state
6896 .get(&PathId(path_id))
6897 .unwrap()
6898 .active_seq()
6899 }
6900
6901 #[cfg(test)]
6904 pub(crate) fn rotate_local_cid(&mut self, v: u64, now: Instant) {
6905 let n = self
6906 .local_cid_state
6907 .get_mut(&PathId::ZERO)
6908 .unwrap()
6909 .assign_retire_seq(v);
6910 debug_assert!(!self.state.is_drained()); self.endpoint_events
6912 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n));
6913 }
6914
6915 #[cfg(test)]
6917 pub(crate) fn active_remote_cid_seq(&self) -> u64 {
6918 self.remote_cids.get(&PathId::ZERO).unwrap().active_seq()
6919 }
6920
6921 #[cfg(test)]
6923 pub(crate) fn path_mtu(&self, path_id: PathId) -> u16 {
6924 self.path_data(path_id).current_mtu()
6925 }
6926
6927 #[cfg(test)]
6929 pub(crate) fn trigger_path_validation(&mut self) {
6930 for path in self.paths.values_mut() {
6931 path.data.pending_on_path_challenge = true;
6932 }
6933 }
6934
6935 #[cfg(test)]
6937 pub fn simulate_protocol_violation(&mut self, now: Instant) {
6938 if !self.state.is_closed() {
6939 self.state
6940 .move_to_closed(TransportError::PROTOCOL_VIOLATION("simulated violation"));
6941 self.close_common();
6942 if !self.state.is_drained() {
6943 self.set_close_timer(now);
6944 }
6945 self.connection_close_pending = true;
6946 }
6947 }
6948
6949 fn can_send_1rtt(&self, path_id: PathId, max_size: usize) -> SendableFrames {
6960 let space_specific = self.paths.get(&path_id).is_some_and(|path| {
6961 path.data.pending_on_path_challenge || !path.data.path_responses.is_empty()
6962 });
6963
6964 let other = self.streams.can_send_stream_data()
6966 || self
6967 .datagrams
6968 .outgoing
6969 .front()
6970 .is_some_and(|x| x.size(true) <= max_size);
6971
6972 SendableFrames {
6974 acks: false,
6975 close: false,
6976 space_specific,
6977 other,
6978 }
6979 }
6980
6981 fn kill(&mut self, reason: ConnectionError) {
6983 self.close_common();
6984 let was_draining = self.state.move_to_drained(Some(reason));
6985 if !was_draining {
6986 self.endpoint_events.push_back(EndpointEventInner::Draining);
6987 }
6988 self.endpoint_events.push_back(EndpointEventInner::Drained);
6991 }
6992
6993 pub fn current_mtu(&self) -> u16 {
7000 self.paths
7001 .iter()
7002 .filter(|&(path_id, _path_state)| !self.abandoned_paths.contains(path_id))
7003 .map(|(_path_id, path_state)| path_state.data.current_mtu())
7004 .min()
7005 .unwrap_or(INITIAL_MTU)
7006 }
7007
7008 fn predict_1rtt_overhead(&mut self, pn: u64, path: PathId) -> usize {
7015 let pn_len = PacketNumber::new(
7016 pn,
7017 self.spaces[SpaceId::Data]
7018 .for_path(path)
7019 .largest_acked_packet_pn
7020 .unwrap_or(0),
7021 )
7022 .len();
7023
7024 1 + self
7026 .remote_cids
7027 .get(&path)
7028 .map(|cids| cids.active().len())
7029 .unwrap_or(20) + pn_len
7031 + self.tag_len_1rtt()
7032 }
7033
7034 fn predict_1rtt_overhead_no_pn(&self) -> usize {
7035 let pn_len = 4;
7036
7037 let cid_len = self
7038 .remote_cids
7039 .values()
7040 .map(|cids| cids.active().len())
7041 .max()
7042 .unwrap_or(20); 1 + cid_len + pn_len + self.tag_len_1rtt()
7046 }
7047
7048 fn tag_len_1rtt(&self) -> usize {
7049 let packet_crypto = self
7051 .crypto_state
7052 .encryption_keys(SpaceKind::Data, self.side.side())
7053 .map(|(_header, packet, _level)| packet);
7054 packet_crypto.map_or(16, |x| x.tag_len())
7058 }
7059
7060 fn on_path_validated(&mut self, path_id: PathId) {
7062 self.path_data_mut(path_id).validated = true;
7063 let ConnectionSide::Server { server_config } = &self.side else {
7064 return;
7065 };
7066 let network_path = self.path_data(path_id).network_path;
7067 let new_tokens = &mut self.spaces[SpaceId::Data as usize].pending.new_tokens;
7068 new_tokens.clear();
7069 for _ in 0..server_config.validation_token.sent {
7070 new_tokens.push(network_path);
7071 }
7072 }
7073
7074 fn on_path_status(&mut self, path_id: PathId, status: PathStatus, status_seq_no: VarInt) {
7076 if let Some(path) = self.paths.get_mut(&path_id) {
7077 path.data.status.remote_update(status, status_seq_no);
7078 } else {
7079 debug!("PATH_STATUS_AVAILABLE received unknown path {:?}", path_id);
7080 }
7081 self.events.push_back(
7082 PathEvent::RemoteStatus {
7083 id: path_id,
7084 status,
7085 }
7086 .into(),
7087 );
7088 }
7089
7090 fn max_path_id(&self) -> Option<PathId> {
7099 if self.is_multipath_negotiated() {
7100 Some(self.remote_max_path_id.min(self.local_max_path_id))
7101 } else {
7102 None
7103 }
7104 }
7105
7106 pub(crate) fn is_ipv6(&self) -> bool {
7111 self.paths
7112 .values()
7113 .any(|p| p.data.network_path.remote.is_ipv6())
7114 }
7115
7116 pub fn add_nat_traversal_address(
7118 &mut self,
7119 address: SocketAddr,
7120 ) -> Result<(), n0_nat_traversal::Error> {
7121 if let Some(added) = self.n0_nat_traversal.add_local_address(address)? {
7122 self.spaces[SpaceId::Data].pending.add_address.insert(added);
7123 };
7124 Ok(())
7125 }
7126
7127 pub fn remove_nat_traversal_address(
7131 &mut self,
7132 address: SocketAddr,
7133 ) -> Result<(), n0_nat_traversal::Error> {
7134 if let Some(removed) = self.n0_nat_traversal.remove_local_address(address)? {
7135 self.spaces[SpaceId::Data]
7136 .pending
7137 .remove_address
7138 .insert(removed);
7139 }
7140 Ok(())
7141 }
7142
7143 pub fn get_local_nat_traversal_addresses(
7145 &self,
7146 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> {
7147 self.n0_nat_traversal.get_local_nat_traversal_addresses()
7148 }
7149
7150 pub fn get_remote_nat_traversal_addresses(
7152 &self,
7153 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> {
7154 Ok(self
7155 .n0_nat_traversal
7156 .client_side()?
7157 .get_remote_nat_traversal_addresses())
7158 }
7159
7160 pub fn initiate_nat_traversal_round(
7172 &mut self,
7173 now: Instant,
7174 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> {
7175 if self.state.is_closed() {
7176 return Err(n0_nat_traversal::Error::Closed);
7177 }
7178
7179 let ipv6 = self.is_ipv6();
7180 let client_state = self.n0_nat_traversal.client_side_mut()?;
7181 let (mut reach_out_frames, probed_addrs) =
7182 client_state.initiate_nat_traversal_round(ipv6)?;
7183 if let Some(delay) = self.n0_nat_traversal.retry_delay(self.config.initial_rtt) {
7184 self.timers.set(
7185 Timer::Conn(ConnTimer::NatTraversalProbeRetry),
7186 now + delay,
7187 self.qlog.with_time(now),
7188 );
7189 }
7190
7191 self.spaces[SpaceId::Data]
7192 .pending
7193 .reach_out
7194 .append(&mut reach_out_frames);
7195
7196 Ok(probed_addrs)
7197 }
7198
7199 fn is_handshake_confirmed(&self) -> bool {
7208 !self.is_handshaking() && !self.crypto_state.has_keys(EncryptionLevel::Handshake)
7209 }
7210}
7211
7212impl fmt::Debug for Connection {
7213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7214 f.debug_struct("Connection")
7215 .field("handshake_cid", &self.handshake_cid)
7216 .finish()
7217 }
7218}
7219
7220#[derive(Debug, Default)]
7226struct AbandonedPaths(ArrayRangeSet<ABANDONED_PATH_INLINE_RANGES, u32>);
7227
7228const ABANDONED_PATH_INLINE_RANGES: usize = 16;
7233
7234impl AbandonedPaths {
7235 fn len(&self) -> u32 {
7237 self.0.elts_count()
7238 }
7239
7240 fn max(&self) -> Option<PathId> {
7242 self.0.max().map(PathId::from)
7243 }
7244
7245 fn contains(&self, val: &PathId) -> bool {
7247 self.0.contains(val.as_u32())
7248 }
7249
7250 fn insert(&mut self, val: PathId) {
7252 self.0.insert_one(val.as_u32());
7253 }
7254}
7255
7256pub trait NetworkChangeHint: std::fmt::Debug + 'static {
7258 fn is_path_recoverable(&self, path_id: PathId, network_path: FourTuple) -> bool;
7267}
7268
7269#[derive(Debug)]
7271enum PollPathSpaceStatus {
7272 NothingToSend {
7274 congestion_blocked: bool,
7276 },
7277 WrotePacket {
7279 last_packet_number: u64,
7281 pad_datagram: PadDatagram,
7295 },
7296 Send {
7303 last_packet_number: u64,
7305 },
7306}
7307
7308#[derive(Debug, Copy, Clone)]
7314struct PathSchedulingInfo {
7315 is_abandoned: bool,
7321 may_send_data: bool,
7339 may_send_close: bool,
7345 may_self_abandon: bool,
7346}
7347
7348#[derive(Debug, Copy, Clone, PartialEq, Eq)]
7349enum PathBlocked {
7350 No,
7351 AntiAmplification,
7352 Congestion,
7353 Pacing,
7354}
7355
7356enum ConnectionSide {
7358 Client {
7359 token: Bytes,
7361 token_store: Arc<dyn TokenStore>,
7362 server_name: String,
7363 },
7364 Server {
7365 server_config: Arc<ServerConfig>,
7366 },
7367}
7368
7369impl ConnectionSide {
7370 fn is_client(&self) -> bool {
7371 self.side().is_client()
7372 }
7373
7374 fn is_server(&self) -> bool {
7375 self.side().is_server()
7376 }
7377
7378 fn side(&self) -> Side {
7379 match *self {
7380 Self::Client { .. } => Side::Client,
7381 Self::Server { .. } => Side::Server,
7382 }
7383 }
7384}
7385
7386impl From<SideArgs> for ConnectionSide {
7387 fn from(side: SideArgs) -> Self {
7388 match side {
7389 SideArgs::Client {
7390 token_store,
7391 server_name,
7392 } => Self::Client {
7393 token: token_store.take(&server_name).unwrap_or_default(),
7394 token_store,
7395 server_name,
7396 },
7397 SideArgs::Server {
7398 server_config,
7399 pref_addr_cid: _,
7400 path_validated: _,
7401 } => Self::Server { server_config },
7402 }
7403 }
7404}
7405
7406pub(crate) enum SideArgs {
7408 Client {
7409 token_store: Arc<dyn TokenStore>,
7410 server_name: String,
7411 },
7412 Server {
7413 server_config: Arc<ServerConfig>,
7414 pref_addr_cid: Option<ConnectionId>,
7415 path_validated: bool,
7416 },
7417}
7418
7419impl SideArgs {
7420 pub(crate) fn pref_addr_cid(&self) -> Option<ConnectionId> {
7421 match *self {
7422 Self::Client { .. } => None,
7423 Self::Server { pref_addr_cid, .. } => pref_addr_cid,
7424 }
7425 }
7426
7427 pub(crate) fn path_validated(&self) -> bool {
7428 match *self {
7429 Self::Client { .. } => true,
7430 Self::Server { path_validated, .. } => path_validated,
7431 }
7432 }
7433
7434 pub(crate) fn side(&self) -> Side {
7435 match *self {
7436 Self::Client { .. } => Side::Client,
7437 Self::Server { .. } => Side::Server,
7438 }
7439 }
7440}
7441
7442#[derive(Debug, Error, Clone, PartialEq, Eq)]
7444pub enum ConnectionError {
7445 #[error("peer doesn't implement any supported version")]
7447 VersionMismatch,
7448 #[error(transparent)]
7450 TransportError(#[from] TransportError),
7451 #[error("aborted by peer: {0}")]
7453 ConnectionClosed(frame::ConnectionClose),
7454 #[error("closed by peer: {0}")]
7456 ApplicationClosed(frame::ApplicationClose),
7457 #[error("reset by peer")]
7459 Reset,
7460 #[error("timed out")]
7466 TimedOut,
7467 #[error("closed")]
7469 LocallyClosed,
7470 #[error("CIDs exhausted")]
7474 CidsExhausted,
7475}
7476
7477impl From<Close> for ConnectionError {
7478 fn from(x: Close) -> Self {
7479 match x {
7480 Close::Connection(reason) => Self::ConnectionClosed(reason),
7481 Close::Application(reason) => Self::ApplicationClosed(reason),
7482 }
7483 }
7484}
7485
7486impl From<ConnectionError> for io::Error {
7488 fn from(x: ConnectionError) -> Self {
7489 use ConnectionError::*;
7490 let kind = match x {
7491 TimedOut => io::ErrorKind::TimedOut,
7492 Reset => io::ErrorKind::ConnectionReset,
7493 ApplicationClosed(_) | ConnectionClosed(_) => io::ErrorKind::ConnectionAborted,
7494 TransportError(_) | VersionMismatch | LocallyClosed | CidsExhausted => {
7495 io::ErrorKind::Other
7496 }
7497 };
7498 Self::new(kind, x)
7499 }
7500}
7501
7502#[derive(Debug, Error, PartialEq, Eq, Clone, Copy)]
7505pub enum PathError {
7506 #[error("multipath extension not negotiated")]
7508 MultipathNotNegotiated,
7509 #[error("the server side may not open a path")]
7511 ServerSideNotAllowed,
7512 #[error("maximum number of concurrent paths reached")]
7514 MaxPathIdReached,
7515 #[error("remoted CIDs exhausted")]
7517 RemoteCidsExhausted,
7518 #[error("path validation failed")]
7520 ValidationFailed,
7521 #[error("invalid remote address")]
7523 InvalidRemoteAddress(SocketAddr),
7524}
7525
7526#[derive(Debug, Error, Clone, Eq, PartialEq)]
7528pub enum ClosePathError {
7529 #[error("Multipath extension not negotiated")]
7531 MultipathNotNegotiated,
7532 #[error("closed path")]
7534 ClosedPath,
7535 #[error("last open path")]
7539 LastOpenPath,
7540}
7541
7542#[derive(Debug, Error, Clone, Copy)]
7544#[error("Multipath extension not negotiated")]
7545pub struct MultipathNotNegotiated {
7546 _private: (),
7547}
7548
7549#[derive(Debug)]
7551pub enum Event {
7552 HandshakeDataReady,
7554 Connected,
7556 HandshakeConfirmed,
7558 ConnectionLost {
7565 reason: ConnectionError,
7567 },
7568 Stream(StreamEvent),
7570 DatagramReceived,
7572 DatagramsUnblocked,
7574 Path(PathEvent),
7576 NatTraversal(n0_nat_traversal::Event),
7578}
7579
7580impl From<PathEvent> for Event {
7581 fn from(source: PathEvent) -> Self {
7582 Self::Path(source)
7583 }
7584}
7585
7586fn get_max_ack_delay(params: &TransportParameters) -> Duration {
7587 Duration::from_micros(params.max_ack_delay.0 * 1000)
7588}
7589
7590const MAX_BACKOFF_EXPONENT: u32 = 16;
7592
7593const MAX_PTO_INTERVAL: Duration = Duration::from_secs(2);
7597
7598const MIN_IDLE_FOR_FAST_PTO: Duration = Duration::from_secs(25);
7600
7601const MAX_PTO_FAST_INTERVAL: Duration = Duration::from_secs(1);
7606
7607const SLOW_RTT_THRESHOLD: Duration =
7612 Duration::from_millis((MAX_PTO_INTERVAL.as_millis() as u64 * 2) / 3);
7613
7614const MIN_PACKET_SPACE: usize = MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE + 32;
7622
7623const MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE: usize =
7629 1 + 4 + 1 + MAX_CID_SIZE + 1 + MAX_CID_SIZE + VarInt::from_u32(u16::MAX as u32).size() + 4;
7630
7631#[derive(Default)]
7632struct SentFrames {
7633 retransmits: ThinRetransmits,
7634 largest_acked: FxHashMap<PathId, u64>,
7636 stream_frames: StreamMetaVec,
7637 non_retransmits: bool,
7639 requires_padding: bool,
7641}
7642
7643impl SentFrames {
7644 fn is_ack_only(&self, streams: &StreamsState) -> bool {
7646 !self.largest_acked.is_empty()
7647 && !self.non_retransmits
7648 && self.stream_frames.is_empty()
7649 && self.retransmits.is_empty(streams)
7650 }
7651
7652 fn retransmits_mut(&mut self) -> &mut Retransmits {
7653 self.retransmits.get_or_create()
7654 }
7655
7656 fn record_sent_frame(&mut self, frame: frame::EncodableFrame<'_>) {
7657 use frame::EncodableFrame::*;
7658 match frame {
7659 PathAck(path_ack_encoder) => {
7660 if let Some(max) = path_ack_encoder.ranges.max() {
7661 self.largest_acked.insert(path_ack_encoder.path_id, max);
7662 }
7663 }
7664 Ack(ack_encoder) => {
7665 if let Some(max) = ack_encoder.ranges.max() {
7666 self.largest_acked.insert(PathId::ZERO, max);
7667 }
7668 }
7669 Close(_) => { }
7670 PathResponse(_) => self.non_retransmits = true,
7671 HandshakeDone(_) => self.retransmits_mut().handshake_done = true,
7672 ReachOut(frame) => self.retransmits_mut().reach_out.push(frame),
7673 ObservedAddr(_) => self.retransmits_mut().observed_addr = true,
7674 Ping(_) => self.non_retransmits = true,
7675 ImmediateAck(_) => self.non_retransmits = true,
7676 AckFrequency(_) => self.retransmits_mut().ack_frequency = true,
7677 PathChallenge(_) => self.non_retransmits = true,
7678 Crypto(crypto) => self.retransmits_mut().crypto.push_back(crypto),
7679 PathAbandon(path_abandon) => {
7680 self.retransmits_mut()
7681 .path_abandon
7682 .entry(path_abandon.path_id)
7683 .or_insert(path_abandon.error_code);
7684 }
7685 PathStatusAvailable(frame::PathStatusAvailable { path_id, .. })
7686 | PathStatusBackup(frame::PathStatusBackup { path_id, .. }) => {
7687 self.retransmits_mut().path_status.insert(path_id);
7688 }
7689 MaxPathId(_) => self.retransmits_mut().max_path_id = true,
7690 PathsBlocked(_) => self.retransmits_mut().paths_blocked = true,
7691 PathCidsBlocked(path_cids_blocked) => {
7692 self.retransmits_mut()
7693 .path_cids_blocked
7694 .insert(path_cids_blocked.path_id);
7695 }
7696 ResetStream(reset) => self
7697 .retransmits_mut()
7698 .reset_stream
7699 .push((reset.id, reset.error_code)),
7700 StopSending(stop_sending) => self.retransmits_mut().stop_sending.push(stop_sending),
7701 NewConnectionId(new_cid) => self.retransmits_mut().new_cids.push(new_cid.issued()),
7702 RetireConnectionId(retire_cid) => self
7703 .retransmits_mut()
7704 .retire_cids
7705 .push((retire_cid.path_id.unwrap_or_default(), retire_cid.sequence)),
7706 Datagram(_) => self.non_retransmits = true,
7707 NewToken(_) => {}
7708 AddAddress(add_address) => {
7709 self.retransmits_mut().add_address.insert(add_address);
7710 }
7711 RemoveAddress(remove_address) => {
7712 self.retransmits_mut().remove_address.insert(remove_address);
7713 }
7714 StreamMeta(stream_meta_encoder) => self.stream_frames.push(stream_meta_encoder.meta),
7715 MaxData(_) => self.retransmits_mut().max_data = true,
7716 MaxStreamData(max) => {
7717 self.retransmits_mut().max_stream_data.insert(max.id);
7718 }
7719 MaxStreams(max_streams) => {
7720 self.retransmits_mut().max_stream_id[max_streams.dir as usize] = true
7721 }
7722 StreamsBlocked(streams_blocked) => {
7723 self.retransmits_mut().streams_blocked[streams_blocked.dir as usize] = true
7724 }
7725 }
7726 }
7727}
7728
7729fn negotiate_max_idle_timeout(x: Option<VarInt>, y: Option<VarInt>) -> Option<Duration> {
7737 match (x, y) {
7738 (Some(VarInt(0)) | None, Some(VarInt(0)) | None) => None,
7739 (Some(VarInt(0)) | None, Some(y)) => Some(Duration::from_millis(y.0)),
7740 (Some(x), Some(VarInt(0)) | None) => Some(Duration::from_millis(x.0)),
7741 (Some(x), Some(y)) => Some(Duration::from_millis(cmp::min(x, y).0)),
7742 }
7743}
7744
7745#[cfg(test)]
7746mod tests {
7747 use super::*;
7748
7749 #[test]
7750 fn negotiate_max_idle_timeout_commutative() {
7751 let test_params = [
7752 (None, None, None),
7753 (None, Some(VarInt(0)), None),
7754 (None, Some(VarInt(2)), Some(Duration::from_millis(2))),
7755 (Some(VarInt(0)), Some(VarInt(0)), None),
7756 (
7757 Some(VarInt(2)),
7758 Some(VarInt(0)),
7759 Some(Duration::from_millis(2)),
7760 ),
7761 (
7762 Some(VarInt(1)),
7763 Some(VarInt(4)),
7764 Some(Duration::from_millis(1)),
7765 ),
7766 ];
7767
7768 for (left, right, result) in test_params {
7769 assert_eq!(negotiate_max_idle_timeout(left, right), result);
7770 assert_eq!(negotiate_max_idle_timeout(right, left), result);
7771 }
7772 }
7773
7774 #[test]
7775 fn abandoned_paths() {
7776 let mut t = AbandonedPaths::default();
7777
7778 t.insert(PathId(0));
7779 t.insert(PathId(1));
7780 assert_eq!(t.len(), 2);
7781 assert_eq!(t.0.range_count(), 1); assert!(t.contains(&PathId(0)));
7783 assert!(t.contains(&PathId(1)));
7784 assert!(!t.contains(&PathId(2)));
7785 assert!(!t.contains(&PathId(3)));
7786 assert_eq!(t.max(), Some(PathId(1)));
7787
7788 t.insert(PathId(3));
7789 assert_eq!(t.len(), 3);
7790 assert_eq!(t.0.range_count(), 2); assert!(t.contains(&PathId(0)));
7792 assert!(t.contains(&PathId(1)));
7793 assert!(!t.contains(&PathId(2)));
7794 assert!(t.contains(&PathId(3)));
7795 assert_eq!(t.max(), Some(PathId(3)));
7796
7797 t.insert(PathId(2));
7798 assert_eq!(t.len(), 4);
7799 assert_eq!(t.0.range_count(), 1); assert!(t.contains(&PathId(0)));
7801 assert!(t.contains(&PathId(1)));
7802 assert!(t.contains(&PathId(2)));
7803 assert!(t.contains(&PathId(3)));
7804 assert_eq!(t.max(), Some(PathId(3)));
7805 }
7806}