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 paths::PathRetransmits,
29 qlog::{QlogRecvPacket, QlogSink},
30 spaces::LostPacket,
31 stats::PathStatsMap,
32 timer::{ConnTimer, PathTimer},
33 },
34 crypto::{self, Keys},
35 frame::{
36 self, Close, DataBlocked, Datagram, FrameStruct, NewToken, ObservedAddr, StreamDataBlocked,
37 StreamsBlocked,
38 },
39 n0_nat_traversal,
40 packet::{
41 FixedLengthConnectionIdParser, Header, InitialHeader, InitialPacket, LongType, Packet,
42 PacketNumber, PartialDecode, SpaceId,
43 },
44 range_set::ArrayRangeSet,
45 shared::{
46 ConnectionEvent, ConnectionEventInner, ConnectionId, DatagramConnectionEvent, EcnCodepoint,
47 EndpointEvent, EndpointEventInner,
48 },
49 token::{ResetToken, Token, TokenPayload},
50 transport_parameters::TransportParameters,
51};
52
53mod ack_frequency;
54use ack_frequency::AckFrequencyState;
55
56mod assembler;
57pub use assembler::Chunk;
58
59mod cid_state;
60use cid_state::CidState;
61
62mod datagrams;
63use datagrams::DatagramState;
64pub use datagrams::{Datagrams, SendDatagramError};
65
66mod mtud;
67mod pacing;
68
69mod packet_builder;
70use packet_builder::{PacketBuilder, PadDatagram};
71
72mod packet_crypto;
73use packet_crypto::CryptoState;
74pub(crate) use packet_crypto::EncryptionLevel;
75
76mod paths;
77pub use paths::{
78 ClosedPath, PathAbandonReason, PathEvent, PathId, PathStatus, RttEstimator, SetPathStatusError,
79};
80use paths::{PathData, PathState};
81
82pub(crate) mod qlog;
83pub(crate) mod send_buffer;
84
85pub(crate) mod spaces;
86#[cfg(fuzzing)]
87pub use spaces::Retransmits;
88#[cfg(not(fuzzing))]
89use spaces::Retransmits;
90pub(crate) use spaces::SpaceKind;
91use spaces::{OpenStatus, PacketSpace, SendableFrames, SentPacket, ThinRetransmits};
92
93mod stats;
94pub use stats::{ConnectionStats, FrameStats, PathStats, UdpStats};
95
96mod streams;
97#[cfg(fuzzing)]
98pub use streams::StreamsState;
99#[cfg(not(fuzzing))]
100use streams::StreamsState;
101pub use streams::{
102 Chunks, ClosedStream, FinishError, ReadError, ReadableError, RecvStream, SendStream,
103 ShouldTransmit, StreamEvent, Streams, WriteError,
104};
105
106mod timer;
107use timer::{Timer, TimerTable};
108
109mod transmit_buf;
110use transmit_buf::TransmitBuf;
111
112mod state;
113
114#[cfg(not(fuzzing))]
115use state::State;
116#[cfg(fuzzing)]
117pub use state::State;
118use state::StateType;
119
120pub struct Connection {
160 endpoint_config: Arc<EndpointConfig>,
161 config: Arc<TransportConfig>,
162 rng: StdRng,
163 crypto_state: CryptoState,
165 handshake_cid: ConnectionId,
167 remote_handshake_cid: ConnectionId,
169 paths: BTreeMap<PathId, PathState>,
175 path_generation_counter: u64,
186 allow_mtud: bool,
188 state: State,
189 side: ConnectionSide,
190 peer_params: TransportParameters,
192 original_remote_cid: ConnectionId,
194 initial_dst_cid: ConnectionId,
196 retry_src_cid: Option<ConnectionId>,
199 events: VecDeque<Event>,
201 endpoint_events: VecDeque<EndpointEventInner>,
202 spin_enabled: bool,
204 spin: bool,
206 spaces: [PacketSpace; 3],
208 highest_space: SpaceKind,
210 idle_timeout: Option<Duration>,
212 timers: TimerTable,
213 authentication_failures: u64,
215
216 connection_close_pending: bool,
221
222 ack_frequency: AckFrequencyState,
226
227 receiving_ecn: bool,
232 total_authed_packets: u64,
234
235 next_observed_addr_seq_no: VarInt,
240
241 streams: StreamsState,
242 remote_cids: FxHashMap<PathId, CidQueue>,
248 local_cid_state: FxHashMap<PathId, CidState>,
255 datagrams: DatagramState,
257 path_stats: PathStatsMap,
259 partial_stats: ConnectionStats,
265 version: u32,
267
268 max_concurrent_paths: NonZeroU32,
277 local_max_path_id: PathId,
292 remote_max_path_id: PathId,
298 max_path_id_with_cids: PathId,
304 abandoned_paths: AbandonedPaths,
310
311 n0_nat_traversal: n0_nat_traversal::State,
313 qlog: QlogSink,
314}
315
316impl Connection {
317 pub(crate) fn new(
318 endpoint_config: Arc<EndpointConfig>,
319 config: Arc<TransportConfig>,
320 init_cid: ConnectionId,
321 local_cid: ConnectionId,
322 remote_cid: ConnectionId,
323 network_path: FourTuple,
324 crypto: Box<dyn crypto::Session>,
325 cid_gen: &dyn ConnectionIdGenerator,
326 now: Instant,
327 version: u32,
328 allow_mtud: bool,
329 rng_seed: [u8; 32],
330 side_args: SideArgs,
331 qlog: QlogSink,
332 ) -> Self {
333 let pref_addr_cid = side_args.pref_addr_cid();
334 let path_validated = side_args.path_validated();
335 let connection_side = ConnectionSide::from(side_args);
336 let side = connection_side.side();
337 let mut rng = StdRng::from_seed(rng_seed);
338 let mut initial_space = PacketSpace::new(now, SpaceId::Initial, &mut rng);
339 let mut handshake_space = PacketSpace::new(now, SpaceId::Handshake, &mut rng);
340 #[cfg(test)]
341 let mut data_space = match config.deterministic_packet_numbers {
342 true => PacketSpace::new_deterministic(now, SpaceId::Data),
343 false => PacketSpace::new(now, SpaceId::Data, &mut rng),
344 };
345 #[cfg(not(test))]
346 let mut data_space = PacketSpace::new(now, SpaceId::Data, &mut rng);
347
348 initial_space.for_path(PathId::ZERO).open_status = OpenStatus::Informed;
350 handshake_space.for_path(PathId::ZERO).open_status = OpenStatus::Informed;
351 data_space.for_path(PathId::ZERO).open_status = OpenStatus::Informed;
352
353 let state = State::handshake(state::Handshake {
354 remote_cid_set: side.is_server(),
355 expected_token: Bytes::new(),
356 client_hello: None,
357 allow_server_migration: side.is_client() && config.server_handshake_migration,
358 });
359 let local_cid_state = FxHashMap::from_iter([(
360 PathId::ZERO,
361 CidState::new(
362 cid_gen.cid_len(),
363 cid_gen.cid_lifetime(),
364 now,
365 if pref_addr_cid.is_some() { 2 } else { 1 },
366 ),
367 )]);
368
369 let mut this = Self {
370 endpoint_config,
371 crypto_state: CryptoState::new(crypto, init_cid, side, &mut rng),
372 handshake_cid: local_cid,
373 remote_handshake_cid: remote_cid,
374 local_cid_state,
375 paths: BTreeMap::from_iter([(
376 PathId::ZERO,
377 PathState {
378 data: PathData::new(network_path, allow_mtud, None, 0, now, &config),
379 prev: None,
380 },
381 )]),
382 path_generation_counter: 0,
383 allow_mtud,
384 state,
385 side: connection_side,
386 peer_params: TransportParameters::default(),
387 original_remote_cid: remote_cid,
388 initial_dst_cid: init_cid,
389 retry_src_cid: None,
390 events: VecDeque::new(),
391 endpoint_events: VecDeque::new(),
392 spin_enabled: config.allow_spin && rng.random_ratio(7, 8),
393 spin: false,
394 spaces: [initial_space, handshake_space, data_space],
395 highest_space: SpaceKind::Initial,
396 idle_timeout: match config.max_idle_timeout {
397 None | Some(VarInt(0)) => None,
398 Some(dur) => Some(Duration::from_millis(dur.0)),
399 },
400 timers: TimerTable::default(),
401 authentication_failures: 0,
402 connection_close_pending: false,
403
404 ack_frequency: AckFrequencyState::new(get_max_ack_delay(
405 &TransportParameters::default(),
406 )),
407
408 receiving_ecn: false,
409 total_authed_packets: 0,
410
411 next_observed_addr_seq_no: 0u32.into(),
412
413 streams: StreamsState::new(
414 side,
415 config.max_concurrent_uni_streams,
416 config.max_concurrent_bidi_streams,
417 config.send_window,
418 config.receive_window,
419 config.stream_receive_window,
420 ),
421 datagrams: DatagramState::default(),
422 config,
423 remote_cids: FxHashMap::from_iter([(PathId::ZERO, CidQueue::new(remote_cid))]),
424 rng,
425 path_stats: Default::default(),
426 partial_stats: ConnectionStats::default(),
427 version,
428
429 max_concurrent_paths: NonZeroU32::MIN,
431 local_max_path_id: PathId::ZERO,
432 remote_max_path_id: PathId::ZERO,
433 max_path_id_with_cids: PathId::ZERO,
434 abandoned_paths: Default::default(),
435
436 n0_nat_traversal: Default::default(),
437 qlog,
438 };
439 if path_validated {
440 this.on_path_validated(PathId::ZERO);
441 }
442 if side.is_client() {
443 this.write_crypto();
445 this.init_0rtt(now);
446 }
447 this.qlog
448 .emit_tuple_assigned(PathId::ZERO, network_path, now);
449 this
450 }
451
452 #[must_use]
460 pub fn poll_timeout(&self) -> Option<Instant> {
461 self.timers.peek()
462 }
463
464 #[must_use]
470 pub fn poll(&mut self) -> Option<Event> {
471 if let Some(x) = self.events.pop_front() {
472 return Some(x);
473 }
474
475 if let Some(event) = self.streams.poll() {
476 return Some(Event::Stream(event));
477 }
478
479 if let Some(reason) = self.state.take_error() {
480 return Some(Event::ConnectionLost { reason });
481 }
482
483 None
484 }
485
486 #[must_use]
488 pub fn poll_endpoint_events(&mut self) -> Option<EndpointEvent> {
489 self.endpoint_events.pop_front().map(EndpointEvent)
490 }
491
492 #[must_use]
494 pub fn streams(&mut self) -> Streams<'_> {
495 Streams {
496 state: &mut self.streams,
497 conn_state: &self.state,
498 }
499 }
500
501 #[must_use]
503 pub fn recv_stream(&mut self, id: StreamId) -> RecvStream<'_> {
504 assert!(id.dir() == Dir::Bi || id.initiator() != self.side.side());
505 RecvStream {
506 id,
507 state: &mut self.streams,
508 pending: &mut self.spaces[SpaceId::Data].pending,
509 }
510 }
511
512 #[must_use]
514 pub fn send_stream(&mut self, id: StreamId) -> SendStream<'_> {
515 assert!(id.dir() == Dir::Bi || id.initiator() == self.side.side());
516 SendStream {
517 id,
518 state: &mut self.streams,
519 pending: &mut self.spaces[SpaceId::Data].pending,
520 conn_state: &self.state,
521 }
522 }
523
524 pub fn open_path_ensure(
541 &mut self,
542 network_path: FourTuple,
543 initial_status: PathStatus,
544 now: Instant,
545 ) -> Result<(PathId, bool), PathError> {
546 let existing_open_path = self.paths.iter().find(|(id, path)| {
547 network_path.is_probably_same_path(&path.data.network_path)
548 && !self.abandoned_paths.contains(id)
549 });
550 match existing_open_path {
551 Some((path_id, _state)) => Ok((*path_id, true)),
552 None => Ok((self.open_path(network_path, initial_status, now)?, false)),
553 }
554 }
555
556 pub fn open_path(
562 &mut self,
563 network_path: FourTuple,
564 initial_status: PathStatus,
565 now: Instant,
566 ) -> Result<PathId, PathError> {
567 let Some(max_path_id) = self.max_path_id() else {
568 return Err(PathError::MultipathNotNegotiated);
569 };
570 if self.side().is_server() {
571 return Err(PathError::ServerSideNotAllowed);
572 }
573
574 let max_abandoned = self.abandoned_paths.max();
575 let max_used = self.paths.keys().last().copied();
576 let path_id = max_abandoned
577 .max(max_used)
578 .unwrap_or(PathId::ZERO)
579 .saturating_add(1u8);
580
581 if path_id > max_path_id {
582 self.spaces[SpaceId::Data].pending.paths_blocked = Some(self.remote_max_path_id);
583 return Err(PathError::MaxPathIdReached);
584 }
585 if !self.remote_cids.contains_key(&path_id) {
586 self.spaces[SpaceId::Data]
587 .pending
588 .path_cids_blocked
589 .insert(path_id, VarInt(0));
590 return Err(PathError::RemoteCidsExhausted);
591 }
592
593 let path = self.create_path(path_id, network_path, now, None);
594 path.status.local_update(initial_status);
595
596 Ok(path_id)
597 }
598
599 pub fn close_path(
605 &mut self,
606 now: Instant,
607 path_id: PathId,
608 error_code: VarInt,
609 ) -> Result<(), ClosePathError> {
610 self.close_path_inner(
611 now,
612 path_id,
613 PathAbandonReason::ApplicationClosed { error_code },
614 )
615 }
616
617 pub(crate) fn close_path_inner(
622 &mut self,
623 now: Instant,
624 path_id: PathId,
625 reason: PathAbandonReason,
626 ) -> Result<(), ClosePathError> {
627 if self.state.is_drained() {
628 return Ok(());
629 }
630
631 if !self.is_multipath_negotiated() {
632 return Err(ClosePathError::MultipathNotNegotiated);
633 }
634 if self.abandoned_paths.contains(&path_id)
635 || Some(path_id) > self.max_path_id()
636 || !self.paths.contains_key(&path_id)
637 {
638 return Err(ClosePathError::ClosedPath);
639 }
640
641 let is_last_path = !self
642 .paths
643 .keys()
644 .any(|id| *id != path_id && !self.abandoned_paths.contains(id));
645
646 if is_last_path && !reason.is_remote() {
647 return Err(ClosePathError::LastOpenPath);
648 }
649
650 self.abandon_path(now, path_id, reason);
651
652 if is_last_path {
656 let rtt = RttEstimator::new(self.config.initial_rtt);
660 let pto = rtt.pto_base() + self.ack_frequency.max_ack_delay_for_pto();
661 let grace = pto * 3;
662 self.timers.set(
663 Timer::Conn(ConnTimer::NoAvailablePath),
664 now + grace,
665 self.qlog.with_time(now),
666 );
667 }
668
669 Ok(())
670 }
671
672 fn abandon_path(&mut self, now: Instant, path_id: PathId, reason: PathAbandonReason) {
677 trace!(%path_id, ?reason, "abandoning path");
678
679 let pending_space = &mut self.spaces[SpaceId::Data].pending;
680 pending_space
682 .path_abandon
683 .insert(path_id, reason.error_code());
684
685 pending_space.new_cids.retain(|cid| cid.path_id != path_id);
687 pending_space.path_status.retain(|&id| id != path_id);
688
689 for space in self.spaces[SpaceId::Data].iter_paths_mut() {
691 for sent_packet in space.sent_packets.values_mut() {
692 if let Some(retransmits) = sent_packet.retransmits.get_mut() {
693 retransmits.new_cids.retain(|cid| cid.path_id != path_id);
694 retransmits.path_status.retain(|&id| id != path_id);
695 }
696 }
697 }
698
699 self.spaces[SpaceId::Data].for_path(path_id).loss_probes = 0;
704
705 debug_assert!(!self.state.is_drained()); self.endpoint_events
710 .push_back(EndpointEventInner::RetireResetToken(path_id));
711
712 self.abandoned_paths.insert(path_id);
713
714 for timer in PathTimer::VALUES {
715 let keep_timer = match timer {
717 PathTimer::PathValidationFailed | PathTimer::PathChallengeLost => false,
721 PathTimer::PathKeepAlive | PathTimer::PathIdle => false,
724 PathTimer::MaxAckDelay => false,
727 PathTimer::PathDrained => false,
730 PathTimer::LossDetection => true,
733 PathTimer::Pacing => true,
737 };
738
739 if !keep_timer {
740 let qlog = self.qlog.with_time(now);
741 self.timers.stop(Timer::PerPath(path_id, timer), qlog);
742 }
743 }
744
745 self.set_loss_detection_timer(now, path_id);
750
751 self.events.push_back(Event::Path(PathEvent::Abandoned {
753 id: path_id,
754 reason,
755 }));
756 }
757
758 #[track_caller]
762 fn path_data(&self, path_id: PathId) -> &PathData {
763 if let Some(data) = self.paths.get(&path_id) {
764 &data.data
765 } else {
766 panic!(
767 "unknown path: {path_id}, currently known paths: {:?}",
768 self.paths.keys().collect::<Vec<_>>()
769 );
770 }
771 }
772
773 #[track_caller]
777 fn path_data_mut(&mut self, path_id: PathId) -> &mut PathData {
778 &mut self.paths.get_mut(&path_id).expect("known path").data
779 }
780
781 fn path(&self, path_id: PathId) -> Option<&PathData> {
783 self.paths.get(&path_id).map(|path_state| &path_state.data)
784 }
785
786 fn path_mut(&mut self, path_id: PathId) -> Option<&mut PathData> {
788 self.paths
789 .get_mut(&path_id)
790 .map(|path_state| &mut path_state.data)
791 }
792
793 pub fn paths(&self) -> Vec<PathId> {
797 self.paths.keys().copied().collect()
798 }
799
800 pub fn path_status(&self, path_id: PathId) -> Result<PathStatus, ClosedPath> {
802 self.path(path_id)
803 .map(PathData::local_status)
804 .ok_or(ClosedPath { _private: () })
805 }
806
807 pub fn network_path(&self, path_id: PathId) -> Result<FourTuple, ClosedPath> {
809 self.path(path_id)
810 .map(|path| path.network_path)
811 .ok_or(ClosedPath { _private: () })
812 }
813
814 pub fn set_path_status(
818 &mut self,
819 path_id: PathId,
820 status: PathStatus,
821 ) -> Result<PathStatus, SetPathStatusError> {
822 if !self.is_multipath_negotiated() {
823 return Err(SetPathStatusError::MultipathNotNegotiated);
824 }
825 let path = self
826 .path_mut(path_id)
827 .ok_or(SetPathStatusError::ClosedPath)?;
828 let prev = match path.status.local_update(status) {
829 Some(prev) => {
830 self.spaces[SpaceId::Data]
831 .pending
832 .path_status
833 .insert(path_id);
834 prev
835 }
836 None => path.local_status(),
837 };
838 Ok(prev)
839 }
840
841 pub fn remote_path_status(&self, path_id: PathId) -> Option<PathStatus> {
846 self.path(path_id).and_then(|path| path.remote_status())
847 }
848
849 pub fn set_path_max_idle_timeout(
858 &mut self,
859 now: Instant,
860 path_id: PathId,
861 timeout: Option<Duration>,
862 ) -> Result<Option<Duration>, ClosedPath> {
863 let path = self
864 .paths
865 .get_mut(&path_id)
866 .ok_or(ClosedPath { _private: () })?;
867 let prev = mem::replace(&mut path.data.idle_timeout, timeout);
868
869 if !self.state.is_closed() {
871 if let Some(new_timeout) = timeout {
872 let timer = Timer::PerPath(path_id, PathTimer::PathIdle);
873 let deadline = match (prev, self.timers.get(timer)) {
874 (Some(old_timeout), Some(old_deadline)) => {
875 let last_activity = old_deadline.checked_sub(old_timeout).unwrap_or(now);
876 last_activity + new_timeout
877 }
878 _ => now + new_timeout,
879 };
880 self.timers.set(timer, deadline, self.qlog.with_time(now));
881 } else {
882 self.timers.stop(
883 Timer::PerPath(path_id, PathTimer::PathIdle),
884 self.qlog.with_time(now),
885 );
886 }
887 }
888
889 Ok(prev)
890 }
891
892 pub fn set_path_keep_alive_interval(
898 &mut self,
899 path_id: PathId,
900 interval: Option<Duration>,
901 ) -> Result<Option<Duration>, ClosedPath> {
902 let path = self
903 .paths
904 .get_mut(&path_id)
905 .ok_or(ClosedPath { _private: () })?;
906 Ok(mem::replace(&mut path.data.keep_alive, interval))
907 }
908
909 fn find_validated_path_on_network_path(
913 &self,
914 network_path: FourTuple,
915 ) -> Option<(&PathId, &PathState)> {
916 self.paths.iter().find(|(path_id, path_state)| {
917 path_state.data.validated
918 && network_path.is_probably_same_path(&path_state.data.network_path)
920 && !self.abandoned_paths.contains(path_id)
921 })
922 }
926
927 fn create_path(
931 &mut self,
932 path_id: PathId,
933 network_path: FourTuple,
934 now: Instant,
935 pn: Option<u64>,
936 ) -> &mut PathData {
937 let valid_path = self.find_validated_path_on_network_path(network_path);
938 let validated = valid_path.is_some();
939 let initial_rtt = valid_path.map(|(_, path)| path.data.rtt.conservative());
940 let vacant_entry = match self.paths.entry(path_id) {
941 btree_map::Entry::Vacant(vacant_entry) => vacant_entry,
942 btree_map::Entry::Occupied(occupied_entry) => {
943 return &mut occupied_entry.into_mut().data;
944 }
945 };
946
947 debug!(%validated, %path_id, %network_path, "path added");
948
949 self.timers.stop(
951 Timer::Conn(ConnTimer::NoAvailablePath),
952 self.qlog.with_time(now),
953 );
954 let peer_max_udp_payload_size =
955 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()).unwrap_or(u16::MAX);
956 self.path_generation_counter = self.path_generation_counter.wrapping_add(1);
957 let mut data = PathData::new(
958 network_path,
959 self.allow_mtud,
960 Some(peer_max_udp_payload_size),
961 self.path_generation_counter,
962 now,
963 &self.config,
964 );
965
966 data.validated = validated;
967 if let Some(initial_rtt) = initial_rtt {
968 data.rtt.reset_initial_rtt(initial_rtt);
969 }
970
971 data.pending_challenge = true;
974 data.pending.observed_address = self
975 .config
976 .address_discovery_role
977 .should_report(&self.peer_params.address_discovery_role);
978
979 let path = vacant_entry.insert(PathState { data, prev: None });
980
981 let mut pn_space = spaces::PacketNumberSpace::new(now, SpaceId::Data, &mut self.rng);
982 if let Some(pn) = pn {
983 pn_space.dedup.insert(pn);
984 }
985 self.spaces[SpaceId::Data]
986 .number_spaces
987 .insert(path_id, pn_space);
988 self.qlog.emit_tuple_assigned(path_id, network_path, now);
989
990 if !self.remote_cids.contains_key(&path_id) {
994 debug!(%path_id, "Remote opened path without issuing CIDs");
995 self.spaces[SpaceId::Data]
996 .pending
997 .path_cids_blocked
998 .insert(path_id, VarInt(0));
999 }
1002
1003 &mut path.data
1004 }
1005
1006 #[must_use]
1016 pub fn poll_transmit(
1017 &mut self,
1018 now: Instant,
1019 max_datagrams: NonZeroUsize,
1020 buf: &mut Vec<u8>,
1021 ) -> Option<Transmit> {
1022 let max_datagrams = match self.config.enable_segmentation_offload {
1023 false => NonZeroUsize::MIN,
1024 true => max_datagrams,
1025 };
1026
1027 let connection_close_pending = match self.state.as_type() {
1033 StateType::Drained => {
1034 for path in self.paths.values_mut() {
1035 path.data.app_limited = true;
1036 }
1037 return None;
1038 }
1039 StateType::Draining | StateType::Closed => {
1040 if !self.connection_close_pending {
1043 for path in self.paths.values_mut() {
1044 path.data.app_limited = true;
1045 }
1046 return None;
1047 }
1048 true
1049 }
1050 _ => false,
1051 };
1052
1053 if let Some(config) = &self.config.ack_frequency_config {
1055 let rtt = self
1056 .paths
1057 .values()
1058 .map(|p| p.data.rtt.get())
1059 .min()
1060 .expect("one path exists");
1061 self.spaces[SpaceId::Data].pending.ack_frequency = self
1062 .ack_frequency
1063 .should_send_ack_frequency(rtt, config, &self.peer_params)
1064 && self.highest_space == SpaceKind::Data
1065 && self.peer_supports_ack_frequency();
1066 }
1067
1068 let mut next_path_id = self.paths.first_entry().map(|e| *e.key());
1069 while let Some(path_id) = next_path_id {
1070 if !connection_close_pending
1071 && let Some(transmit) = self.poll_transmit_off_path(now, buf, path_id)
1072 {
1073 #[cfg(test)]
1074 {
1075 self.partial_stats.transmits_tx += 1;
1076 }
1077 return Some(transmit);
1078 }
1079
1080 let info = self.scheduling_info(path_id);
1081 if let Some(transmit) = self.poll_transmit_on_path(
1082 now,
1083 buf,
1084 path_id,
1085 max_datagrams,
1086 &info,
1087 connection_close_pending,
1088 ) {
1089 #[cfg(test)]
1090 {
1091 self.partial_stats.transmits_tx += 1;
1092 }
1093 return Some(transmit);
1094 }
1095
1096 debug_assert!(
1099 buf.is_empty(),
1100 "nothing to send on path but buffer not empty"
1101 );
1102
1103 next_path_id = self.paths.keys().find(|i| **i > path_id).copied();
1104 }
1105
1106 debug_assert!(
1108 buf.is_empty(),
1109 "there was data in the buffer, but it was not sent"
1110 );
1111
1112 if self.state.is_established() {
1113 let mut next_path_id = self.paths.first_entry().map(|e| *e.key());
1115 while let Some(path_id) = next_path_id {
1116 if let Some(transmit) = self.poll_transmit_mtu_probe(now, buf, path_id) {
1117 #[cfg(test)]
1118 {
1119 self.partial_stats.transmits_tx += 1;
1120 }
1121 return Some(transmit);
1122 }
1123 next_path_id = self.paths.keys().find(|i| **i > path_id).copied();
1124 }
1125 }
1126
1127 None
1128 }
1129
1130 fn scheduling_info(&self, path_id: PathId) -> PathSchedulingInfo {
1148 let have_validated_status_available_space = self.paths.iter().any(|(path_id, path)| {
1150 self.remote_cids.contains_key(path_id)
1151 && !self.abandoned_paths.contains(path_id)
1152 && path.data.validated
1153 && path.data.local_status() == PathStatus::Available
1154 });
1155
1156 let have_validated_space = self.paths.iter().any(|(path_id, path)| {
1158 self.remote_cids.contains_key(path_id)
1159 && !self.abandoned_paths.contains(path_id)
1160 && path.data.validated
1161 });
1162
1163 let is_handshaking = self.is_handshaking();
1164 let has_cids = self.remote_cids.contains_key(&path_id);
1165 let is_abandoned = self.abandoned_paths.contains(&path_id);
1166 let path_data = self.path_data(path_id);
1167 let validated = path_data.validated;
1168 let status = path_data.local_status();
1169
1170 let may_send_data = has_cids
1173 && !is_abandoned
1174 && if is_handshaking {
1175 true
1179 } else if !validated {
1180 false
1187 } else {
1188 match status {
1189 PathStatus::Available => {
1190 true
1192 }
1193 PathStatus::Backup => {
1194 !have_validated_status_available_space
1196 }
1197 }
1198 };
1199
1200 let may_send_close = has_cids
1205 && !is_abandoned
1206 && if !validated && have_validated_status_available_space {
1207 false
1209 } else {
1210 true
1212 };
1213
1214 let may_self_abandon = has_cids && validated && !have_validated_space;
1218
1219 PathSchedulingInfo {
1220 is_abandoned,
1221 may_send_data,
1222 may_send_close,
1223 may_self_abandon,
1224 }
1225 }
1226
1227 fn build_transmit(&mut self, path_id: PathId, transmit: TransmitBuf<'_>) -> Transmit {
1228 debug_assert!(
1229 !transmit.is_empty(),
1230 "must not be called with an empty transmit buffer"
1231 );
1232
1233 let network_path = self.path_data(path_id).network_path;
1234 trace!(
1235 segment_size = transmit.segment_size(),
1236 last_datagram_len = transmit.len() % transmit.segment_size(),
1237 %network_path,
1238 "sending {} bytes in {} datagrams",
1239 transmit.len(),
1240 transmit.num_datagrams()
1241 );
1242 self.path_data_mut(path_id)
1243 .inc_total_sent(transmit.len() as u64);
1244
1245 self.path_stats
1246 .get_mut(path_id)
1247 .udp_tx
1248 .on_sent(transmit.num_datagrams() as u64, transmit.len());
1249
1250 Transmit {
1251 destination: network_path.remote,
1252 size: transmit.len(),
1253 ecn: if self.path_data(path_id).sending_ecn {
1254 Some(EcnCodepoint::Ect0)
1255 } else {
1256 None
1257 },
1258 segment_size: match transmit.num_datagrams() {
1259 1 => None,
1260 _ => Some(transmit.segment_size()),
1261 },
1262 src_ip: network_path.local_ip,
1263 }
1264 }
1265
1266 fn poll_transmit_off_path(
1268 &mut self,
1269 now: Instant,
1270 buf: &mut Vec<u8>,
1271 path_id: PathId,
1272 ) -> Option<Transmit> {
1273 if let Some(challenge) = self.send_prev_path_challenge(now, buf, path_id) {
1274 return Some(challenge);
1275 }
1276 if let Some(response) = self.send_off_path_path_response(now, buf, path_id) {
1277 return Some(response);
1278 }
1279 if let Some(challenge) = self.send_nat_traversal_path_challenge(now, buf, path_id) {
1280 return Some(challenge);
1281 }
1282 None
1283 }
1284
1285 #[must_use]
1292 fn poll_transmit_on_path(
1293 &mut self,
1294 now: Instant,
1295 buf: &mut Vec<u8>,
1296 path_id: PathId,
1297 max_datagrams: NonZeroUsize,
1298 scheduling_info: &PathSchedulingInfo,
1299 connection_close_pending: bool,
1300 ) -> Option<Transmit> {
1301 let Some(remote_cid) = self.remote_cids.get(&path_id).map(CidQueue::active) else {
1303 if !self.abandoned_paths.contains(&path_id) {
1304 debug!(%path_id, "no remote CIDs for path");
1305 }
1306 return None;
1307 };
1308
1309 let mut pad_datagram = PadDatagram::No;
1315
1316 let mut last_packet_number = None;
1320
1321 let mut congestion_blocked = false;
1324
1325 let pmtu = self.path_data(path_id).current_mtu().into();
1327 let mut transmit = TransmitBuf::new(buf, max_datagrams, pmtu);
1328
1329 for space_id in SpaceId::iter() {
1331 if path_id != PathId::ZERO && space_id != SpaceId::Data {
1333 continue;
1334 }
1335 match self.poll_transmit_path_space(
1336 now,
1337 &mut transmit,
1338 path_id,
1339 space_id,
1340 remote_cid,
1341 scheduling_info,
1342 connection_close_pending,
1343 pad_datagram,
1344 ) {
1345 PollPathSpaceStatus::NothingToSend {
1346 congestion_blocked: cb,
1347 } => {
1348 congestion_blocked |= cb;
1349 }
1352 PollPathSpaceStatus::WrotePacket {
1353 last_packet_number: pn,
1354 pad_datagram: pad,
1355 } => {
1356 debug_assert!(!transmit.is_empty(), "transmit must contain packets");
1357 last_packet_number = Some(pn);
1358 pad_datagram = pad;
1359 continue;
1364 }
1365 PollPathSpaceStatus::Send {
1366 last_packet_number: pn,
1367 } => {
1368 debug_assert!(!transmit.is_empty(), "transmit must contain packets");
1369 last_packet_number = Some(pn);
1370 break;
1371 }
1372 }
1373 }
1374
1375 if last_packet_number.is_some() || congestion_blocked {
1376 self.qlog.emit_recovery_metrics(
1377 path_id,
1378 &mut self
1379 .paths
1380 .get_mut(&path_id)
1381 .expect("path_id was iterated from self.paths above")
1382 .data,
1383 now,
1384 );
1385 }
1386
1387 self.path_data_mut(path_id).app_limited =
1388 last_packet_number.is_none() && !congestion_blocked;
1389
1390 match last_packet_number {
1391 Some(last_packet_number) => {
1392 self.path_data_mut(path_id).congestion.on_sent(
1395 now,
1396 transmit.len() as u64,
1397 last_packet_number,
1398 );
1399 Some(self.build_transmit(path_id, transmit))
1400 }
1401 None => None,
1402 }
1403 }
1404
1405 #[must_use]
1407 fn poll_transmit_path_space(
1408 &mut self,
1409 now: Instant,
1410 transmit: &mut TransmitBuf<'_>,
1411 path_id: PathId,
1412 space_id: SpaceId,
1413 remote_cid: ConnectionId,
1414 scheduling_info: &PathSchedulingInfo,
1415 connection_close_pending: bool,
1417 mut pad_datagram: PadDatagram,
1419 ) -> PollPathSpaceStatus {
1420 let mut last_packet_number = None;
1423
1424 loop {
1440 let max_packet_size = if transmit.datagram_remaining_mut() > 0 {
1442 transmit.datagram_remaining_mut()
1444 } else {
1445 transmit.segment_size()
1447 };
1448 let can_send =
1449 self.space_can_send(space_id, path_id, max_packet_size, connection_close_pending);
1450 let needs_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0;
1451 let space_will_send = {
1452 if scheduling_info.is_abandoned {
1453 scheduling_info.may_self_abandon
1458 && self.spaces[space_id]
1459 .pending
1460 .path_abandon
1461 .contains_key(&path_id)
1462 } else if can_send.close && scheduling_info.may_send_close {
1463 true
1465 } else if needs_loss_probe || can_send.space_specific {
1466 true
1469 } else {
1470 !can_send.is_empty() && scheduling_info.may_send_data
1473 }
1474 };
1475
1476 if !space_will_send {
1477 return match last_packet_number {
1480 Some(pn) => PollPathSpaceStatus::WrotePacket {
1481 last_packet_number: pn,
1482 pad_datagram,
1483 },
1484 None => {
1485 if self.crypto_state.has_keys(space_id.encryption_level())
1487 || (space_id == SpaceId::Data
1488 && self.crypto_state.has_keys(EncryptionLevel::ZeroRtt))
1489 {
1490 trace!(?space_id, %path_id, "nothing to send in space");
1491 }
1492 PollPathSpaceStatus::NothingToSend {
1493 congestion_blocked: false,
1494 }
1495 }
1496 };
1497 }
1498
1499 if transmit.datagram_remaining_mut() == 0 {
1503 let congestion_blocked =
1504 self.path_congestion_check(space_id, path_id, transmit, &can_send, now);
1505 if congestion_blocked != PathBlocked::No {
1506 return match last_packet_number {
1508 Some(pn) => PollPathSpaceStatus::WrotePacket {
1509 last_packet_number: pn,
1510 pad_datagram,
1511 },
1512 None => {
1513 return PollPathSpaceStatus::NothingToSend {
1514 congestion_blocked: true,
1515 };
1516 }
1517 };
1518 }
1519
1520 if transmit.num_datagrams() >= transmit.max_datagrams().get() {
1523 return match last_packet_number {
1526 Some(pn) => PollPathSpaceStatus::WrotePacket {
1527 last_packet_number: pn,
1528 pad_datagram,
1529 },
1530 None => {
1531 return PollPathSpaceStatus::NothingToSend {
1532 congestion_blocked: false,
1533 };
1534 }
1535 };
1536 }
1537
1538 if needs_loss_probe {
1539 let request_immediate_ack =
1541 space_id == SpaceId::Data && self.peer_supports_ack_frequency();
1542 self.spaces[space_id].queue_tail_loss_probe(
1543 path_id,
1544 request_immediate_ack,
1545 &self.streams,
1546 );
1547
1548 self.spaces[space_id].for_path(path_id).loss_probes -= 1; transmit.start_new_datagram_with_size(cmp::min(
1554 usize::from(INITIAL_MTU),
1555 transmit.segment_size(),
1556 ));
1557 } else {
1558 transmit.start_new_datagram();
1559 }
1560 trace!(count = transmit.num_datagrams(), "new datagram started");
1561
1562 pad_datagram = PadDatagram::No;
1564 }
1565
1566 if transmit.datagram_start_offset() < transmit.len() {
1569 debug_assert!(transmit.datagram_remaining_mut() >= MIN_PACKET_SPACE);
1570 }
1571
1572 if self.crypto_state.has_keys(EncryptionLevel::Initial)
1577 && space_id == SpaceId::Handshake
1578 && self.side.is_client()
1579 {
1580 self.discard_space(now, SpaceKind::Initial);
1583 }
1584 if let Some(ref mut prev) = self.crypto_state.prev_crypto {
1585 prev.update_unacked = false;
1586 }
1587
1588 let Some(mut builder) =
1589 PacketBuilder::new(now, space_id, path_id, remote_cid, transmit, self)
1590 else {
1591 return PollPathSpaceStatus::NothingToSend {
1598 congestion_blocked: false,
1599 };
1600 };
1601 last_packet_number = Some(builder.packet_number);
1602
1603 if space_id == SpaceId::Initial
1604 && (self.side.is_client() || can_send.is_ack_eliciting() || needs_loss_probe)
1605 {
1606 pad_datagram |= PadDatagram::ToMinMtu;
1608 }
1609 if space_id == SpaceId::Data && self.config.pad_to_mtu {
1610 pad_datagram |= PadDatagram::ToSegmentSize;
1611 }
1612
1613 if scheduling_info.may_send_close && can_send.close {
1614 trace!("sending CONNECTION_CLOSE");
1615 let is_multipath_negotiated = self.is_multipath_negotiated();
1620 for path_id in self.spaces[space_id]
1621 .number_spaces
1622 .iter()
1623 .filter(|(_, pns)| !pns.pending_acks.ranges().is_empty())
1624 .map(|(&path_id, _)| path_id)
1625 .collect::<Vec<_>>()
1626 {
1627 Self::populate_acks(
1628 now,
1629 self.receiving_ecn,
1630 path_id,
1631 space_id,
1632 &mut self.spaces[space_id],
1633 is_multipath_negotiated,
1634 &mut builder,
1635 &mut self.path_stats.get_mut(path_id).frame_tx,
1636 self.crypto_state.has_keys(space_id.encryption_level()),
1637 );
1638 }
1639
1640 debug_assert!(
1648 builder.frame_space_remaining() > frame::ConnectionClose::SIZE_BOUND,
1649 "ACKs should leave space for ConnectionClose"
1650 );
1651 let stats = &mut self.path_stats.get_mut(path_id).frame_tx;
1652 if frame::ConnectionClose::SIZE_BOUND < builder.frame_space_remaining() {
1653 let max_frame_size = builder.frame_space_remaining();
1654 let close: Close = match self.state.as_type() {
1655 StateType::Closed => {
1656 let reason: Close =
1657 self.state.as_closed().expect("checked").clone().into();
1658 if space_id == SpaceId::Data || reason.is_transport_layer() {
1659 reason
1660 } else {
1661 TransportError::APPLICATION_ERROR("").into()
1662 }
1663 }
1664 StateType::Draining => TransportError::NO_ERROR("").into(),
1665 _ => unreachable!(
1666 "tried to make a close packet when the connection wasn't closed"
1667 ),
1668 };
1669 builder.write_frame(close.encoder(max_frame_size), stats);
1670 }
1671 let last_pn = builder.packet_number;
1672 builder.finish_and_track(now, self, path_id, pad_datagram);
1673 if space_id.kind() == self.highest_space {
1674 self.connection_close_pending = false;
1677 }
1678 return PollPathSpaceStatus::WrotePacket {
1691 last_packet_number: last_pn,
1692 pad_datagram,
1693 };
1694 }
1695
1696 self.populate_packet(now, space_id, path_id, scheduling_info, &mut builder);
1697
1698 debug_assert!(
1705 !(builder.sent_frames().is_ack_only(&self.streams)
1706 && !can_send.acks
1707 && (can_send.other || can_send.space_specific)
1708 && builder.buf.segment_size()
1709 == self.path_data(path_id).current_mtu() as usize
1710 && self.datagrams.outgoing.is_empty()),
1711 "SendableFrames was {can_send:?}, but only ACKs have been written"
1712 );
1713 if builder.sent_frames().requires_padding {
1714 pad_datagram |= PadDatagram::ToMinMtu;
1715 }
1716
1717 for path_id in builder.sent_frames().largest_acked.keys() {
1718 self.spaces[space_id]
1719 .for_path(*path_id)
1720 .pending_acks
1721 .acks_sent();
1722 self.timers.stop(
1723 Timer::PerPath(*path_id, PathTimer::MaxAckDelay),
1724 self.qlog.with_time(now),
1725 );
1726 }
1727
1728 let max_packet_size = builder
1734 .buf
1735 .datagram_remaining_mut()
1736 .saturating_sub(builder.predict_packet_end());
1737 if builder.can_coalesce
1740 && path_id == PathId::ZERO
1741 && let Some(next_space_id) = space_id.next()
1742 && max_packet_size > MIN_PACKET_SPACE
1743 && self
1744 .space_can_send(space_id, path_id, max_packet_size, connection_close_pending)
1745 .is_empty()
1746 && self.has_pending_packet(next_space_id, max_packet_size, connection_close_pending)
1747 {
1748 trace!("will coalesce with next packet");
1751 let last_pn = builder.packet_number;
1752 builder.finish_and_track(now, self, path_id, PadDatagram::No);
1753 return PollPathSpaceStatus::WrotePacket {
1756 last_packet_number: last_pn,
1757 pad_datagram,
1758 };
1759 } else {
1760 if builder.buf.num_datagrams() > 1 && matches!(pad_datagram, PadDatagram::No) {
1766 const MAX_PADDING: usize = 32;
1774 if builder.buf.datagram_remaining_mut()
1775 > builder.predict_packet_end() + MAX_PADDING
1776 {
1777 trace!(
1778 "GSO truncated by demand for {} padding bytes",
1779 builder.buf.datagram_remaining_mut() - builder.predict_packet_end()
1780 );
1781 let last_pn = builder.packet_number;
1782 builder.finish_and_track(now, self, path_id, PadDatagram::No);
1783 return PollPathSpaceStatus::Send {
1784 last_packet_number: last_pn,
1785 };
1786 }
1787
1788 builder.finish_and_track(now, self, path_id, PadDatagram::ToSegmentSize);
1791 } else {
1792 builder.finish_and_track(now, self, path_id, pad_datagram);
1793 }
1794
1795 if transmit.num_datagrams() == 1 {
1798 transmit.clip_segment_size();
1799 }
1800 }
1801 }
1802 }
1803
1804 fn poll_transmit_mtu_probe(
1805 &mut self,
1806 now: Instant,
1807 buf: &mut Vec<u8>,
1808 path_id: PathId,
1809 ) -> Option<Transmit> {
1810 let (active_cid, probe_size) = self.get_mtu_probe_data(now, path_id)?;
1811
1812 let mut transmit = TransmitBuf::new(buf, NonZeroUsize::MIN, probe_size as usize);
1814 transmit.start_new_datagram_with_size(probe_size as usize);
1815
1816 let mut builder =
1817 PacketBuilder::new(now, SpaceId::Data, path_id, active_cid, &mut transmit, self)?;
1818
1819 trace!(?probe_size, "writing MTUD probe");
1821 builder.write_frame(frame::Ping, &mut self.path_stats.get_mut(path_id).frame_tx);
1822
1823 if self.peer_supports_ack_frequency() {
1825 builder.write_frame(
1826 frame::ImmediateAck,
1827 &mut self.path_stats.get_mut(path_id).frame_tx,
1828 );
1829 }
1830
1831 builder.finish_and_track(now, self, path_id, PadDatagram::ToSize(probe_size));
1832
1833 self.path_stats.get_mut(path_id).sent_plpmtud_probes += 1;
1834
1835 Some(self.build_transmit(path_id, transmit))
1836 }
1837
1838 fn get_mtu_probe_data(&mut self, now: Instant, path_id: PathId) -> Option<(ConnectionId, u16)> {
1846 let active_cid = self.remote_cids.get(&path_id).map(CidQueue::active)?;
1847 let is_eligible = self.path_data(path_id).validated
1848 && !self.path_data(path_id).is_validating_path()
1849 && !self.abandoned_paths.contains(&path_id);
1850
1851 if !is_eligible {
1852 return None;
1853 }
1854 let next_pn = self.spaces[SpaceId::Data]
1855 .for_path(path_id)
1856 .peek_tx_number();
1857 let probe_size = self
1858 .path_data_mut(path_id)
1859 .mtud
1860 .poll_transmit(now, next_pn)?;
1861
1862 Some((active_cid, probe_size))
1863 }
1864
1865 fn has_pending_packet(
1882 &mut self,
1883 current_space_id: SpaceId,
1884 max_packet_size: usize,
1885 connection_close_pending: bool,
1886 ) -> bool {
1887 let mut space_id = current_space_id;
1888 loop {
1889 let can_send = self.space_can_send(
1890 space_id,
1891 PathId::ZERO,
1892 max_packet_size,
1893 connection_close_pending,
1894 );
1895 if !can_send.is_empty() {
1896 return true;
1897 }
1898 match space_id.next() {
1899 Some(next_space_id) => space_id = next_space_id,
1900 None => break,
1901 }
1902 }
1903 false
1904 }
1905
1906 fn path_congestion_check(
1908 &mut self,
1909 space_id: SpaceId,
1910 path_id: PathId,
1911 transmit: &TransmitBuf<'_>,
1912 can_send: &SendableFrames,
1913 now: Instant,
1914 ) -> PathBlocked {
1915 if self.side().is_server()
1921 && self
1922 .path_data(path_id)
1923 .anti_amplification_blocked(transmit.len() as u64 + 1)
1924 {
1925 trace!(?space_id, %path_id, "blocked by anti-amplification");
1926 return PathBlocked::AntiAmplification;
1927 }
1928
1929 let bytes_to_send = transmit.segment_size() as u64;
1932 let need_loss_probe = self.spaces[space_id].for_path(path_id).loss_probes > 0;
1933
1934 if can_send.other && !need_loss_probe && !can_send.close {
1935 let path = self.path_data(path_id);
1936 if path.in_flight.bytes + bytes_to_send >= path.congestion.window() {
1937 trace!(
1938 ?space_id,
1939 %path_id,
1940 in_flight=%path.in_flight.bytes,
1941 congestion_window=%path.congestion.window(),
1942 "blocked by congestion control",
1943 );
1944 return PathBlocked::Congestion;
1945 }
1946 }
1947
1948 if let Some(delay) = self.path_data_mut(path_id).pacing_delay(bytes_to_send, now) {
1950 let resume_time = now + delay;
1951 self.timers.set(
1952 Timer::PerPath(path_id, PathTimer::Pacing),
1953 resume_time,
1954 self.qlog.with_time(now),
1955 );
1956 trace!(?space_id, %path_id, ?delay, "blocked by pacing");
1959 return PathBlocked::Pacing;
1960 }
1961
1962 PathBlocked::No
1963 }
1964
1965 fn send_prev_path_challenge(
1970 &mut self,
1971 now: Instant,
1972 buf: &mut Vec<u8>,
1973 path_id: PathId,
1974 ) -> Option<Transmit> {
1975 let (prev_cid, prev_path) = self.paths.get_mut(&path_id)?.prev.as_mut()?;
1976 if !prev_path.pending_challenge {
1977 return None;
1978 };
1979 prev_path.pending_challenge = false;
1980 let token = self.rng.random();
1981 let network_path = prev_path.network_path;
1982 prev_path.record_path_challenge_sent(now, token, network_path);
1983
1984 debug_assert_eq!(
1985 self.highest_space,
1986 SpaceKind::Data,
1987 "PATH_CHALLENGE queued without 1-RTT keys"
1988 );
1989 let buf = &mut TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into());
1990 buf.start_new_datagram();
1991
1992 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, *prev_cid, buf, self)?;
1998 let challenge = frame::PathChallenge(token);
1999 let stats = &mut self.path_stats.get_mut(path_id).frame_tx;
2000 builder.write_frame_with_log_msg(challenge, stats, Some("validating previous path"));
2001
2002 builder.pad_to(MIN_INITIAL_SIZE);
2007
2008 builder.finish(self, now);
2009 self.path_stats
2010 .get_mut(path_id)
2011 .udp_tx
2012 .on_sent(1, buf.len());
2013
2014 trace!(
2015 dst = ?network_path.remote,
2016 src = ?network_path.local_ip,
2017 len = buf.len(),
2018 "sending prev_path off-path challenge",
2019 );
2020 Some(Transmit {
2021 destination: network_path.remote,
2022 size: buf.len(),
2023 ecn: None,
2024 segment_size: None,
2025 src_ip: network_path.local_ip,
2026 })
2027 }
2028
2029 fn send_off_path_path_response(
2030 &mut self,
2031 now: Instant,
2032 buf: &mut Vec<u8>,
2033 path_id: PathId,
2034 ) -> Option<Transmit> {
2035 let network_path = self
2036 .paths
2037 .get_mut(&path_id)
2038 .map(|state| state.data.network_path)?;
2039 let cid_queue = self.remote_cids.get_mut(&path_id)?;
2040 let pns = self.spaces[SpaceKind::Data].for_path(path_id);
2041 let (token, network_path) = pns.pending_path_responses.pop_off_path(network_path)?;
2042
2043 let cid = cid_queue.active();
2045
2046 let frame = frame::PathResponse(token);
2048
2049 let buf = &mut TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into());
2050 buf.start_new_datagram();
2051
2052 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, cid, buf, self)?;
2053 let stats = &mut self.path_stats.get_mut(path_id).frame_tx;
2054 builder.write_frame_with_log_msg(frame, stats, Some("(off-path)"));
2055
2056 if self
2063 .find_validated_path_on_network_path(network_path)
2064 .is_none()
2065 && self.n0_nat_traversal.client_side().is_ok()
2066 {
2067 let token = self.rng.random();
2068 let stats = &mut self.path_stats.get_mut(path_id).frame_tx;
2069 builder.write_frame(frame::PathChallenge(token), stats);
2070 let ip_port = (network_path.remote.ip(), network_path.remote.port());
2071 self.n0_nat_traversal.mark_probe_sent(ip_port, token);
2072 }
2073
2074 builder.pad_to(MIN_INITIAL_SIZE);
2077 builder.finish(self, now);
2078
2079 let size = buf.len();
2080 self.path_stats.get_mut(path_id).udp_tx.on_sent(1, size);
2081
2082 trace!(
2083 dst = ?network_path.remote,
2084 src = ?network_path.local_ip,
2085 len = buf.len(),
2086 "sending off-path PATH_RESPONSE",
2087 );
2088 Some(Transmit {
2089 destination: network_path.remote,
2090 size,
2091 ecn: None,
2092 segment_size: None,
2093 src_ip: network_path.local_ip,
2094 })
2095 }
2096
2097 fn send_nat_traversal_path_challenge(
2099 &mut self,
2100 now: Instant,
2101 buf: &mut Vec<u8>,
2102 path_id: PathId,
2103 ) -> Option<Transmit> {
2104 let remote = self.n0_nat_traversal.next_probe_addr()?;
2105
2106 if !self.paths.get(&path_id)?.data.validated {
2107 return None;
2109 }
2110
2111 let Some(cid) = self
2116 .remote_cids
2117 .get(&path_id)
2118 .map(|cid_queue| cid_queue.active())
2119 else {
2120 trace!(%path_id, "Not sending NAT traversal probe for path with no CIDs");
2121 return None;
2122 };
2123 let token = self.rng.random();
2124
2125 let frame = frame::PathChallenge(token);
2127
2128 let mut buf = TransmitBuf::new(buf, NonZeroUsize::MIN, MIN_INITIAL_SIZE.into());
2129 buf.start_new_datagram();
2130
2131 let mut builder = PacketBuilder::new(now, SpaceId::Data, path_id, cid, &mut buf, self)?;
2132 let stats = &mut self.path_stats.get_mut(path_id).frame_tx;
2133 builder.write_frame_with_log_msg(frame, stats, Some("(nat-traversal)"));
2134 builder.finish(self, now);
2137
2138 self.n0_nat_traversal.mark_probe_sent(remote, token);
2140
2141 let size = buf.len();
2142 self.path_stats.get_mut(path_id).udp_tx.on_sent(1, size);
2143
2144 trace!(dst = ?remote, len = buf.len(), "sending off-path NAT probe");
2145 Some(Transmit {
2146 destination: remote.into(),
2147 size,
2148 ecn: None,
2149 segment_size: None,
2150 src_ip: None,
2151 })
2152 }
2153
2154 fn space_can_send(
2162 &mut self,
2163 space_id: SpaceId,
2164 path_id: PathId,
2165 packet_size: usize,
2166 connection_close_pending: bool,
2167 ) -> SendableFrames {
2168 let space = &mut self.spaces[space_id];
2169 let space_has_crypto = self.crypto_state.has_keys(space_id.encryption_level());
2170
2171 if !space_has_crypto
2172 && (space_id != SpaceId::Data
2173 || !self.crypto_state.has_keys(EncryptionLevel::ZeroRtt)
2174 || self.side.is_server())
2175 {
2176 return SendableFrames::empty();
2178 }
2179
2180 let mut can_send = space.can_send(path_id, &self.streams);
2181
2182 if space_id == SpaceId::Data {
2184 let pn = space.for_path(path_id).peek_tx_number();
2185 let frame_space_1rtt =
2191 packet_size.saturating_sub(self.predict_1rtt_overhead(pn, path_id));
2192 can_send |= self.can_send_1rtt(path_id, frame_space_1rtt);
2193 }
2194
2195 can_send.close = connection_close_pending && space_has_crypto;
2196
2197 can_send
2198 }
2199
2200 pub fn handle_event(&mut self, event: ConnectionEvent) {
2206 use ConnectionEventInner::*;
2207 match event.0 {
2208 Datagram(DatagramConnectionEvent {
2209 now,
2210 network_path,
2211 path_id,
2212 ecn,
2213 first_decode,
2214 remaining,
2215 }) => {
2216 let span = trace_span!("pkt", %path_id);
2217 let _guard = span.enter();
2218
2219 if self.early_discard_packet(network_path, path_id) {
2220 return;
2222 }
2223
2224 let was_anti_amplification_blocked = self
2225 .path(path_id)
2226 .map(|path| path.anti_amplification_blocked(1))
2227 .unwrap_or(false);
2230
2231 let rx = &mut self.path_stats.get_mut(path_id).udp_rx;
2232 rx.datagrams += 1;
2233 rx.bytes += first_decode.len() as u64;
2234 let data_len = first_decode.len();
2235
2236 self.handle_decode(now, network_path, path_id, ecn, first_decode);
2237 if let Some(path) = self.path_mut(path_id) {
2242 path.inc_total_recvd(data_len as u64);
2243 }
2244
2245 if let Some(data) = remaining {
2246 self.path_stats.get_mut(path_id).udp_rx.bytes += data.len() as u64;
2247 self.handle_coalesced(now, network_path, path_id, ecn, data);
2248 }
2249
2250 if let Some(path) = self.paths.get_mut(&path_id) {
2251 self.qlog
2252 .emit_recovery_metrics(path_id, &mut path.data, now);
2253 }
2254
2255 if was_anti_amplification_blocked {
2256 self.set_loss_detection_timer(now, path_id);
2260 }
2261 }
2262 NewIdentifiers(ids, now, cid_len, cid_lifetime) => {
2263 let path_id = ids.first().map(|issued| issued.path_id).unwrap_or_default();
2264 debug_assert!(ids.iter().all(|issued| issued.path_id == path_id));
2265
2266 if self.abandoned_paths.contains(&path_id) {
2269 if !self.state.is_drained() {
2270 for issued in &ids {
2271 self.endpoint_events
2272 .push_back(EndpointEventInner::RetireConnectionId(
2273 now,
2274 path_id,
2275 issued.sequence,
2276 false,
2277 ));
2278 }
2279 }
2280 return;
2281 }
2282
2283 let cid_state = self
2284 .local_cid_state
2285 .entry(path_id)
2286 .or_insert_with(|| CidState::new(cid_len, cid_lifetime, now, 0));
2287 cid_state.new_cids(&ids, now);
2288
2289 ids.into_iter().rev().for_each(|frame| {
2290 self.spaces[SpaceId::Data].pending.new_cids.push(frame);
2291 });
2292 self.reset_cid_retirement(now);
2294 }
2295 }
2296 }
2297
2298 fn early_discard_packet(&mut self, network_path: FourTuple, path_id: PathId) -> bool {
2306 if self.is_handshaking() && path_id != PathId::ZERO {
2307 debug!(%network_path, %path_id, "discarding multipath packet during handshake");
2308 return true;
2309 }
2310
2311 if !self.paths.contains_key(&path_id) && self.abandoned_paths.contains(&path_id) {
2312 trace!(%path_id, "discarding packet for discarded path");
2313 return true;
2314 }
2315
2316 let peer_may_probe = self.peer_may_probe();
2317 let local_ip_may_migrate = self.local_ip_may_migrate();
2318
2319 if let Some(known_path) = self.path_mut(path_id) {
2323 if network_path.remote != known_path.network_path.remote && !peer_may_probe {
2324 trace!(
2325 %path_id,
2326 %network_path,
2327 %known_path.network_path,
2328 "discarding packet from unrecognized peer"
2329 );
2330 return true;
2331 }
2332
2333 if known_path.network_path.local_ip.is_some()
2334 && network_path.local_ip.is_some()
2335 && known_path.network_path.local_ip != network_path.local_ip
2336 && !local_ip_may_migrate
2337 {
2338 trace!(
2339 %path_id,
2340 %network_path,
2341 %known_path.network_path,
2342 "discarding packet sent to incorrect interface"
2343 );
2344 return true;
2345 }
2346 }
2347 false
2348 }
2349
2350 fn peer_may_probe(&self) -> bool {
2361 match &self.side {
2362 ConnectionSide::Client { .. } => {
2363 if let Some(hs) = self.state.as_handshake() {
2364 hs.allow_server_migration
2365 } else {
2366 self.n0_nat_traversal.is_negotiated() && self.is_handshake_confirmed()
2367 }
2368 }
2369 ConnectionSide::Server { server_config } => {
2370 self.is_handshake_confirmed()
2371 && (server_config.migration || self.n0_nat_traversal.is_negotiated())
2372 }
2373 }
2374 }
2375
2376 fn peer_may_migrate(&self) -> bool {
2388 match &self.side {
2389 ConnectionSide::Server { server_config } => {
2390 server_config.migration && self.is_handshake_confirmed()
2391 }
2392 ConnectionSide::Client { .. } => false,
2393 }
2394 }
2395
2396 fn local_ip_may_migrate(&self) -> bool {
2409 (self.side.is_client() || self.n0_nat_traversal.is_negotiated())
2410 && self.is_handshake_confirmed()
2411 }
2412 pub fn handle_timeout(&mut self, now: Instant) {
2422 while let Some((timer, _time)) = self.timers.expire_before(now, &self.qlog) {
2423 let span = match timer {
2424 Timer::Conn(timer) => trace_span!("timeout", scope = "conn", ?timer),
2425 Timer::PerPath(path_id, timer) => {
2426 trace_span!("timer_fired", scope="path", %path_id, ?timer)
2427 }
2428 };
2429 let _guard = span.enter();
2430 trace!("timeout");
2431 match timer {
2432 Timer::Conn(timer) => match timer {
2433 ConnTimer::Close => {
2434 self.state.move_to_drained(None, &mut self.endpoint_events);
2435 }
2436 ConnTimer::Idle => {
2437 self.kill(ConnectionError::TimedOut);
2438 }
2439 ConnTimer::KeepAlive => {
2440 self.ping();
2441 }
2442 ConnTimer::KeyDiscard => {
2443 self.crypto_state.discard_temporary_keys();
2444 }
2445 ConnTimer::PushNewCid => {
2446 while let Some((path_id, when)) = self.next_cid_retirement() {
2447 if when > now {
2448 break;
2449 }
2450 match self.local_cid_state.get_mut(&path_id) {
2451 None => error!(%path_id, "No local CID state for path"),
2452 Some(cid_state) => {
2453 let num_new_cid = cid_state.on_cid_timeout().into();
2455 if !self.state.is_closed() {
2456 trace!(
2457 "push a new CID to peer RETIRE_PRIOR_TO field {}",
2458 cid_state.retire_prior_to()
2459 );
2460 self.endpoint_events.push_back(
2461 EndpointEventInner::NeedIdentifiers(
2462 path_id,
2463 now,
2464 num_new_cid,
2465 ),
2466 );
2467 }
2468 }
2469 }
2470 }
2471 }
2472 ConnTimer::NoAvailablePath => {
2473 if self.state.is_closed() || self.state.is_drained() {
2478 error!("no viable path timer fired, but connection already closing");
2481 } else {
2482 trace!("no viable path grace period expired, closing connection");
2483 let err = TransportError::NO_VIABLE_PATH(
2484 "last path abandoned, no new path opened",
2485 );
2486 self.close_common();
2487 self.set_close_timer(now);
2488 self.connection_close_pending = true;
2489 self.state.move_to_closed(err);
2490 }
2491 }
2492 ConnTimer::NatTraversalProbeRetry => {
2493 self.n0_nat_traversal.queue_retries(self.is_ipv6());
2494 if let Some(delay) =
2495 self.n0_nat_traversal.retry_delay(self.config.initial_rtt)
2496 {
2497 self.timers.set(
2498 Timer::Conn(ConnTimer::NatTraversalProbeRetry),
2499 now + delay,
2500 self.qlog.with_time(now),
2501 );
2502 trace!("re-queued NAT probes");
2503 } else {
2504 trace!("no more NAT probes remaining");
2505 }
2506 }
2507 },
2508 Timer::PerPath(path_id, timer) => {
2509 match timer {
2510 PathTimer::PathIdle => {
2511 if let Err(err) =
2512 self.close_path_inner(now, path_id, PathAbandonReason::TimedOut)
2513 {
2514 warn!(?err, "failed closing path");
2515 }
2516 }
2517
2518 PathTimer::PathKeepAlive => {
2519 self.ping_path(path_id).ok();
2520 }
2521 PathTimer::LossDetection => {
2522 self.on_loss_detection_timeout(now, path_id);
2523 if let Some(path) = self.paths.get_mut(&path_id) {
2524 self.qlog
2525 .emit_recovery_metrics(path_id, &mut path.data, now);
2526 } else {
2527 error!("LossDetection fired for unknown path");
2528 }
2529 }
2530 PathTimer::PathValidationFailed => {
2531 let Some(path) = self.paths.get_mut(&path_id) else {
2532 continue;
2533 };
2534 self.timers.stop(
2535 Timer::PerPath(path_id, PathTimer::PathChallengeLost),
2536 self.qlog.with_time(now),
2537 );
2538 debug!("path migration validation failed");
2539 path.data.reset_on_path_challenges();
2540 if let Some((_, prev)) = path.prev.take() {
2541 path.data = prev;
2542 self.set_loss_detection_timer(now, path_id);
2543 }
2544 }
2545 PathTimer::PathChallengeLost => {
2546 let Some(path) = self.paths.get_mut(&path_id) else {
2547 continue;
2548 };
2549 trace!(?path.data.lost_challenge_count, "path challenge deemed lost");
2550 path.data.pending_challenge = true;
2551 path.data.lost_challenge_count += 1;
2552 self.timers.set(
2553 Timer::PerPath(path_id, PathTimer::PathChallengeLost),
2554 now + path.data.on_path_challenge_pto(),
2555 self.qlog.with_time(now),
2556 );
2557 }
2558 PathTimer::Pacing => {}
2559 PathTimer::MaxAckDelay => {
2560 self.spaces[SpaceId::Data]
2562 .for_path(path_id)
2563 .pending_acks
2564 .on_max_ack_delay_timeout()
2565 }
2566 PathTimer::PathDrained => {
2567 self.timers.stop_per_path(path_id, self.qlog.with_time(now));
2570 if let Some(local_cid_state) = self.local_cid_state.remove(&path_id) {
2571 debug_assert!(!self.state.is_drained()); let (min_seq, max_seq) = local_cid_state.active_seq();
2573 for seq in min_seq..=max_seq {
2574 self.endpoint_events.push_back(
2575 EndpointEventInner::RetireConnectionId(
2576 now, path_id, seq, false,
2577 ),
2578 );
2579 }
2580 }
2581 self.discard_path(path_id, now);
2582 }
2583 }
2584 }
2585 }
2586 }
2587 }
2588
2589 pub fn close(&mut self, now: Instant, error_code: VarInt, reason: Bytes) {
2601 self.close_inner(
2602 now,
2603 Close::Application(frame::ApplicationClose { error_code, reason }),
2604 )
2605 }
2606
2607 fn close_inner(&mut self, now: Instant, reason: Close) {
2623 let was_closed = self.state.is_closed();
2624 if !was_closed {
2625 self.close_common();
2626 self.set_close_timer(now);
2627 self.connection_close_pending = true;
2628 self.state.move_to_closed_local(reason);
2629 }
2630 }
2631
2632 pub fn datagrams(&mut self) -> Datagrams<'_> {
2634 Datagrams { conn: self }
2635 }
2636
2637 pub fn stats(&mut self) -> ConnectionStats {
2639 let mut stats = self.partial_stats.clone();
2640
2641 for path_stats in self.path_stats.iter_stats() {
2642 stats += *path_stats;
2647 }
2648
2649 stats
2650 }
2651
2652 pub fn path_stats(&mut self, path_id: PathId) -> Option<PathStats> {
2654 let path = self.paths.get(&path_id)?;
2655 let mut stats = self.path_stats.get(path_id).unwrap_or_default();
2656 stats.rtt = path.data.rtt.get();
2657 stats.cwnd = path.data.congestion.window();
2658 stats.current_mtu = path.data.mtud.current_mtu();
2659 Some(stats)
2660 }
2661
2662 pub fn ping(&mut self) {
2666 for path_data in self.spaces[self.highest_space].number_spaces.values_mut() {
2669 path_data.pending_ping = true;
2670 }
2671 }
2672
2673 pub fn ping_path(&mut self, path: PathId) -> Result<(), ClosedPath> {
2677 let path_data = self.spaces[self.highest_space]
2678 .number_spaces
2679 .get_mut(&path)
2680 .ok_or(ClosedPath { _private: () })?;
2681 path_data.pending_ping = true;
2682 Ok(())
2683 }
2684
2685 pub fn force_key_update(&mut self) {
2689 if !self.state.is_established() {
2690 debug!("ignoring forced key update in illegal state");
2691 return;
2692 }
2693 if self.crypto_state.prev_crypto.is_some() {
2694 debug!("ignoring redundant forced key update");
2697 return;
2698 }
2699 self.crypto_state.update_keys(None, false);
2700 }
2701
2702 pub fn crypto_session(&self) -> &dyn crypto::Session {
2704 self.crypto_state.session.as_ref()
2705 }
2706
2707 pub fn is_handshaking(&self) -> bool {
2717 self.state.is_handshake()
2718 }
2719
2720 pub fn is_closed(&self) -> bool {
2731 self.state.is_closed()
2732 }
2733
2734 pub fn is_drained(&self) -> bool {
2739 self.state.is_drained()
2740 }
2741
2742 pub fn accepted_0rtt(&self) -> bool {
2746 self.crypto_state.accepted_0rtt
2747 }
2748
2749 pub fn has_0rtt(&self) -> bool {
2751 self.crypto_state.zero_rtt_enabled
2752 }
2753
2754 pub fn has_pending_retransmits(&self) -> bool {
2756 !self.spaces[SpaceId::Data].pending.is_empty(&self.streams)
2757 }
2758
2759 pub fn side(&self) -> Side {
2761 self.side.side()
2762 }
2763
2764 pub fn path_observed_address(&self, path_id: PathId) -> Result<Option<SocketAddr>, ClosedPath> {
2766 self.path(path_id)
2767 .map(|path_data| {
2768 path_data
2769 .last_observed_addr_report
2770 .as_ref()
2771 .map(|observed| observed.socket_addr())
2772 })
2773 .ok_or(ClosedPath { _private: () })
2774 }
2775
2776 pub fn rtt(&self, path_id: PathId) -> Option<Duration> {
2778 self.path(path_id).map(|d| d.rtt.get())
2779 }
2780
2781 pub fn congestion_state(&self, path_id: PathId) -> Option<&dyn Controller> {
2783 self.path(path_id).map(|d| d.congestion.as_ref())
2784 }
2785
2786 pub fn set_max_concurrent_streams(&mut self, dir: Dir, count: VarInt) {
2791 self.streams.set_max_concurrent(dir, count);
2792 let pending = &mut self.spaces[SpaceId::Data].pending;
2795 self.streams.queue_max_stream_id(pending);
2796 }
2797
2798 pub fn set_max_concurrent_paths(
2808 &mut self,
2809 now: Instant,
2810 count: NonZeroU32,
2811 ) -> Result<(), MultipathNotNegotiated> {
2812 if !self.is_multipath_negotiated() {
2813 return Err(MultipathNotNegotiated { _private: () });
2814 }
2815 self.max_concurrent_paths = count;
2816
2817 let in_use_count = self
2818 .local_max_path_id
2819 .next()
2820 .saturating_sub(self.abandoned_paths.len())
2821 .as_u32();
2822 let extra_needed = count.get().saturating_sub(in_use_count);
2823 let new_max_path_id = self.local_max_path_id.saturating_add(extra_needed);
2824
2825 self.set_max_path_id(now, new_max_path_id);
2826
2827 Ok(())
2828 }
2829
2830 fn set_max_path_id(&mut self, now: Instant, max_path_id: PathId) {
2832 if max_path_id <= self.local_max_path_id {
2833 return;
2834 }
2835
2836 self.local_max_path_id = max_path_id;
2837 self.spaces[SpaceId::Data].pending.max_path_id = true;
2838
2839 self.issue_first_path_cids(now);
2840 }
2841
2842 pub fn max_concurrent_streams(&self, dir: Dir) -> u64 {
2848 self.streams.max_concurrent(dir)
2849 }
2850
2851 pub fn set_send_window(&mut self, send_window: u64) {
2853 self.streams.set_send_window(send_window);
2854 }
2855
2856 pub fn set_receive_window(&mut self, receive_window: VarInt) {
2858 if self.streams.set_receive_window(receive_window) {
2859 self.spaces[SpaceId::Data].pending.max_data = true;
2860 }
2861 }
2862
2863 pub fn is_multipath_negotiated(&self) -> bool {
2868 !self.is_handshaking()
2869 && self.config.max_concurrent_multipath_paths.is_some()
2870 && self.peer_params.initial_max_path_id.is_some()
2871 }
2872
2873 fn on_ack_received(
2874 &mut self,
2875 now: Instant,
2876 space: SpaceId,
2877 ack: frame::Ack,
2878 ) -> Result<(), TransportError> {
2879 let path = PathId::ZERO;
2881 self.inner_on_ack_received(now, space, path, ack)
2882 }
2883
2884 fn on_path_ack_received(
2885 &mut self,
2886 now: Instant,
2887 space: SpaceId,
2888 path_ack: frame::PathAck,
2889 ) -> Result<(), TransportError> {
2890 let (ack, path) = path_ack.into_ack();
2891 self.inner_on_ack_received(now, space, path, ack)
2892 }
2893
2894 fn inner_on_ack_received(
2896 &mut self,
2897 now: Instant,
2898 space: SpaceId,
2899 path: PathId,
2900 ack: frame::Ack,
2901 ) -> Result<(), TransportError> {
2902 if !self.spaces[space].number_spaces.contains_key(&path) {
2903 if self.abandoned_paths.contains(&path) {
2904 trace!("silently ignoring PATH_ACK on discarded path");
2910 return Ok(());
2911 } else {
2912 return Err(TransportError::PROTOCOL_VIOLATION(
2913 "received PATH_ACK with path ID never used",
2914 ));
2915 }
2916 }
2917 if ack.largest >= self.spaces[space].for_path(path).next_packet_number {
2918 return Err(TransportError::PROTOCOL_VIOLATION("unsent packet acked"));
2919 }
2920 let new_largest_pn = {
2922 let space = &mut self.spaces[space].for_path(path);
2923 if space
2924 .largest_acked_packet_pn
2925 .is_none_or(|pn| ack.largest > pn)
2926 {
2927 space.largest_acked_packet_pn = Some(ack.largest);
2928 if let Some(info) = space.sent_packets.get(ack.largest) {
2929 space.largest_acked_packet_send_time = info.time_sent;
2933 }
2934 Some(ack.largest)
2935 } else {
2936 None
2937 }
2938 };
2939
2940 if self.detect_spurious_loss(&ack, space, path) {
2941 self.path_stats.get_mut(path).spurious_congestion_events += 1;
2942 self.path_data_mut(path)
2943 .congestion
2944 .on_spurious_congestion_event();
2945 }
2946
2947 let mut newly_acked: ArrayRangeSet = ArrayRangeSet::new();
2949 for range in ack.iter() {
2950 self.spaces[space].for_path(path).check_ack(range.clone())?;
2951 for (pn, _) in self.spaces[space]
2952 .for_path(path)
2953 .sent_packets
2954 .iter_range(range)
2955 {
2956 newly_acked.insert_one(pn);
2957 }
2958 }
2959
2960 if newly_acked.is_empty() {
2961 return Ok(());
2962 }
2963
2964 let mut ack_eliciting_acked = false;
2965 for packet in newly_acked.elts() {
2966 if let Some(info) = self.spaces[space].for_path(path).take(packet) {
2967 for (acked_path_id, acked_pn) in info.largest_acked.iter() {
2968 if let Some(pns) = self.spaces[space].path_space_mut(*acked_path_id) {
2974 pns.pending_acks.subtract_below(*acked_pn);
2975 }
2976 }
2977 ack_eliciting_acked |= info.ack_eliciting;
2978
2979 let path_data = self.path_data_mut(path);
2981 let mtu_updated = path_data.mtud.on_acked(space.kind(), packet, info.size);
2982 if mtu_updated {
2983 path_data
2984 .congestion
2985 .on_mtu_update(path_data.mtud.current_mtu());
2986 }
2987
2988 self.ack_frequency.on_acked(path, packet);
2990
2991 self.on_packet_acked(now, path, packet, info);
2992 }
2993 }
2994
2995 let largest_ackd = self.spaces[space].for_path(path).largest_acked_packet_pn;
2996 let path_data = self.path_data_mut(path);
2997 let app_limited = path_data.app_limited;
2998 let in_flight = path_data.in_flight.bytes;
2999
3000 path_data
3001 .congestion
3002 .on_end_acks(now, in_flight, app_limited, largest_ackd);
3003
3004 if new_largest_pn.is_some() && ack_eliciting_acked {
3005 let ack_delay = if space != SpaceId::Data {
3006 Duration::from_micros(0)
3007 } else {
3008 cmp::min(
3009 self.ack_frequency.peer_max_ack_delay,
3010 Duration::from_micros(ack.delay << self.peer_params.ack_delay_exponent.0),
3011 )
3012 };
3013 let rtt = now.saturating_duration_since(
3014 self.spaces[space]
3015 .for_path(path)
3016 .largest_acked_packet_send_time,
3017 );
3018
3019 let next_pn = self.spaces[space].for_path(path).next_packet_number;
3020 let path_data = self.path_data_mut(path);
3021 path_data.rtt.update(ack_delay, rtt);
3023 if path_data.first_packet_after_rtt_sample.is_none() {
3024 path_data.first_packet_after_rtt_sample = Some((space.kind(), next_pn));
3025 }
3026 }
3027
3028 self.detect_lost_packets(now, space, path, true);
3030
3031 if self.peer_completed_handshake_address_validation() {
3036 self.path_data_mut(path).pto_count = 0;
3037 }
3038
3039 if self.path_data(path).sending_ecn {
3044 if let Some(ecn) = ack.ecn {
3045 if let Some(largest_sent_pn) = new_largest_pn {
3050 let sent = self.spaces[space]
3051 .for_path(path)
3052 .largest_acked_packet_send_time;
3053 self.process_ecn(
3054 now,
3055 space,
3056 path,
3057 newly_acked.range_count() as u64,
3058 ecn,
3059 sent,
3060 largest_sent_pn,
3061 );
3062 }
3063 } else {
3064 debug!("ECN not acknowledged by peer");
3066 self.path_data_mut(path).sending_ecn = false;
3067 }
3068 }
3069
3070 self.set_loss_detection_timer(now, path);
3071 Ok(())
3072 }
3073
3074 fn detect_spurious_loss(&mut self, ack: &frame::Ack, space: SpaceId, path: PathId) -> bool {
3075 let lost_packets = &mut self.spaces[space].for_path(path).lost_packets;
3076
3077 if lost_packets.is_empty() {
3078 return false;
3079 }
3080
3081 for range in ack.iter() {
3082 let spurious_losses: Vec<u64> = lost_packets
3083 .iter_range(range.clone())
3084 .map(|(pn, _info)| pn)
3085 .collect();
3086
3087 for pn in spurious_losses {
3088 lost_packets.remove(pn);
3089 }
3090 }
3091
3092 lost_packets.is_empty()
3097 }
3098
3099 fn drain_lost_packets(&mut self, now: Instant, space: SpaceId, path: PathId) {
3104 let two_pto = 2 * self.path_data(path).rtt.pto_base();
3105
3106 let lost_packets = &mut self.spaces[space].for_path(path).lost_packets;
3107 lost_packets.retain(|_pn, info| now.saturating_duration_since(info.time_sent) <= two_pto);
3108 }
3109
3110 fn process_ecn(
3112 &mut self,
3113 now: Instant,
3114 space: SpaceId,
3115 path: PathId,
3116 newly_acked_pn: u64,
3117 ecn: frame::EcnCounts,
3118 largest_sent_time: Instant,
3119 largest_sent_pn: u64,
3120 ) {
3121 match self.spaces[space]
3122 .for_path(path)
3123 .detect_ecn(newly_acked_pn, ecn)
3124 {
3125 Err(e) => {
3126 debug!("halting ECN due to verification failure: {}", e);
3127
3128 self.path_data_mut(path).sending_ecn = false;
3129 self.spaces[space].for_path(path).ecn_feedback = frame::EcnCounts::ZERO;
3132 }
3133 Ok(false) => {}
3134 Ok(true) => {
3135 self.path_stats.get_mut(path).congestion_events += 1;
3136 self.path_data_mut(path).congestion.on_congestion_event(
3137 now,
3138 largest_sent_time,
3139 false,
3140 true,
3141 0,
3142 largest_sent_pn,
3143 );
3144 }
3145 }
3146 }
3147
3148 fn on_packet_acked(&mut self, now: Instant, path_id: PathId, pn: u64, info: SentPacket) {
3151 let path = self.path_data_mut(path_id);
3152 let app_limited = path.app_limited;
3153 path.remove_in_flight(&info);
3154 if info.ack_eliciting && info.path_generation == path.generation() {
3155 let rtt = path.rtt;
3159 path.congestion
3160 .on_ack(now, info.time_sent, info.size.into(), pn, app_limited, &rtt);
3161 }
3162
3163 if let Some(retransmits) = info.retransmits.get() {
3165 for (id, _) in retransmits.reset_stream.iter() {
3166 self.streams.reset_acked(*id);
3167 }
3168 }
3169
3170 for frame in info.stream_frames {
3171 self.streams.received_ack_of(frame);
3172 }
3173 }
3174
3175 fn set_key_discard_timer(&mut self, now: Instant, space: SpaceKind) {
3176 let start = if self.crypto_state.has_keys(EncryptionLevel::ZeroRtt) {
3177 now
3178 } else {
3179 self.crypto_state
3180 .prev_crypto
3181 .as_ref()
3182 .expect("no previous keys")
3183 .end_packet
3184 .as_ref()
3185 .expect("update not acknowledged yet")
3186 .1
3187 };
3188
3189 self.timers.set(
3191 Timer::Conn(ConnTimer::KeyDiscard),
3192 start + self.max_pto_for_space(space) * 3,
3193 self.qlog.with_time(now),
3194 );
3195 }
3196
3197 fn on_loss_detection_timeout(&mut self, now: Instant, path_id: PathId) {
3210 if let Some((_, pn_space)) = self.loss_time_and_space(path_id) {
3211 self.detect_lost_packets(now, pn_space, path_id, false);
3213 self.set_loss_detection_timer(now, path_id);
3214 return;
3215 }
3216
3217 let Some((_, space)) = self.pto_time_and_space(now, path_id) else {
3218 debug!(%path_id, "PTO expired while unset");
3219 return;
3220 };
3221 trace!(
3222 in_flight = self.path_data(path_id).in_flight.bytes,
3223 count = self.path_data(path_id).pto_count,
3224 ?space,
3225 %path_id,
3226 "PTO fired"
3227 );
3228
3229 let count = match self.path_data(path_id).in_flight.ack_eliciting {
3230 0 => {
3233 debug_assert!(!self.peer_completed_handshake_address_validation());
3234 1
3235 }
3236 _ => 2,
3238 };
3239 let pns = self.spaces[space].for_path(path_id);
3240 pns.loss_probes = pns.loss_probes.saturating_add(count);
3241 let path_data = self.path_data_mut(path_id);
3242 path_data.pto_count = path_data.pto_count.saturating_add(1);
3243 self.set_loss_detection_timer(now, path_id);
3244 }
3245
3246 fn detect_lost_packets(
3263 &mut self,
3264 now: Instant,
3265 pn_space: SpaceId,
3266 path_id: PathId,
3267 due_to_ack: bool,
3268 ) {
3269 let mut lost_packets = Vec::<u64>::new();
3270 let mut lost_mtu_probe = None;
3271 let mut in_persistent_congestion = false;
3272 let mut size_of_lost_packets = 0u64;
3273 self.spaces[pn_space].for_path(path_id).loss_time = None;
3274
3275 let path = self.path_data(path_id);
3278 let in_flight_mtu_probe = path.mtud.in_flight_mtu_probe();
3279 let loss_delay = path
3280 .rtt
3281 .conservative()
3282 .mul_f32(self.config.time_threshold)
3283 .max(TIMER_GRANULARITY);
3284 let first_packet_after_rtt_sample = path.first_packet_after_rtt_sample;
3285
3286 let largest_acked_packet_pn = self.spaces[pn_space]
3287 .for_path(path_id)
3288 .largest_acked_packet_pn
3289 .expect("detect_lost_packets only to be called if path received at least one ACK");
3290 let packet_threshold = self.config.packet_threshold as u64;
3291
3292 let congestion_period = self
3296 .pto(SpaceKind::Data, path_id)
3297 .saturating_mul(self.config.persistent_congestion_threshold);
3298 let mut persistent_congestion_start: Option<Instant> = None;
3299 let mut prev_packet = None;
3300 let space = self.spaces[pn_space].for_path(path_id);
3301
3302 for (packet, info) in space.sent_packets.iter_range(0..largest_acked_packet_pn) {
3303 if prev_packet != Some(packet.wrapping_sub(1)) {
3304 persistent_congestion_start = None;
3306 }
3307
3308 let packet_too_old = now.saturating_duration_since(info.time_sent) >= loss_delay;
3312 if packet_too_old || largest_acked_packet_pn >= packet + packet_threshold {
3313 if Some(packet) == in_flight_mtu_probe {
3315 lost_mtu_probe = in_flight_mtu_probe;
3318 } else {
3319 lost_packets.push(packet);
3320 size_of_lost_packets += info.size as u64;
3321 if info.ack_eliciting && due_to_ack {
3322 match persistent_congestion_start {
3323 Some(start) if info.time_sent - start > congestion_period => {
3326 in_persistent_congestion = true;
3327 }
3328 None if first_packet_after_rtt_sample
3330 .is_some_and(|x| x < (pn_space.kind(), packet)) =>
3331 {
3332 persistent_congestion_start = Some(info.time_sent);
3333 }
3334 _ => {}
3335 }
3336 }
3337 }
3338 } else {
3339 if space.loss_time.is_none() {
3341 space.loss_time = Some(info.time_sent + loss_delay);
3344 }
3345 persistent_congestion_start = None;
3346 }
3347
3348 prev_packet = Some(packet);
3349 }
3350
3351 self.handle_lost_packets(
3352 pn_space,
3353 path_id,
3354 now,
3355 lost_packets,
3356 lost_mtu_probe,
3357 loss_delay,
3358 in_persistent_congestion,
3359 size_of_lost_packets,
3360 );
3361 }
3362
3363 fn discard_path(&mut self, path_id: PathId, now: Instant) {
3365 trace!(%path_id, "dropping path state");
3366 let path = self.path_data(path_id);
3367 let in_flight_mtu_probe = path.mtud.in_flight_mtu_probe();
3368
3369 let mut size_of_lost_packets = 0u64; let lost_pns: Vec<_> = self.spaces[SpaceId::Data]
3371 .for_path(path_id)
3372 .sent_packets
3373 .iter()
3374 .filter(|(pn, _info)| Some(*pn) != in_flight_mtu_probe)
3375 .map(|(pn, info)| {
3376 size_of_lost_packets += info.size as u64;
3377 pn
3378 })
3379 .collect();
3380
3381 if !lost_pns.is_empty() {
3382 trace!(
3383 %path_id,
3384 count = lost_pns.len(),
3385 lost_bytes = size_of_lost_packets,
3386 "packets lost on path abandon"
3387 );
3388 self.handle_lost_packets(
3389 SpaceId::Data,
3390 path_id,
3391 now,
3392 lost_pns,
3393 in_flight_mtu_probe,
3394 Duration::ZERO,
3395 false,
3396 size_of_lost_packets,
3397 );
3398 }
3399 let path_stats = self.path_stats(path_id).unwrap_or_default();
3402 self.path_stats.discard(&path_id);
3403 self.partial_stats += path_stats;
3404 self.paths.remove(&path_id);
3405 self.spaces[SpaceId::Data].number_spaces.remove(&path_id);
3406
3407 self.events.push_back(
3408 PathEvent::Discarded {
3409 id: path_id,
3410 path_stats: Box::new(path_stats),
3411 }
3412 .into(),
3413 );
3414 }
3415
3416 fn handle_lost_packets(
3417 &mut self,
3418 pn_space: SpaceId,
3419 path_id: PathId,
3420 now: Instant,
3421 lost_packets: Vec<u64>,
3422 lost_mtu_probe: Option<u64>,
3423 loss_delay: Duration,
3424 in_persistent_congestion: bool,
3425 size_of_lost_packets: u64,
3426 ) {
3427 debug_assert!(lost_packets.is_sorted(), "lost_packets must be sorted");
3428
3429 self.drain_lost_packets(now, pn_space, path_id);
3430
3431 if let Some(largest_lost) = lost_packets.last().cloned() {
3433 let old_bytes_in_flight = self.path_data_mut(path_id).in_flight.bytes;
3434 let largest_lost_sent = self.spaces[pn_space]
3435 .for_path(path_id)
3436 .sent_packets
3437 .get(largest_lost)
3438 .unwrap()
3439 .time_sent;
3440 let path_stats = self.path_stats.get_mut(path_id);
3441 path_stats.lost_packets += lost_packets.len() as u64;
3442 path_stats.lost_bytes += size_of_lost_packets;
3443 trace!(
3444 %path_id,
3445 count = lost_packets.len(),
3446 lost_bytes = size_of_lost_packets,
3447 "packets lost",
3448 );
3449
3450 for &packet in &lost_packets {
3451 let Some(info) = self.spaces[pn_space].for_path(path_id).take(packet) else {
3452 continue;
3453 };
3454 self.qlog
3455 .emit_packet_lost(packet, &info, loss_delay, pn_space.kind(), now);
3456 self.paths
3457 .get_mut(&path_id)
3458 .unwrap()
3459 .remove_in_flight(&info);
3460
3461 for frame in info.stream_frames {
3462 self.streams.retransmit(frame);
3463 }
3464 self.spaces[pn_space].pending |= info.retransmits;
3465 let path = self.path_data_mut(path_id);
3466 path.pending |= info.path_retransmits;
3467 path.mtud.on_non_probe_lost(packet, info.size);
3468 path.congestion.on_packet_lost(info.size, packet, now);
3469
3470 self.spaces[pn_space].for_path(path_id).lost_packets.insert(
3471 packet,
3472 LostPacket {
3473 time_sent: info.time_sent,
3474 },
3475 );
3476 }
3477
3478 let path = self.path_data_mut(path_id);
3479 if path.mtud.black_hole_detected(now) {
3480 path.congestion.on_mtu_update(path.mtud.current_mtu());
3481 if let Some(max_datagram_size) = self.datagrams().max_size()
3482 && self.datagrams.drop_oversized(max_datagram_size)
3483 && self.datagrams.send_blocked
3484 {
3485 self.datagrams.send_blocked = false;
3486 self.events.push_back(Event::DatagramsUnblocked);
3487 }
3488 self.path_stats.get_mut(path_id).black_holes_detected += 1;
3489 }
3490
3491 let lost_ack_eliciting =
3493 old_bytes_in_flight != self.path_data_mut(path_id).in_flight.bytes;
3494
3495 if lost_ack_eliciting {
3496 self.path_stats.get_mut(path_id).congestion_events += 1;
3497 self.path_data_mut(path_id).congestion.on_congestion_event(
3498 now,
3499 largest_lost_sent,
3500 in_persistent_congestion,
3501 false,
3502 size_of_lost_packets,
3503 largest_lost,
3504 );
3505 }
3506 }
3507
3508 if let Some(packet) = lost_mtu_probe {
3510 let info = self.spaces[SpaceId::Data]
3511 .for_path(path_id)
3512 .take(packet)
3513 .unwrap(); self.paths
3516 .get_mut(&path_id)
3517 .unwrap()
3518 .remove_in_flight(&info);
3519 self.path_data_mut(path_id).mtud.on_probe_lost();
3520 self.path_stats.get_mut(path_id).lost_plpmtud_probes += 1;
3521 }
3522 }
3523
3524 fn loss_time_and_space(&self, path_id: PathId) -> Option<(Instant, SpaceId)> {
3530 SpaceId::iter()
3531 .filter_map(|id| {
3532 self.spaces[id]
3533 .number_spaces
3534 .get(&path_id)
3535 .and_then(|pns| pns.loss_time)
3536 .map(|time| (time, id))
3537 })
3538 .min_by_key(|&(time, _)| time)
3539 }
3540
3541 fn pto_time_and_space(&mut self, now: Instant, path_id: PathId) -> Option<(Instant, SpaceId)> {
3549 let path = self.path(path_id)?;
3550 let pto_count = path.pto_count;
3551
3552 let max_interval = if path.rtt.get() > SLOW_RTT_THRESHOLD {
3554 (path.rtt.get() * 3) / 2
3556 } else if let Some(idle) = path.idle_timeout.or(self.idle_timeout)
3557 && idle <= MIN_IDLE_FOR_FAST_PTO
3558 {
3559 MAX_PTO_FAST_INTERVAL
3562 } else {
3563 MAX_PTO_INTERVAL
3565 };
3566
3567 if path_id == PathId::ZERO
3568 && path.in_flight.ack_eliciting == 0
3569 && !self.peer_completed_handshake_address_validation()
3570 {
3571 let space = match self.highest_space {
3577 SpaceKind::Handshake => SpaceId::Handshake,
3578 _ => SpaceId::Initial,
3579 };
3580
3581 let backoff = 2u32.pow(path.pto_count.min(MAX_BACKOFF_EXPONENT));
3582 let duration = path.rtt.pto_base() * backoff;
3583 let duration = duration.min(max_interval);
3584 return Some((now + duration, space));
3585 }
3586
3587 let mut result = None;
3588 for space in SpaceId::iter() {
3589 let Some(pns) = self.spaces[space].number_spaces.get(&path_id) else {
3590 continue;
3591 };
3592
3593 if space == SpaceId::Data && !self.is_handshake_confirmed() {
3594 continue;
3598 }
3599
3600 if !pns.has_in_flight() {
3601 continue;
3602 }
3603
3604 let duration = {
3609 let max_ack_delay = if space == SpaceId::Data {
3610 self.ack_frequency.max_ack_delay_for_pto()
3611 } else {
3612 Duration::ZERO
3613 };
3614 let pto_base = path.rtt.pto_base() + max_ack_delay;
3615 let mut duration = pto_base;
3616 for i in 1..=pto_count {
3617 let exponential_duration = pto_base * 2u32.pow(i.min(MAX_BACKOFF_EXPONENT));
3618 let max_duration = duration + max_interval;
3619 duration = exponential_duration.min(max_duration);
3620 }
3621 duration
3622 };
3623
3624 let Some(last_ack_eliciting) = pns.time_of_last_ack_eliciting_packet else {
3625 continue;
3626 };
3627 let pto = last_ack_eliciting + duration;
3630 if result.is_none_or(|(earliest_pto, _)| pto < earliest_pto) {
3631 if path.anti_amplification_blocked(1) {
3632 continue;
3634 }
3635 if path.in_flight.ack_eliciting == 0 {
3636 continue;
3638 }
3639 result = Some((pto, space));
3640 }
3641 }
3642 result
3643 }
3644
3645 fn peer_completed_handshake_address_validation(&self) -> bool {
3647 if self.side.is_server() || self.state.is_closed() {
3648 return true;
3649 }
3650 self.spaces[SpaceId::Handshake]
3654 .path_space(PathId::ZERO)
3655 .and_then(|pns| pns.largest_acked_packet_pn)
3656 .is_some()
3657 || self.spaces[SpaceId::Data]
3658 .path_space(PathId::ZERO)
3659 .and_then(|pns| pns.largest_acked_packet_pn)
3660 .is_some()
3661 || (self.crypto_state.has_keys(EncryptionLevel::OneRtt)
3662 && !self.crypto_state.has_keys(EncryptionLevel::Handshake))
3663 }
3664
3665 fn set_loss_detection_timer(&mut self, now: Instant, path_id: PathId) {
3673 if self.state.is_closed() {
3674 return;
3678 }
3679
3680 if let Some((loss_time, _)) = self.loss_time_and_space(path_id) {
3681 self.timers.set(
3683 Timer::PerPath(path_id, PathTimer::LossDetection),
3684 loss_time,
3685 self.qlog.with_time(now),
3686 );
3687 return;
3688 }
3689
3690 if !self.abandoned_paths.contains(&path_id)
3693 && let Some((timeout, _)) = self.pto_time_and_space(now, path_id)
3694 {
3695 self.timers.set(
3696 Timer::PerPath(path_id, PathTimer::LossDetection),
3697 timeout,
3698 self.qlog.with_time(now),
3699 );
3700 } else {
3701 self.timers.stop(
3702 Timer::PerPath(path_id, PathTimer::LossDetection),
3703 self.qlog.with_time(now),
3704 );
3705 }
3706 }
3707
3708 fn max_pto_for_space(&self, space: SpaceKind) -> Duration {
3712 self.paths
3713 .keys()
3714 .map(|path_id| self.pto(space, *path_id))
3715 .max()
3716 .unwrap_or_else(|| {
3717 let rtt = self.config.initial_rtt;
3721 let max_ack_delay = match space {
3722 SpaceKind::Initial | SpaceKind::Handshake => Duration::ZERO,
3723 SpaceKind::Data => self.ack_frequency.max_ack_delay_for_pto(),
3724 };
3725 rtt + cmp::max(4 * (rtt / 2), TIMER_GRANULARITY) + max_ack_delay
3726 })
3727 }
3728
3729 fn pto(&self, space: SpaceKind, path_id: PathId) -> Duration {
3734 let max_ack_delay = match space {
3735 SpaceKind::Initial | SpaceKind::Handshake => Duration::ZERO,
3736 SpaceKind::Data => self.ack_frequency.max_ack_delay_for_pto(),
3737 };
3738 self.path_data(path_id).rtt.pto_base() + max_ack_delay
3739 }
3740
3741 fn on_packet_authenticated(
3742 &mut self,
3743 now: Instant,
3744 space_id: SpaceKind,
3745 path_id: PathId,
3746 ecn: Option<EcnCodepoint>,
3747 packet_number: Option<u64>,
3748 spin: bool,
3749 is_1rtt: bool,
3750 remote: &FourTuple,
3751 ) {
3752 let is_on_path = self
3759 .path_data(path_id)
3760 .network_path
3761 .is_probably_same_path(remote);
3762
3763 self.total_authed_packets += 1;
3764 self.reset_keep_alive(path_id, now);
3765 self.reset_idle_timeout(now, space_id, path_id);
3766 self.path_data_mut(path_id).permit_idle_reset = true;
3767
3768 if is_on_path {
3771 self.receiving_ecn |= ecn.is_some();
3772 if let Some(x) = ecn {
3773 let space = &mut self.spaces[space_id];
3774 space.for_path(path_id).ecn_counters += x;
3775
3776 if x.is_ce() {
3777 space
3778 .for_path(path_id)
3779 .pending_acks
3780 .set_immediate_ack_required();
3781 }
3782 }
3783 }
3784
3785 let Some(packet_number) = packet_number else {
3786 return;
3787 };
3788 match &self.side {
3789 ConnectionSide::Client { .. } => {
3790 if space_id == SpaceKind::Handshake
3794 && let Some(hs) = self.state.as_handshake_mut()
3795 {
3796 hs.allow_server_migration = false;
3797 }
3798 }
3799 ConnectionSide::Server { .. } => {
3800 if self.crypto_state.has_keys(EncryptionLevel::Initial)
3801 && space_id == SpaceKind::Handshake
3802 {
3803 self.discard_space(now, SpaceKind::Initial);
3805 }
3806 if self.crypto_state.has_keys(EncryptionLevel::ZeroRtt) && is_1rtt {
3807 self.set_key_discard_timer(now, space_id)
3809 }
3810 }
3811 }
3812 let space = self.spaces[space_id].for_path(path_id);
3813
3814 space.pending_acks.insert_one(packet_number, now);
3815 if packet_number >= space.largest_received_packet_number.unwrap_or_default() {
3816 space.largest_received_packet_number = Some(packet_number);
3817
3818 if is_on_path {
3820 self.spin = self.side.is_client() ^ spin;
3821 }
3822 }
3823 }
3824
3825 fn reset_idle_timeout(&mut self, now: Instant, space: SpaceKind, path_id: PathId) {
3830 if let Some(timeout) = self.idle_timeout {
3832 if self.state.is_closed() {
3833 self.timers
3834 .stop(Timer::Conn(ConnTimer::Idle), self.qlog.with_time(now));
3835 } else {
3836 let dt = cmp::max(timeout, 3 * self.max_pto_for_space(space));
3837 self.timers.set(
3838 Timer::Conn(ConnTimer::Idle),
3839 now + dt,
3840 self.qlog.with_time(now),
3841 );
3842 }
3843 }
3844
3845 if let Some(timeout) = self.path_data(path_id).idle_timeout {
3847 if self.state.is_closed() {
3848 self.timers.stop(
3849 Timer::PerPath(path_id, PathTimer::PathIdle),
3850 self.qlog.with_time(now),
3851 );
3852 } else {
3853 let dt = cmp::max(timeout, 3 * self.pto(space, path_id));
3854 self.timers.set(
3855 Timer::PerPath(path_id, PathTimer::PathIdle),
3856 now + dt,
3857 self.qlog.with_time(now),
3858 );
3859 }
3860 }
3861 }
3862
3863 fn reset_keep_alive(&mut self, path_id: PathId, now: Instant) {
3865 if !self.state.is_established() {
3866 return;
3867 }
3868
3869 if let Some(interval) = self.config.keep_alive_interval {
3870 self.timers.set(
3871 Timer::Conn(ConnTimer::KeepAlive),
3872 now + interval,
3873 self.qlog.with_time(now),
3874 );
3875 }
3876
3877 if let Some(interval) = self.path_data(path_id).keep_alive {
3878 self.timers.set(
3879 Timer::PerPath(path_id, PathTimer::PathKeepAlive),
3880 now + interval,
3881 self.qlog.with_time(now),
3882 );
3883 }
3884 }
3885
3886 fn reset_cid_retirement(&mut self, now: Instant) {
3888 if let Some((_path, t)) = self.next_cid_retirement() {
3889 self.timers.set(
3890 Timer::Conn(ConnTimer::PushNewCid),
3891 t,
3892 self.qlog.with_time(now),
3893 );
3894 }
3895 }
3896
3897 fn next_cid_retirement(&self) -> Option<(PathId, Instant)> {
3899 self.local_cid_state
3900 .iter()
3901 .filter_map(|(path_id, cid_state)| cid_state.next_timeout().map(|t| (*path_id, t)))
3902 .min_by_key(|(_path_id, timeout)| *timeout)
3903 }
3904
3905 pub(crate) fn handle_first_packet(
3910 &mut self,
3911 now: Instant,
3912 network_path: FourTuple,
3913 ecn: Option<EcnCodepoint>,
3914 packet_number: u64,
3915 packet: InitialPacket,
3916 remaining: Option<BytesMut>,
3917 ) -> Result<(), ConnectionError> {
3918 let span = trace_span!("first recv");
3919 let _guard = span.enter();
3920 debug_assert!(self.side.is_server());
3921 let len = packet.header_data.len() + packet.payload.len();
3922 let path_id = PathId::ZERO;
3923 self.path_data_mut(path_id).total_recvd = len as u64;
3924
3925 if let Some(hs) = self.state.as_handshake_mut() {
3926 hs.expected_token = packet.header.token.clone();
3927 } else {
3928 unreachable!("first packet must be delivered in Handshake state");
3929 }
3930
3931 self.on_packet_authenticated(
3933 now,
3934 SpaceKind::Initial,
3935 path_id,
3936 ecn,
3937 Some(packet_number),
3938 false,
3939 false,
3940 &network_path,
3941 );
3942
3943 let packet: Packet = packet.into();
3944
3945 let mut qlog = QlogRecvPacket::new(len);
3946 qlog.header(&packet.header, Some(packet_number), path_id);
3947
3948 self.process_decrypted_packet(
3949 now,
3950 network_path,
3951 path_id,
3952 Some(packet_number),
3953 packet,
3954 &mut qlog,
3955 )?;
3956 self.qlog.emit_packet_received(qlog, now);
3957 if let Some(data) = remaining {
3958 self.handle_coalesced(now, network_path, path_id, ecn, data);
3959 }
3960
3961 self.qlog.emit_recovery_metrics(
3962 path_id,
3963 &mut self
3964 .paths
3965 .get_mut(&path_id)
3966 .expect("path_id was supplied by the caller for an active path")
3967 .data,
3968 now,
3969 );
3970
3971 Ok(())
3972 }
3973
3974 fn init_0rtt(&mut self, now: Instant) {
3975 let Some((header, packet)) = self.crypto_state.session.early_crypto() else {
3976 return;
3977 };
3978 if self.side.is_client() {
3979 match self.crypto_state.session.transport_parameters() {
3980 Ok(params) => {
3981 let params = params
3982 .expect("crypto layer didn't supply transport parameters with ticket");
3983 let params = TransportParameters {
3985 initial_src_cid: None,
3986 original_dst_cid: None,
3987 preferred_address: None,
3988 retry_src_cid: None,
3989 stateless_reset_token: None,
3990 min_ack_delay: None,
3991 ack_delay_exponent: TransportParameters::default().ack_delay_exponent,
3992 max_ack_delay: TransportParameters::default().max_ack_delay,
3993 initial_max_path_id: None,
3994 ..params
3995 };
3996 self.set_peer_params(params);
3997 self.qlog.emit_peer_transport_params_restored(self, now);
3998 }
3999 Err(e) => {
4000 error!("session ticket has malformed transport parameters: {}", e);
4001 return;
4002 }
4003 }
4004 }
4005 trace!("0-RTT enabled");
4006 self.crypto_state.enable_zero_rtt(header, packet);
4007 }
4008
4009 fn read_crypto(
4010 &mut self,
4011 space: SpaceId,
4012 crypto: &frame::Crypto,
4013 payload_len: usize,
4014 ) -> Result<(), TransportError> {
4015 let expected = if !self.state.is_handshake() {
4016 SpaceId::Data
4017 } else if self.highest_space == SpaceKind::Initial {
4018 SpaceId::Initial
4019 } else {
4020 SpaceId::Handshake
4023 };
4024 debug_assert!(space <= expected, "received out-of-order CRYPTO data");
4028
4029 let end = crypto.offset + crypto.data.len() as u64;
4030 if space < expected
4031 && end
4032 > self.crypto_state.spaces[space.kind()]
4033 .crypto_stream
4034 .bytes_read()
4035 {
4036 warn!(
4037 "received new {:?} CRYPTO data when expecting {:?}",
4038 space, expected
4039 );
4040 return Err(TransportError::PROTOCOL_VIOLATION(
4041 "new data at unexpected encryption level",
4042 ));
4043 }
4044
4045 let crypto_space = &mut self.crypto_state.spaces[space.kind()];
4046 let max = end.saturating_sub(crypto_space.crypto_stream.bytes_read());
4047 if max > self.config.crypto_buffer_size as u64 {
4048 return Err(TransportError::CRYPTO_BUFFER_EXCEEDED(""));
4049 }
4050
4051 crypto_space
4052 .crypto_stream
4053 .insert(crypto.offset, crypto.data.clone(), payload_len);
4054 while let Some(chunk) = crypto_space.crypto_stream.read(usize::MAX, true) {
4055 trace!("consumed {} CRYPTO bytes", chunk.bytes.len());
4056 if self.crypto_state.session.read_handshake(&chunk.bytes)? {
4057 self.events.push_back(Event::HandshakeDataReady);
4058 }
4059 }
4060
4061 Ok(())
4062 }
4063
4064 fn write_crypto(&mut self) {
4065 loop {
4066 let space = self.highest_space;
4067 let mut outgoing = Vec::new();
4068 if let Some(crypto) = self.crypto_state.session.write_handshake(&mut outgoing) {
4069 match space {
4070 SpaceKind::Initial => {
4071 self.upgrade_crypto(SpaceKind::Handshake, crypto);
4072 }
4073 SpaceKind::Handshake => {
4074 self.upgrade_crypto(SpaceKind::Data, crypto);
4075 }
4076 SpaceKind::Data => unreachable!("got updated secrets during 1-RTT"),
4077 }
4078 }
4079 if outgoing.is_empty() {
4080 if space == self.highest_space {
4081 break;
4082 } else {
4083 continue;
4085 }
4086 }
4087 let offset = self.crypto_state.spaces[space].crypto_offset;
4088 let outgoing = Bytes::from(outgoing);
4089 if let Some(hs) = self.state.as_handshake_mut()
4090 && space == SpaceKind::Initial
4091 && offset == 0
4092 && self.side.is_client()
4093 {
4094 hs.client_hello = Some(outgoing.clone());
4095 }
4096 self.crypto_state.spaces[space].crypto_offset += outgoing.len() as u64;
4097 trace!("wrote {} {:?} CRYPTO bytes", outgoing.len(), space);
4098 self.spaces[space].pending.crypto.push_back(frame::Crypto {
4099 offset,
4100 data: outgoing,
4101 });
4102 }
4103 }
4104
4105 fn upgrade_crypto(&mut self, space: SpaceKind, crypto: Keys) {
4107 debug_assert!(
4108 !self.crypto_state.has_keys(space.encryption_level()),
4109 "already reached packet space {space:?}"
4110 );
4111 trace!("{:?} keys ready", space);
4112 if space == SpaceKind::Data {
4113 self.crypto_state.next_crypto = Some(
4115 self.crypto_state
4116 .session
4117 .next_1rtt_keys()
4118 .expect("handshake should be complete"),
4119 );
4120 }
4121
4122 self.crypto_state.spaces[space].keys = Some(crypto);
4123 debug_assert!(space > self.highest_space);
4124 self.highest_space = space;
4125 if space == SpaceKind::Data && self.side.is_client() {
4126 self.crypto_state.discard_zero_rtt();
4128 }
4129 }
4130
4131 fn discard_space(&mut self, now: Instant, space: SpaceKind) {
4132 debug_assert!(space != SpaceKind::Data);
4133 trace!("discarding {:?} keys", space);
4134 if space == SpaceKind::Initial {
4135 if let ConnectionSide::Client { token, .. } = &mut self.side {
4137 *token = Bytes::new();
4138 }
4139 }
4140 self.crypto_state.spaces[space].keys = None;
4141 let space = &mut self.spaces[space];
4142 let pns = space.for_path(PathId::ZERO);
4143 pns.time_of_last_ack_eliciting_packet = None;
4144 pns.loss_time = None;
4145 pns.loss_probes = 0;
4146 let sent_packets = mem::take(&mut pns.sent_packets);
4147 let path = self
4148 .paths
4149 .get_mut(&PathId::ZERO)
4150 .expect("PathId::ZERO is alive while Initial/Handshake spaces exist");
4151 for (_, packet) in sent_packets.into_iter() {
4152 path.data.remove_in_flight(&packet);
4153 }
4154
4155 self.set_loss_detection_timer(now, PathId::ZERO)
4156 }
4157
4158 fn handle_coalesced(
4159 &mut self,
4160 now: Instant,
4161 network_path: FourTuple,
4162 path_id: PathId,
4163 ecn: Option<EcnCodepoint>,
4164 data: BytesMut,
4165 ) {
4166 self.path_data_mut(path_id)
4167 .inc_total_recvd(data.len() as u64);
4168 let mut remaining = Some(data);
4169 let cid_len = self
4170 .local_cid_state
4171 .values()
4172 .map(|cid_state| cid_state.cid_len())
4173 .next()
4174 .expect("one cid_state must exist");
4175 while let Some(data) = remaining {
4176 match PartialDecode::new(
4177 data,
4178 &FixedLengthConnectionIdParser::new(cid_len),
4179 &[self.version],
4180 self.endpoint_config.grease_quic_bit,
4181 ) {
4182 Ok((partial_decode, rest)) => {
4183 remaining = rest;
4184 self.handle_decode(now, network_path, path_id, ecn, partial_decode);
4185 }
4186 Err(e) => {
4187 trace!("malformed header: {}", e);
4188 return;
4189 }
4190 }
4191 }
4192 }
4193
4194 fn handle_decode(
4200 &mut self,
4201 now: Instant,
4202 network_path: FourTuple,
4203 path_id: PathId,
4204 ecn: Option<EcnCodepoint>,
4205 partial_decode: PartialDecode,
4206 ) {
4207 let qlog = QlogRecvPacket::new(partial_decode.len());
4208 if let Some(decoded) = self
4209 .crypto_state
4210 .unprotect_header(partial_decode, self.peer_params.stateless_reset_token)
4211 {
4212 self.handle_packet(
4213 now,
4214 network_path,
4215 path_id,
4216 ecn,
4217 decoded.packet,
4218 decoded.stateless_reset,
4219 qlog,
4220 );
4221 }
4222 }
4223
4224 fn handle_packet(
4231 &mut self,
4232 now: Instant,
4233 network_path: FourTuple,
4234 path_id: PathId,
4235 ecn: Option<EcnCodepoint>,
4236 packet: Option<Packet>,
4237 stateless_reset: bool,
4238 mut qlog: QlogRecvPacket,
4239 ) {
4240 if let Some(ref packet) = packet {
4241 trace!(
4242 "got {:?} packet ({} bytes) from {} using id {}",
4243 packet.header.space(),
4244 packet.payload.len() + packet.header_data.len(),
4245 network_path,
4246 packet.header.dst_cid(),
4247 );
4248 }
4249
4250 let was_closed = self.state.is_closed();
4251 let was_drained = self.state.is_drained();
4252
4253 let decrypted = match packet {
4255 None => Err(None),
4256 Some(mut packet) => self
4257 .decrypt_packet(now, path_id, &mut packet)
4258 .map(move |number| (packet, number)),
4259 };
4260 let result = match decrypted {
4261 _ if stateless_reset => {
4262 debug!("got stateless reset");
4263 Err(ConnectionError::Reset)
4264 }
4265 Err(Some(e)) => {
4266 warn!("illegal packet: {}", e);
4267 Err(e.into())
4268 }
4269 Err(None) => {
4270 debug!("failed to authenticate packet");
4271 self.authentication_failures += 1;
4272 let integrity_limit = self
4273 .crypto_state
4274 .integrity_limit(self.highest_space)
4275 .unwrap();
4276 if self.authentication_failures > integrity_limit {
4277 Err(TransportError::AEAD_LIMIT_REACHED("integrity limit violated").into())
4278 } else {
4279 return;
4280 }
4281 }
4282 Ok((packet, pn)) => {
4283 qlog.header(&packet.header, pn, path_id);
4285 let span = match pn {
4286 Some(pn) => trace_span!("recv", space = ?packet.header.space(), pn),
4287 None => trace_span!("recv", space = ?packet.header.space()),
4288 };
4289 let _guard = span.enter();
4290
4291 if self.is_handshaking()
4299 && self
4300 .path(path_id)
4301 .map(|path_data| {
4302 !path_data.network_path.is_probably_same_path(&network_path)
4303 })
4304 .unwrap_or(false)
4305 {
4306 if let Some(hs) = self.state.as_handshake()
4307 && hs.allow_server_migration
4308 {
4309 trace!(
4310 %network_path,
4311 prev = %self.path_data(path_id).network_path,
4312 "server migrated to new remote",
4313 );
4314 self.path_data_mut(path_id).network_path = network_path;
4315 self.qlog.emit_tuple_assigned(path_id, network_path, now);
4316 } else {
4317 debug!(
4318 recv_path = %network_path,
4319 expected_path = %self.path_data_mut(path_id).network_path,
4320 "discarding packet with unexpected remote during handshake",
4321 );
4322 return;
4323 }
4324 }
4325
4326 let dedup = self.spaces[packet.header.space()]
4327 .path_space_mut(path_id)
4328 .map(|pns| &mut pns.dedup);
4329 if pn.zip(dedup).is_some_and(|(n, d)| d.insert(n)) {
4330 debug!("discarding possible duplicate packet");
4331 self.qlog.emit_packet_received(qlog, now);
4332 return;
4333 } else if self.state.is_handshake() && packet.header.is_short() {
4334 trace!("dropping short packet during handshake");
4336 self.qlog.emit_packet_received(qlog, now);
4337 return;
4338 } else {
4339 if let Header::Initial(InitialHeader { ref token, .. }) = packet.header
4340 && let Some(hs) = self.state.as_handshake()
4341 && self.side.is_server()
4342 && token != &hs.expected_token
4343 {
4344 warn!("discarding Initial with invalid retry token");
4348 self.qlog.emit_packet_received(qlog, now);
4349 return;
4350 }
4351
4352 if !self.state.is_closed() {
4353 let spin = match packet.header {
4354 Header::Short { spin, .. } => spin,
4355 _ => false,
4356 };
4357
4358 if self.side().is_server() && !self.abandoned_paths.contains(&path_id) {
4359 self.create_path(path_id, network_path, now, pn);
4361 }
4362 if self.paths.contains_key(&path_id) {
4363 self.on_packet_authenticated(
4364 now,
4365 packet.header.space(),
4366 path_id,
4367 ecn,
4368 pn,
4369 spin,
4370 packet.header.is_1rtt(),
4371 &network_path,
4372 );
4373 }
4374 }
4375
4376 let res = self.process_decrypted_packet(
4377 now,
4378 network_path,
4379 path_id,
4380 pn,
4381 packet,
4382 &mut qlog,
4383 );
4384
4385 self.qlog.emit_packet_received(qlog, now);
4386 res
4387 }
4388 }
4389 };
4390
4391 if let Err(conn_err) = result {
4393 match conn_err {
4394 ConnectionError::ApplicationClosed(reason) => self.state.move_to_closed(reason),
4395 ConnectionError::ConnectionClosed(reason) => self.state.move_to_closed(reason),
4396 ConnectionError::Reset
4397 | ConnectionError::TransportError(TransportError {
4398 code: TransportErrorCode::AEAD_LIMIT_REACHED,
4399 ..
4400 }) => {
4401 if !self.state.is_drained() {
4402 self.state
4403 .move_to_drained(Some(conn_err), &mut self.endpoint_events);
4404 }
4405 }
4406 ConnectionError::TimedOut => {
4407 unreachable!("timeouts aren't generated by packet processing");
4408 }
4409 ConnectionError::TransportError(err) => {
4410 debug!("closing connection due to transport error: {}", err);
4411 self.state.move_to_closed(err);
4412 }
4413 ConnectionError::VersionMismatch => {
4414 self.state
4415 .move_to_draining(Some(conn_err), &mut self.endpoint_events);
4416 }
4417 ConnectionError::LocallyClosed => {
4418 unreachable!("LocallyClosed isn't generated by packet processing");
4419 }
4420 ConnectionError::CidsExhausted => {
4421 unreachable!("CidsExhausted isn't generated by packet processing");
4422 }
4423 };
4424 }
4425
4426 if !was_closed && self.state.is_closed() {
4427 self.close_common();
4428 if !self.state.is_drained() {
4429 self.set_close_timer(now);
4430 }
4431 }
4432 if !was_drained && self.state.is_drained() {
4433 self.timers
4436 .stop(Timer::Conn(ConnTimer::Close), self.qlog.with_time(now));
4437 }
4438
4439 if matches!(self.state.as_type(), StateType::Closed) {
4446 if self
4464 .paths
4465 .get(&path_id)
4466 .map(|p| p.data.validated && p.data.network_path == network_path)
4467 .unwrap_or(false)
4468 {
4469 self.connection_close_pending = true;
4470 }
4471 }
4472 }
4473
4474 fn process_decrypted_packet(
4475 &mut self,
4476 now: Instant,
4477 network_path: FourTuple,
4478 path_id: PathId,
4479 number: Option<u64>,
4480 packet: Packet,
4481 qlog: &mut QlogRecvPacket,
4482 ) -> Result<(), ConnectionError> {
4483 if !self.paths.contains_key(&path_id) {
4484 trace!(%path_id, ?number, "discarding packet for unknown path");
4488 return Ok(());
4489 }
4490 let state = match self.state.as_type() {
4491 StateType::Established => {
4492 match packet.header.space() {
4493 SpaceKind::Data => self.process_payload(
4494 now,
4495 network_path,
4496 path_id,
4497 number.unwrap(),
4498 packet,
4499 qlog,
4500 )?,
4501 _ if packet.header.has_frames() => {
4502 self.process_early_payload(now, path_id, packet, qlog)?
4503 }
4504 _ => {
4505 trace!("discarding unexpected pre-handshake packet");
4506 }
4507 }
4508 return Ok(());
4509 }
4510 StateType::Closed => {
4511 for result in frame::Iter::new(packet.payload.freeze())? {
4512 let frame = match result {
4513 Ok(frame) => frame,
4514 Err(err) => {
4515 debug!("frame decoding error: {err:?}");
4516 continue;
4517 }
4518 };
4519 qlog.frame(&frame);
4520
4521 if let Frame::Padding = frame {
4522 continue;
4523 };
4524
4525 trace!(?frame, "processing frame in closed state");
4526
4527 self.path_stats.get_mut(path_id).frame_rx.record(frame.ty());
4528
4529 if let Frame::Close(_error) = frame {
4530 self.state.move_to_draining(None, &mut self.endpoint_events);
4531 break;
4532 }
4533 }
4534 return Ok(());
4535 }
4536 StateType::Draining | StateType::Drained => return Ok(()),
4537 StateType::Handshake => self.state.as_handshake_mut().expect("checked"),
4538 };
4539
4540 match packet.header {
4541 Header::Retry {
4542 src_cid: remote_cid,
4543 ..
4544 } => {
4545 debug_assert_eq!(path_id, PathId::ZERO);
4546 if self.side.is_server() {
4547 return Err(TransportError::PROTOCOL_VIOLATION("client sent Retry").into());
4548 }
4549
4550 let is_valid_retry = self
4551 .remote_cids
4552 .get(&path_id)
4553 .map(|cids| cids.active())
4554 .map(|orig_dst_cid| {
4555 self.crypto_state.session.is_valid_retry(
4556 orig_dst_cid,
4557 &packet.header_data,
4558 &packet.payload,
4559 )
4560 })
4561 .unwrap_or_default();
4562 if self.total_authed_packets > 1
4563 || packet.payload.len() <= 16 || !is_valid_retry
4565 {
4566 trace!("discarding invalid Retry");
4567 return Ok(());
4575 }
4576
4577 trace!("retrying with CID {}", remote_cid);
4578 let client_hello = state.client_hello.take().unwrap();
4579 self.retry_src_cid = Some(remote_cid);
4580 self.remote_cids
4581 .get_mut(&path_id)
4582 .expect("PathId::ZERO not yet abandoned, is_valid_retry would have been false")
4583 .update_initial_cid(remote_cid);
4584 self.remote_handshake_cid = remote_cid;
4585
4586 let space = &mut self.spaces[SpaceId::Initial];
4587 if let Some(info) = space.for_path(PathId::ZERO).take(0) {
4588 self.on_packet_acked(now, PathId::ZERO, 0, info);
4589 };
4590
4591 self.discard_space(now, SpaceKind::Initial); let crypto_space = &mut self.crypto_state.spaces[SpaceKind::Initial];
4594 crypto_space.keys = Some(
4595 self.crypto_state
4596 .session
4597 .initial_keys(remote_cid, self.side.side()),
4598 );
4599 crypto_space.crypto_offset = client_hello.len() as u64;
4600
4601 let next_pn = self.spaces[SpaceId::Initial]
4602 .for_path(path_id)
4603 .next_packet_number;
4604 self.spaces[SpaceId::Initial] = {
4605 let mut space = PacketSpace::new(now, SpaceId::Initial, &mut self.rng);
4606 space.for_path(path_id).next_packet_number = next_pn;
4607 space.pending.crypto.push_back(frame::Crypto {
4608 offset: 0,
4609 data: client_hello,
4610 });
4611 space
4612 };
4613
4614 let zero_rtt = mem::take(
4616 &mut self.spaces[SpaceId::Data]
4617 .for_path(PathId::ZERO)
4618 .sent_packets,
4619 );
4620 for (_, info) in zero_rtt.into_iter() {
4621 self.paths
4622 .get_mut(&PathId::ZERO)
4623 .unwrap()
4624 .remove_in_flight(&info);
4625 self.spaces[SpaceId::Data].pending |= info.retransmits;
4626 }
4627 self.streams.retransmit_all_for_0rtt();
4628
4629 let token_len = packet.payload.len() - 16;
4630 let ConnectionSide::Client { ref mut token, .. } = self.side else {
4631 unreachable!("we already short-circuited if we're server");
4632 };
4633 *token = packet.payload.freeze().split_to(token_len);
4634
4635 self.state = State::handshake(state::Handshake {
4636 expected_token: Bytes::new(),
4637 remote_cid_set: false,
4638 client_hello: None,
4639 allow_server_migration: self.config.server_handshake_migration,
4640 });
4641 Ok(())
4642 }
4643 Header::Long {
4644 ty: LongType::Handshake,
4645 src_cid: remote_cid,
4646 dst_cid: local_cid,
4647 ..
4648 } => {
4649 debug_assert_eq!(path_id, PathId::ZERO);
4650 if remote_cid != self.remote_handshake_cid {
4651 debug!(
4652 "discarding packet with mismatched remote CID: {} != {}",
4653 self.remote_handshake_cid, remote_cid
4654 );
4655 return Ok(());
4656 }
4657 self.on_path_validated(path_id);
4658
4659 self.process_early_payload(now, path_id, packet, qlog)?;
4660 if self.state.is_closed() {
4661 return Ok(());
4662 }
4663
4664 if self.crypto_state.session.is_handshaking() {
4665 trace!("handshake ongoing");
4666 return Ok(());
4667 }
4668
4669 if self.side.is_client() {
4670 let params = self
4672 .crypto_state
4673 .session
4674 .transport_parameters()?
4675 .ok_or_else(|| {
4676 TransportError::new(
4677 TransportErrorCode::crypto(0x6d),
4678 "transport parameters missing".to_owned(),
4679 )
4680 })?;
4681
4682 if self.has_0rtt() {
4683 if !self.crypto_state.session.early_data_accepted().unwrap() {
4684 debug_assert!(self.side.is_client());
4685 debug!("0-RTT rejected");
4686 self.crypto_state.accepted_0rtt = false;
4687 self.streams.zero_rtt_rejected();
4688
4689 self.spaces[SpaceId::Data].pending = Retransmits::default();
4691
4692 let sent_packets = mem::take(
4694 &mut self.spaces[SpaceId::Data].for_path(path_id).sent_packets,
4695 );
4696 for (_, packet) in sent_packets.into_iter() {
4697 self.paths
4698 .get_mut(&path_id)
4699 .unwrap()
4700 .remove_in_flight(&packet);
4701 }
4702 } else {
4703 self.crypto_state.accepted_0rtt = true;
4704 params.validate_resumption_from(&self.peer_params)?;
4705 }
4706 }
4707 if let Some(token) = params.stateless_reset_token {
4708 let remote = self.path_data(path_id).network_path.remote;
4709 debug_assert!(!self.state.is_drained()); self.endpoint_events
4711 .push_back(EndpointEventInner::ResetToken(path_id, remote, token));
4712 }
4713 self.handle_peer_params(params, local_cid, remote_cid, now)?;
4714 self.issue_first_cids(now);
4715 } else {
4716 self.spaces[SpaceId::Data].pending.handshake_done = true;
4718 self.discard_space(now, SpaceKind::Handshake);
4719 self.events.push_back(Event::HandshakeConfirmed);
4720 trace!("handshake confirmed");
4721 }
4722
4723 self.events.push_back(Event::Connected);
4724 self.state.move_to_established();
4725 trace!("established");
4726
4727 self.issue_first_path_cids(now);
4730 Ok(())
4731 }
4732 Header::Initial(InitialHeader {
4733 src_cid: remote_cid,
4734 dst_cid: local_cid,
4735 ..
4736 }) => {
4737 debug_assert_eq!(path_id, PathId::ZERO);
4738 if !state.remote_cid_set {
4739 trace!("switching remote CID to {}", remote_cid);
4740 let mut state = state.clone();
4741 self.remote_cids
4742 .get_mut(&path_id)
4743 .expect("PathId::ZERO not yet abandoned")
4744 .update_initial_cid(remote_cid);
4745 self.remote_handshake_cid = remote_cid;
4746 self.original_remote_cid = remote_cid;
4747 state.remote_cid_set = true;
4748 self.state.move_to_handshake(state);
4749 } else if remote_cid != self.remote_handshake_cid {
4750 debug!(
4751 "discarding packet with mismatched remote CID: {} != {}",
4752 self.remote_handshake_cid, remote_cid
4753 );
4754 return Ok(());
4755 }
4756
4757 let starting_space = self.highest_space;
4758 self.process_early_payload(now, path_id, packet, qlog)?;
4759
4760 if self.side.is_server()
4761 && starting_space == SpaceKind::Initial
4762 && self.highest_space != SpaceKind::Initial
4763 {
4764 let params = self
4765 .crypto_state
4766 .session
4767 .transport_parameters()?
4768 .ok_or_else(|| {
4769 TransportError::new(
4770 TransportErrorCode::crypto(0x6d),
4771 "transport parameters missing".to_owned(),
4772 )
4773 })?;
4774 self.handle_peer_params(params, local_cid, remote_cid, now)?;
4775 self.issue_first_cids(now);
4776 self.init_0rtt(now);
4777 }
4778 Ok(())
4779 }
4780 Header::Long {
4781 ty: LongType::ZeroRtt,
4782 ..
4783 } => {
4784 self.process_payload(now, network_path, path_id, number.unwrap(), packet, qlog)?;
4785 Ok(())
4786 }
4787 Header::VersionNegotiate { .. } => {
4788 if self.total_authed_packets > 1 {
4789 return Ok(());
4790 }
4791 let supported = packet
4792 .payload
4793 .chunks(4)
4794 .any(|x| match <[u8; 4]>::try_from(x) {
4795 Ok(version) => self.version == u32::from_be_bytes(version),
4796 Err(_) => false,
4797 });
4798 if supported {
4799 return Ok(());
4800 }
4801 debug!("remote doesn't support our version");
4802 Err(ConnectionError::VersionMismatch)
4803 }
4804 Header::Short { .. } => unreachable!(
4805 "short packets received during handshake are discarded in handle_packet"
4806 ),
4807 }
4808 }
4809
4810 fn process_early_payload(
4812 &mut self,
4813 now: Instant,
4814 path_id: PathId,
4815 packet: Packet,
4816 #[allow(unused)] qlog: &mut QlogRecvPacket,
4817 ) -> Result<(), TransportError> {
4818 debug_assert_ne!(packet.header.space(), SpaceKind::Data);
4819 debug_assert_eq!(path_id, PathId::ZERO);
4820 let payload_len = packet.payload.len();
4821 let mut ack_eliciting = false;
4822 for result in frame::Iter::new(packet.payload.freeze())? {
4823 let frame = result?;
4824 qlog.frame(&frame);
4825 let span = match frame {
4826 Frame::Padding => continue,
4827 _ => Some(trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty)),
4828 };
4829
4830 self.path_stats.get_mut(path_id).frame_rx.record(frame.ty());
4831
4832 let _guard = span.as_ref().map(|x| x.enter());
4833 ack_eliciting |= frame.is_ack_eliciting();
4834
4835 if frame.is_1rtt() && packet.header.space() != SpaceKind::Data {
4837 return Err(TransportError::PROTOCOL_VIOLATION(
4838 "illegal frame type in handshake",
4839 ));
4840 }
4841
4842 match frame {
4843 Frame::Padding | Frame::Ping => {}
4844 Frame::Crypto(frame) => {
4845 self.read_crypto(packet.header.space().into(), &frame, payload_len)?;
4846 }
4847 Frame::Ack(ack) => {
4848 self.on_ack_received(now, packet.header.space().into(), ack)?;
4849 }
4850 Frame::PathAck(ack) => {
4851 span.as_ref()
4852 .map(|span| span.record("path", tracing::field::display(&ack.path_id)));
4853 self.on_path_ack_received(now, packet.header.space().into(), ack)?;
4854 }
4855 Frame::Close(reason) => {
4856 self.state
4857 .move_to_draining(Some(reason.into()), &mut self.endpoint_events);
4858 return Ok(());
4859 }
4860 _ => {
4861 let mut err =
4862 TransportError::PROTOCOL_VIOLATION("illegal frame type in handshake");
4863 err.frame = frame::MaybeFrame::Known(frame.ty());
4864 return Err(err);
4865 }
4866 }
4867 }
4868
4869 if ack_eliciting {
4870 self.spaces[packet.header.space()]
4872 .for_path(path_id)
4873 .pending_acks
4874 .set_immediate_ack_required();
4875 }
4876
4877 self.write_crypto();
4878 Ok(())
4879 }
4880
4881 fn process_payload(
4883 &mut self,
4884 now: Instant,
4885 network_path: FourTuple,
4886 path_id: PathId,
4887 number: u64,
4888 packet: Packet,
4889 #[allow(unused)] qlog: &mut QlogRecvPacket,
4890 ) -> Result<(), TransportError> {
4891 let payload = packet.payload.freeze();
4892 let mut is_probing_packet = true;
4893 let mut close = None;
4894 let payload_len = payload.len();
4895 let mut ack_eliciting = false;
4896 let mut migration_observed_addr = None;
4899 for result in frame::Iter::new(payload)? {
4900 let frame = result?;
4901 qlog.frame(&frame);
4902 let span = match frame {
4903 Frame::Padding => continue,
4904 _ => trace_span!("frame", ty = %frame.ty(), path = tracing::field::Empty),
4905 };
4906
4907 self.path_stats.get_mut(path_id).frame_rx.record(frame.ty());
4908 match &frame {
4911 Frame::Crypto(f) => {
4912 trace!(offset = f.offset, len = f.data.len(), "got frame CRYPTO");
4913 }
4914 Frame::Stream(f) => {
4915 trace!(id = %f.id, offset = f.offset, len = f.data.len(), fin = f.fin, "got frame STREAM");
4916 }
4917 Frame::Datagram(f) => {
4918 trace!(len = f.data.len(), "got frame DATAGRAM");
4919 }
4920 f => {
4921 trace!("got frame {f}");
4922 }
4923 }
4924
4925 let _guard = span.enter();
4926 if packet.header.is_0rtt() {
4927 match frame {
4928 Frame::Crypto(_) | Frame::Close(Close::Application(_)) => {
4929 return Err(TransportError::PROTOCOL_VIOLATION(
4930 "illegal frame type in 0-RTT",
4931 ));
4932 }
4933 _ => {
4934 if frame.is_1rtt() {
4935 return Err(TransportError::PROTOCOL_VIOLATION(
4936 "illegal frame type in 0-RTT",
4937 ));
4938 }
4939 }
4940 }
4941 }
4942 ack_eliciting |= frame.is_ack_eliciting();
4943
4944 match frame {
4946 Frame::Padding
4947 | Frame::PathChallenge(_)
4948 | Frame::PathResponse(_)
4949 | Frame::NewConnectionId(_)
4950 | Frame::ObservedAddr(_) => {}
4951 _ => {
4952 is_probing_packet = false;
4953 }
4954 }
4955
4956 match frame {
4957 Frame::Crypto(frame) => {
4958 self.read_crypto(SpaceId::Data, &frame, payload_len)?;
4959 }
4960 Frame::Stream(frame) => {
4961 if self.streams.received(frame, payload_len)?.should_transmit() {
4962 self.spaces[SpaceId::Data].pending.max_data = true;
4963 }
4964 }
4965 Frame::Ack(ack) => {
4966 self.on_ack_received(now, SpaceId::Data, ack)?;
4967 }
4968 Frame::PathAck(ack) => {
4969 if !self.is_multipath_negotiated() {
4970 return Err(TransportError::PROTOCOL_VIOLATION(
4971 "received PATH_ACK frame when multipath was not negotiated",
4972 ));
4973 }
4974 span.record("path", tracing::field::display(&ack.path_id));
4975 self.on_path_ack_received(now, SpaceId::Data, ack)?;
4976 }
4977 Frame::Padding | Frame::Ping => {}
4978 Frame::Close(reason) => {
4979 close = Some(reason);
4980 }
4981 Frame::PathChallenge(challenge) => {
4982 self.spaces[SpaceKind::Data]
4983 .for_path(path_id)
4984 .pending_path_responses
4985 .push(number, challenge.0, network_path);
4986 let path = &mut self
4990 .path_mut(path_id)
4991 .expect("payload is processed only after the path becomes known");
4992 if network_path.remote == path.network_path.remote {
4993 match self.peer_supports_ack_frequency() {
5001 true => self.immediate_ack(path_id),
5002 false => {
5003 self.ping_path(path_id).ok();
5004 }
5005 }
5006 }
5007 }
5008 Frame::PathResponse(response) => {
5009 if self
5011 .n0_nat_traversal
5012 .handle_path_response(network_path, response.0)
5013 {
5014 self.open_nat_traversed_paths(now);
5015 } else {
5016 self.handle_path_response_on_path(now, response, path_id);
5018 }
5019 }
5020 Frame::MaxData(frame::MaxData(bytes)) => {
5021 self.streams.received_max_data(bytes);
5022 }
5023 Frame::MaxStreamData(frame::MaxStreamData { id, offset }) => {
5024 self.streams.received_max_stream_data(id, offset)?;
5025 }
5026 Frame::MaxStreams(frame::MaxStreams { dir, count }) => {
5027 self.streams.received_max_streams(dir, count)?;
5028 }
5029 Frame::ResetStream(frame) => {
5030 if self.streams.received_reset(frame)?.should_transmit() {
5031 self.spaces[SpaceId::Data].pending.max_data = true;
5032 }
5033 }
5034 Frame::DataBlocked(DataBlocked(offset)) => {
5035 debug!(offset, "peer claims to be blocked at connection level");
5036 }
5037 Frame::StreamDataBlocked(StreamDataBlocked { id, offset }) => {
5038 if id.initiator() == self.side.side() && id.dir() == Dir::Uni {
5039 debug!("got STREAM_DATA_BLOCKED on send-only {}", id);
5040 return Err(TransportError::STREAM_STATE_ERROR(
5041 "STREAM_DATA_BLOCKED on send-only stream",
5042 ));
5043 }
5044 debug!(
5045 stream = %id,
5046 offset, "peer claims to be blocked at stream level"
5047 );
5048 }
5049 Frame::StreamsBlocked(StreamsBlocked { dir, limit }) => {
5050 if limit > MAX_STREAM_COUNT {
5051 return Err(TransportError::FRAME_ENCODING_ERROR(
5052 "unrepresentable stream limit",
5053 ));
5054 }
5055 debug!(
5056 "peer claims to be blocked opening more than {} {} streams",
5057 limit, dir
5058 );
5059 }
5060 Frame::StopSending(frame::StopSending { id, error_code }) => {
5061 if id.initiator() != self.side.side() {
5062 if id.dir() == Dir::Uni {
5063 debug!("got STOP_SENDING on recv-only {}", id);
5064 return Err(TransportError::STREAM_STATE_ERROR(
5065 "STOP_SENDING on recv-only stream",
5066 ));
5067 }
5068 } else if self.streams.is_local_unopened(id) {
5069 return Err(TransportError::STREAM_STATE_ERROR(
5070 "STOP_SENDING on unopened stream",
5071 ));
5072 }
5073 self.streams.received_stop_sending(id, error_code);
5074 }
5075 Frame::RetireConnectionId(frame::RetireConnectionId { path_id, sequence }) => {
5076 if let Some(ref path_id) = path_id {
5077 span.record("path", tracing::field::display(&path_id));
5078 }
5079 let path_id = path_id.unwrap_or_default();
5080 match self.local_cid_state.get_mut(&path_id) {
5081 None => debug!(?path_id, "RETIRE_CONNECTION_ID for unknown path"),
5082 Some(cid_state) => {
5083 let allow_more_cids = cid_state
5084 .on_cid_retirement(sequence, self.peer_params.issue_cids_limit())?;
5085
5086 let has_path = !self.abandoned_paths.contains(&path_id);
5090 let allow_more_cids = allow_more_cids && has_path;
5091
5092 debug_assert!(!self.state.is_drained()); self.endpoint_events
5094 .push_back(EndpointEventInner::RetireConnectionId(
5095 now,
5096 path_id,
5097 sequence,
5098 allow_more_cids,
5099 ));
5100 }
5101 }
5102 }
5103 Frame::NewConnectionId(frame) => {
5104 let path_id = if let Some(path_id) = frame.path_id {
5105 if !self.is_multipath_negotiated() {
5106 return Err(TransportError::PROTOCOL_VIOLATION(
5107 "received PATH_NEW_CONNECTION_ID frame when multipath was not negotiated",
5108 ));
5109 }
5110 if path_id > self.local_max_path_id {
5111 return Err(TransportError::PROTOCOL_VIOLATION(
5112 "PATH_NEW_CONNECTION_ID contains path_id exceeding current max",
5113 ));
5114 }
5115 path_id
5116 } else {
5117 PathId::ZERO
5118 };
5119
5120 if let Some(ref path_id) = frame.path_id {
5121 span.record("path", tracing::field::display(&path_id));
5122 }
5123
5124 if self.abandoned_paths.contains(&path_id) {
5125 trace!("ignoring issued CID for abandoned path");
5126 continue;
5127 }
5128 let remote_cids = self
5129 .remote_cids
5130 .entry(path_id)
5131 .or_insert_with(|| CidQueue::new(frame.id));
5132 if remote_cids.active().is_empty() {
5133 return Err(TransportError::PROTOCOL_VIOLATION(
5134 "NEW_CONNECTION_ID when CIDs aren't in use",
5135 ));
5136 }
5137 if frame.retire_prior_to > frame.sequence {
5138 return Err(TransportError::PROTOCOL_VIOLATION(
5139 "NEW_CONNECTION_ID retiring unissued CIDs",
5140 ));
5141 }
5142
5143 use crate::cid_queue::InsertError;
5144 match remote_cids.insert(frame) {
5145 Ok(None) => {
5146 self.open_nat_traversed_paths(now);
5147 }
5148 Ok(Some((retired, reset_token))) => {
5149 let pending_retired =
5150 &mut self.spaces[SpaceId::Data].pending.retire_cids;
5151 const MAX_PENDING_RETIRED_CIDS: u64 = CidQueue::LEN as u64 * 10;
5154 if (pending_retired.len() as u64)
5157 .saturating_add(retired.end.saturating_sub(retired.start))
5158 > MAX_PENDING_RETIRED_CIDS
5159 {
5160 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR(
5161 "queued too many retired CIDs",
5162 ));
5163 }
5164 pending_retired.extend(retired.map(|seq| (path_id, seq)));
5165 self.set_reset_token(path_id, network_path.remote, reset_token);
5166 self.open_nat_traversed_paths(now);
5167 }
5168 Err(InsertError::ExceedsLimit) => {
5169 return Err(TransportError::CONNECTION_ID_LIMIT_ERROR(""));
5170 }
5171 Err(InsertError::Retired) => {
5172 trace!("discarding already-retired");
5173 self.spaces[SpaceId::Data]
5177 .pending
5178 .retire_cids
5179 .push((path_id, frame.sequence));
5180 continue;
5181 }
5182 };
5183
5184 if self.side.is_server()
5185 && path_id == PathId::ZERO
5186 && self
5187 .remote_cids
5188 .get(&PathId::ZERO)
5189 .map(|cids| cids.active_seq() == 0)
5190 .unwrap_or_default()
5191 {
5192 self.update_remote_cid(PathId::ZERO);
5195 }
5196 }
5197 Frame::NewToken(NewToken { token }) => {
5198 let ConnectionSide::Client {
5199 token_store,
5200 server_name,
5201 ..
5202 } = &self.side
5203 else {
5204 return Err(TransportError::PROTOCOL_VIOLATION("client sent NEW_TOKEN"));
5205 };
5206 if token.is_empty() {
5207 return Err(TransportError::FRAME_ENCODING_ERROR("empty token"));
5208 }
5209 trace!("got new token");
5210 token_store.insert(server_name, token);
5211 }
5212 Frame::Datagram(datagram) => {
5213 if self
5214 .datagrams
5215 .received(datagram, &self.config.datagram_receive_buffer_size)?
5216 {
5217 self.events.push_back(Event::DatagramReceived);
5218 }
5219 }
5220 Frame::AckFrequency(ack_frequency) => {
5221 if !self.ack_frequency.ack_frequency_received(&ack_frequency)? {
5224 continue;
5227 }
5228
5229 for (path_id, space) in self.spaces[SpaceId::Data].number_spaces.iter_mut() {
5231 space.pending_acks.set_ack_frequency_params(&ack_frequency);
5232
5233 if !self.abandoned_paths.contains(path_id)
5237 && let Some(timeout) = space
5238 .pending_acks
5239 .max_ack_delay_timeout(self.ack_frequency.max_ack_delay)
5240 {
5241 self.timers.set(
5242 Timer::PerPath(*path_id, PathTimer::MaxAckDelay),
5243 timeout,
5244 self.qlog.with_time(now),
5245 );
5246 }
5247 }
5248 }
5249 Frame::ImmediateAck => {
5250 for pns in self.spaces[SpaceId::Data].iter_paths_mut() {
5252 pns.pending_acks.set_immediate_ack_required();
5253 }
5254 }
5255 Frame::HandshakeDone => {
5256 if self.side.is_server() {
5257 return Err(TransportError::PROTOCOL_VIOLATION(
5258 "client sent HANDSHAKE_DONE",
5259 ));
5260 }
5261 if self.crypto_state.has_keys(EncryptionLevel::Handshake) {
5262 self.discard_space(now, SpaceKind::Handshake);
5263 self.events.push_back(Event::HandshakeConfirmed);
5264 trace!("handshake confirmed");
5265 }
5266 }
5267 Frame::ObservedAddr(observed) => {
5268 trace!(seq_no = %observed.seq_no, ip = %observed.ip, port = observed.port);
5270 if !self
5271 .peer_params
5272 .address_discovery_role
5273 .should_report(&self.config.address_discovery_role)
5274 {
5275 return Err(TransportError::PROTOCOL_VIOLATION(
5276 "received OBSERVED_ADDRESS frame when not negotiated",
5277 ));
5278 }
5279 if packet.header.space() != SpaceKind::Data {
5281 return Err(TransportError::PROTOCOL_VIOLATION(
5282 "OBSERVED_ADDRESS frame outside data space",
5283 ));
5284 }
5285
5286 let space_open_status =
5287 self.spaces[SpaceKind::Data].for_path(path_id).open_status;
5288 let path = self.path_data_mut(path_id);
5289 if path.network_path.remote == network_path.remote {
5290 if let Some(updated) = path.update_observed_addr_report(observed)
5291 && space_open_status == OpenStatus::Informed
5292 {
5293 self.events.push_back(Event::Path(PathEvent::ObservedAddr {
5294 id: path_id,
5295 addr: updated,
5296 }));
5297 }
5299 } else {
5300 migration_observed_addr = Some(observed)
5302 }
5303 }
5304 Frame::PathAbandon(frame::PathAbandon {
5305 path_id,
5306 error_code,
5307 }) => {
5308 span.record("path", tracing::field::display(&path_id));
5309 match self.close_path_inner(
5310 now,
5311 path_id,
5312 PathAbandonReason::RemoteAbandoned {
5313 error_code: error_code.into(),
5314 },
5315 ) {
5316 Ok(()) => {
5317 trace!("peer abandoned path");
5318 }
5319 Err(ClosePathError::ClosedPath) => {
5320 trace!("peer abandoned already closed path");
5321 }
5322 Err(ClosePathError::MultipathNotNegotiated) => {
5323 return Err(TransportError::PROTOCOL_VIOLATION(
5324 "received PATH_ABANDON frame when multipath was not negotiated",
5325 ));
5326 }
5327 Err(ClosePathError::LastOpenPath) => {
5328 error!(
5331 "peer abandoned last path but close_path_inner returned LastOpenPath"
5332 );
5333 }
5334 };
5335
5336 if let Some(path) = self.paths.get_mut(&path_id)
5338 && !mem::replace(&mut path.data.draining, true)
5339 {
5340 let ack_delay = self.ack_frequency.max_ack_delay_for_pto();
5341 let pto = path.data.rtt.pto_base() + ack_delay;
5342 self.timers.set(
5343 Timer::PerPath(path_id, PathTimer::PathDrained),
5344 now + 3 * pto,
5345 self.qlog.with_time(now),
5346 );
5347
5348 self.set_max_path_id(now, self.local_max_path_id.saturating_add(1u8));
5349 }
5350 }
5351 Frame::PathStatusAvailable(info) => {
5352 span.record("path", tracing::field::display(&info.path_id));
5353 if self.is_multipath_negotiated() {
5354 self.on_path_status(
5355 info.path_id,
5356 PathStatus::Available,
5357 info.status_seq_no,
5358 );
5359 } else {
5360 return Err(TransportError::PROTOCOL_VIOLATION(
5361 "received PATH_STATUS_AVAILABLE frame when multipath was not negotiated",
5362 ));
5363 }
5364 }
5365 Frame::PathStatusBackup(info) => {
5366 span.record("path", tracing::field::display(&info.path_id));
5367 if self.is_multipath_negotiated() {
5368 self.on_path_status(info.path_id, PathStatus::Backup, info.status_seq_no);
5369 } else {
5370 return Err(TransportError::PROTOCOL_VIOLATION(
5371 "received PATH_STATUS_BACKUP frame when multipath was not negotiated",
5372 ));
5373 }
5374 }
5375 Frame::MaxPathId(frame::MaxPathId(path_id)) => {
5376 span.record("path", tracing::field::display(&path_id));
5377 if !self.is_multipath_negotiated() {
5378 return Err(TransportError::PROTOCOL_VIOLATION(
5379 "received MAX_PATH_ID frame when multipath was not negotiated",
5380 ));
5381 }
5382 if path_id > self.remote_max_path_id {
5384 self.remote_max_path_id = path_id;
5385 self.issue_first_path_cids(now);
5386 self.open_nat_traversed_paths(now);
5387 }
5388 }
5389 Frame::PathsBlocked(frame::PathsBlocked(max_path_id)) => {
5390 if self.is_multipath_negotiated() {
5394 if max_path_id > self.local_max_path_id {
5395 return Err(TransportError::PROTOCOL_VIOLATION(
5396 "PATHS_BLOCKED maximum path identifier was larger than local maximum",
5397 ));
5398 }
5399 } else {
5400 return Err(TransportError::PROTOCOL_VIOLATION(
5401 "received PATHS_BLOCKED frame when not multipath was not negotiated",
5402 ));
5403 }
5404 }
5405 Frame::PathCidsBlocked(frame::PathCidsBlocked { path_id, next_seq }) => {
5406 if self.is_multipath_negotiated() {
5414 if path_id > self.local_max_path_id {
5415 return Err(TransportError::PROTOCOL_VIOLATION(
5416 "PATH_CIDS_BLOCKED path identifier was larger than local maximum",
5417 ));
5418 }
5419 if self
5420 .local_cid_state
5421 .get(&path_id)
5422 .is_some_and(|cid_state| next_seq.0 > cid_state.active_seq().1 + 1)
5425 {
5426 return Err(TransportError::PROTOCOL_VIOLATION(
5427 "PATH_CIDS_BLOCKED next sequence number larger than in local state",
5428 ));
5429 }
5430 debug!(%path_id, %next_seq, "received PATH_CIDS_BLOCKED");
5431 } else {
5432 return Err(TransportError::PROTOCOL_VIOLATION(
5433 "received PATH_CIDS_BLOCKED frame when not multipath was not negotiated",
5434 ));
5435 }
5436 }
5437 Frame::AddAddress(addr) => {
5438 let client_state = match self.n0_nat_traversal.client_side_mut() {
5439 Ok(state) => state,
5440 Err(err) => {
5441 return Err(TransportError::PROTOCOL_VIOLATION(format!(
5442 "Nat traversal(ADD_ADDRESS): {err}"
5443 )));
5444 }
5445 };
5446
5447 if !client_state.check_remote_address(&addr) {
5448 warn!(?addr, "server sent illegal ADD_ADDRESS frame");
5450 }
5451
5452 match client_state.add_remote_address(addr) {
5453 Ok(maybe_added) => {
5454 if let Some(added) = maybe_added {
5455 self.events.push_back(Event::NatTraversal(
5456 n0_nat_traversal::Event::AddressAdded(added),
5457 ));
5458 }
5459 }
5460 Err(e) => {
5461 warn!(%e, "failed to add remote address")
5462 }
5463 }
5464 }
5465 Frame::RemoveAddress(addr) => {
5466 let client_state = match self.n0_nat_traversal.client_side_mut() {
5467 Ok(state) => state,
5468 Err(err) => {
5469 return Err(TransportError::PROTOCOL_VIOLATION(format!(
5470 "Nat traversal(REMOVE_ADDRESS): {err}"
5471 )));
5472 }
5473 };
5474 if let Some(removed_addr) = client_state.remove_remote_address(addr) {
5475 self.events.push_back(Event::NatTraversal(
5476 n0_nat_traversal::Event::AddressRemoved(removed_addr),
5477 ));
5478 }
5479 }
5480 Frame::ReachOut(reach_out) => {
5481 let ipv6 = self.is_ipv6();
5482 let server_state = match self.n0_nat_traversal.server_side_mut() {
5483 Ok(state) => state,
5484 Err(err) => {
5485 return Err(TransportError::PROTOCOL_VIOLATION(format!(
5486 "Nat traversal(REACH_OUT): {err}"
5487 )));
5488 }
5489 };
5490
5491 let round_before = server_state.current_round();
5492
5493 if let Err(err) = server_state.handle_reach_out(reach_out, ipv6) {
5494 return Err(TransportError::PROTOCOL_VIOLATION(format!(
5495 "Nat traversal(REACH_OUT): {err}"
5496 )));
5497 }
5498
5499 if server_state.current_round() > round_before {
5500 if let Some(delay) =
5502 self.n0_nat_traversal.retry_delay(self.config.initial_rtt)
5503 {
5504 self.timers.set(
5505 Timer::Conn(ConnTimer::NatTraversalProbeRetry),
5506 now + delay,
5507 self.qlog.with_time(now),
5508 );
5509 }
5510 }
5511 }
5512 }
5513 }
5514
5515 let space = self.spaces[SpaceId::Data].for_path(path_id);
5516 if space
5517 .pending_acks
5518 .packet_received(now, number, ack_eliciting, &space.dedup)
5519 {
5520 if self.abandoned_paths.contains(&path_id) {
5521 space.pending_acks.set_immediate_ack_required();
5524 } else {
5525 self.timers.set(
5526 Timer::PerPath(path_id, PathTimer::MaxAckDelay),
5527 now + self.ack_frequency.max_ack_delay,
5528 self.qlog.with_time(now),
5529 );
5530 }
5531 }
5532
5533 let pending = &mut self.spaces[SpaceId::Data].pending;
5538 self.streams.queue_max_stream_id(pending);
5539
5540 if let Some(reason) = close {
5541 self.state
5542 .move_to_draining(Some(reason.into()), &mut self.endpoint_events);
5543 self.connection_close_pending = true;
5544 }
5545
5546 let migrate_on_any_packet =
5549 self.is_multipath_negotiated() && !self.n0_nat_traversal.is_negotiated();
5550
5551 let is_largest_received_pn = Some(number)
5553 == self.spaces[SpaceId::Data]
5554 .for_path(path_id)
5555 .largest_received_packet_number;
5556
5557 if (migrate_on_any_packet || !is_probing_packet)
5562 && is_largest_received_pn
5563 && self.local_ip_may_migrate()
5564 && let Some(new_local_ip) = network_path.local_ip
5565 {
5566 let path_data = self.path_data_mut(path_id);
5567 if path_data
5568 .network_path
5569 .local_ip
5570 .is_some_and(|ip| ip != new_local_ip)
5571 {
5572 debug!(
5573 %path_id,
5574 new_4tuple = %network_path,
5575 prev_4tuple = %path_data.network_path,
5576 "local address passive migration"
5577 );
5578 }
5579 path_data.network_path.local_ip = Some(new_local_ip)
5580 }
5581
5582 if self.peer_may_migrate()
5584 && (migrate_on_any_packet || !is_probing_packet)
5585 && is_largest_received_pn
5586 && network_path.remote != self.path_data(path_id).network_path.remote
5587 {
5588 self.migrate(path_id, now, network_path, migration_observed_addr);
5589 self.update_remote_cid(path_id);
5591 self.spin = false;
5592 }
5593
5594 Ok(())
5595 }
5596
5597 fn handle_path_response_on_path(
5601 &mut self,
5602 now: Instant,
5603 response: frame::PathResponse,
5604 path_id: PathId,
5605 ) {
5606 let is_multipath_negotiated = self.is_multipath_negotiated();
5607 let path = self
5608 .paths
5609 .get_mut(&path_id)
5610 .expect("payload is processed only after the path becomes known");
5611 match path.data.on_path_response_received(now, response.0) {
5612 paths::OnPathResponseReceived::OnPath if !self.abandoned_paths.contains(&path_id) => {
5613 let qlog = self.qlog.with_time(now);
5614 self.timers.stop(
5615 Timer::PerPath(path_id, PathTimer::PathValidationFailed),
5616 qlog.clone(),
5617 );
5618 let next_challenge = path
5619 .data
5620 .earliest_on_path_expiring_challenge()
5621 .map(|time| time + self.ack_frequency.max_ack_delay_for_pto());
5622 self.timers.set_or_stop(
5623 Timer::PerPath(path_id, PathTimer::PathChallengeLost),
5624 next_challenge,
5625 qlog,
5626 );
5627 let pns = self.spaces[SpaceKind::Data].for_path(path_id);
5628 if !matches!(pns.open_status, OpenStatus::Informed) {
5629 if is_multipath_negotiated {
5630 self.events
5631 .push_back(Event::Path(PathEvent::Established { id: path_id }));
5632 }
5633 pns.open_status = OpenStatus::Informed;
5634 if let Some(observed) = path.data.last_observed_addr_report.as_ref() {
5635 self.events.push_back(Event::Path(PathEvent::ObservedAddr {
5636 id: path_id,
5637 addr: observed.socket_addr(),
5638 }));
5639 }
5640 }
5641 if let Some((_, ref mut prev)) = path.prev {
5642 prev.reset_on_path_challenges();
5647 }
5648 }
5649 paths::OnPathResponseReceived::OnPath => {
5650 trace!(
5651 %response,
5652 "ignoring PATH_RESPONSE received after path is abandoned"
5653 );
5654 }
5655 paths::OnPathResponseReceived::Unknown => {
5656 debug!(%response, "ignoring invalid PATH_RESPONSE");
5657 }
5658 paths::OnPathResponseReceived::Ignored {
5659 sent_on,
5660 current_path,
5661 } => {
5662 debug!(%sent_on, %current_path, %response, "ignoring valid PATH_RESPONSE");
5663 }
5664 }
5665 }
5666
5667 fn open_nat_traversed_paths(&mut self, now: Instant) {
5669 while let Some(network_path) = self
5670 .n0_nat_traversal
5671 .client_side_mut()
5672 .ok()
5673 .and_then(|s| s.pop_pending_path_open())
5674 {
5675 match self.open_path_ensure(network_path, PathStatus::Backup, now) {
5676 Ok((path_id, already_existed)) => {
5677 debug!(
5678 %path_id,
5679 ?network_path,
5680 new_path = !already_existed,
5681 "Opened NAT traversal path",
5682 );
5683 }
5684 Err(err) => match err {
5685 PathError::MultipathNotNegotiated
5686 | PathError::ServerSideNotAllowed
5687 | PathError::ValidationFailed
5688 | PathError::InvalidRemoteAddress(_) => {
5689 error!(
5690 ?err,
5691 ?network_path,
5692 "Failed to open path for successful NAT traversal"
5693 );
5694 }
5695 PathError::MaxPathIdReached | PathError::RemoteCidsExhausted => {
5696 self.n0_nat_traversal
5698 .client_side_mut()
5699 .map(|s| s.push_pending_path_open(network_path))
5700 .ok();
5701 debug!(
5702 ?err,
5703 ?network_path,
5704 "Blocked opening NAT traversal path, enqueued"
5705 );
5706 return;
5707 }
5708 },
5709 }
5710 }
5711 }
5712
5713 fn migrate(
5718 &mut self,
5719 path_id: PathId,
5720 now: Instant,
5721 network_path: FourTuple,
5722 observed_addr: Option<ObservedAddr>,
5723 ) {
5724 trace!(
5725 new_4tuple = %network_path,
5726 prev_4tuple = %self.path_data(path_id).network_path,
5727 %path_id,
5728 "migration initiated",
5729 );
5730 self.path_generation_counter = self.path_generation_counter.wrapping_add(1);
5731 let prev_pto = self.pto(SpaceKind::Data, path_id);
5738 let path = self.paths.get_mut(&path_id).expect("known path");
5739 let mut new_path_data = if network_path.remote.is_ipv4()
5740 && network_path.remote.ip() == path.data.network_path.remote.ip()
5741 {
5742 PathData::from_previous(network_path, &path.data, self.path_generation_counter, now)
5743 } else {
5744 let peer_max_udp_payload_size =
5745 u16::try_from(self.peer_params.max_udp_payload_size.into_inner())
5746 .unwrap_or(u16::MAX);
5747 PathData::new(
5748 network_path,
5749 self.allow_mtud,
5750 Some(peer_max_udp_payload_size),
5751 self.path_generation_counter,
5752 now,
5753 &self.config,
5754 )
5755 };
5756 new_path_data.last_observed_addr_report = path.data.last_observed_addr_report.clone();
5757 if let Some(report) = observed_addr
5758 && let Some(updated) = new_path_data.update_observed_addr_report(report)
5759 {
5760 tracing::info!("adding observed addr event from migration");
5761 self.events.push_back(Event::Path(PathEvent::ObservedAddr {
5762 id: path_id,
5763 addr: updated,
5764 }));
5765 }
5766 new_path_data.pending_challenge = true;
5767 new_path_data.pending.observed_address = self
5768 .config
5769 .address_discovery_role
5770 .should_report(&self.peer_params.address_discovery_role);
5771
5772 let mut prev_path_data = mem::replace(&mut path.data, new_path_data);
5773
5774 if !prev_path_data.validated
5783 && let Some(cid) = self.remote_cids.get(&path_id).map(CidQueue::active)
5784 {
5785 prev_path_data.pending_challenge = true;
5786 path.prev = Some((cid, prev_path_data));
5789 }
5790
5791 self.qlog.emit_tuple_assigned(path_id, network_path, now);
5793
5794 self.timers.set(
5795 Timer::PerPath(path_id, PathTimer::PathValidationFailed),
5796 now + 3 * cmp::max(self.pto(SpaceKind::Data, path_id), prev_pto),
5797 self.qlog.with_time(now),
5798 );
5799 }
5800
5801 pub fn handle_network_change(&mut self, hint: Option<&dyn NetworkChangeHint>, now: Instant) {
5818 debug!("network changed");
5819 if self.state.is_drained() {
5820 return;
5821 }
5822 if self.highest_space < SpaceKind::Data {
5823 for path in self.paths.values_mut() {
5824 path.data.network_path.local_ip = None;
5826 }
5827
5828 self.update_remote_cid(PathId::ZERO);
5829 self.ping();
5830
5831 return;
5832 }
5833
5834 let mut non_recoverable_paths = Vec::default();
5837 let mut recoverable_paths = Vec::default();
5838 let mut open_paths = 0;
5839
5840 let is_multipath_negotiated = self.is_multipath_negotiated();
5841 let is_client = self.side().is_client();
5842 let immediate_ack_allowed = self.peer_supports_ack_frequency();
5843
5844 for (path_id, path) in self.paths.iter_mut() {
5845 if self.abandoned_paths.contains(path_id) {
5846 continue;
5847 }
5848 open_paths += 1;
5849
5850 let network_path = path.data.network_path;
5853
5854 path.data.network_path.local_ip = None;
5857 let remote = network_path.remote;
5858
5859 let attempt_to_recover = if is_multipath_negotiated {
5863 hint.map(|h| h.is_path_recoverable(*path_id, network_path))
5867 .unwrap_or(!is_client)
5868 } else {
5869 true
5871 };
5872
5873 if attempt_to_recover {
5874 recoverable_paths.push((*path_id, remote));
5875 } else {
5876 non_recoverable_paths.push((*path_id, remote, path.data.local_status()))
5877 }
5878 }
5879
5880 let open_first = open_paths == non_recoverable_paths.len();
5889
5890 for (path_id, remote, status) in non_recoverable_paths.into_iter() {
5891 let network_path = FourTuple {
5892 remote,
5893 local_ip: None, };
5895
5896 if open_first && let Err(e) = self.open_path(network_path, status, now) {
5897 if self.side().is_client() {
5898 debug!(%e, "Failed to open new path for network change");
5899 }
5900 recoverable_paths.push((path_id, remote));
5902 continue;
5903 }
5904
5905 if let Err(e) =
5906 self.close_path_inner(now, path_id, PathAbandonReason::UnusableAfterNetworkChange)
5907 {
5908 debug!(%e,"Failed to close unrecoverable path after network change");
5909 recoverable_paths.push((path_id, remote));
5910 continue;
5911 }
5912
5913 if !open_first && let Err(e) = self.open_path(network_path, status, now) {
5914 debug!(%e,"Failed to open new path for network change");
5918 }
5919 }
5920
5921 for (path_id, remote) in recoverable_paths.into_iter() {
5924 if let Some(path_space) = self.spaces[SpaceId::Data].number_spaces.get_mut(&path_id) {
5926 path_space.pending_ping = true;
5927
5928 if immediate_ack_allowed {
5929 path_space.pending_immediate_ack = true;
5930 }
5931 }
5932
5933 if let Some(path) = self.paths.get_mut(&path_id) {
5938 path.data.pto_count = 0;
5939 }
5940 self.set_loss_detection_timer(now, path_id);
5941
5942 let Some((reset_token, retired)) =
5943 self.remote_cids.get_mut(&path_id).and_then(CidQueue::next)
5944 else {
5945 continue;
5946 };
5947
5948 self.spaces[SpaceId::Data]
5950 .pending
5951 .retire_cids
5952 .extend(retired.map(|seq| (path_id, seq)));
5953
5954 debug_assert!(!self.state.is_drained()); self.endpoint_events
5956 .push_back(EndpointEventInner::ResetToken(path_id, remote, reset_token));
5957 }
5958 }
5959
5960 fn update_remote_cid(&mut self, path_id: PathId) {
5962 let Some((reset_token, retired)) = self
5963 .remote_cids
5964 .get_mut(&path_id)
5965 .and_then(|cids| cids.next())
5966 else {
5967 return;
5968 };
5969
5970 self.spaces[SpaceId::Data]
5972 .pending
5973 .retire_cids
5974 .extend(retired.map(|seq| (path_id, seq)));
5975 let remote = self.path_data(path_id).network_path.remote;
5976 self.set_reset_token(path_id, remote, reset_token);
5977 }
5978
5979 fn set_reset_token(&mut self, path_id: PathId, remote: SocketAddr, reset_token: ResetToken) {
5988 debug_assert!(!self.state.is_drained()); self.endpoint_events
5990 .push_back(EndpointEventInner::ResetToken(path_id, remote, reset_token));
5991
5992 if path_id == PathId::ZERO {
5998 self.peer_params.stateless_reset_token = Some(reset_token);
5999 }
6000 }
6001
6002 fn issue_first_cids(&mut self, now: Instant) {
6004 if self
6005 .local_cid_state
6006 .get(&PathId::ZERO)
6007 .expect("PathId::ZERO exists when the connection is created")
6008 .cid_len()
6009 == 0
6010 {
6011 return;
6012 }
6013
6014 let mut n = self.peer_params.issue_cids_limit() - 1;
6016 if let ConnectionSide::Server { server_config } = &self.side
6017 && server_config.has_preferred_address()
6018 {
6019 n -= 1;
6021 }
6022 debug_assert!(!self.state.is_drained()); self.endpoint_events
6024 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n));
6025 }
6026
6027 fn issue_first_path_cids(&mut self, now: Instant) {
6031 if let Some(max_path_id) = self.max_path_id() {
6032 let mut path_id = self.max_path_id_with_cids.next();
6033 while path_id <= max_path_id {
6034 self.endpoint_events
6035 .push_back(EndpointEventInner::NeedIdentifiers(
6036 path_id,
6037 now,
6038 self.peer_params.issue_cids_limit(),
6039 ));
6040 path_id = path_id.next();
6041 }
6042 self.max_path_id_with_cids = max_path_id;
6043 }
6044 }
6045
6046 fn populate_packet<'a, 'b>(
6054 &mut self,
6055 now: Instant,
6056 space_id: SpaceId,
6057 path_id: PathId,
6058 scheduling_info: &PathSchedulingInfo,
6059 builder: &mut PacketBuilder<'a, 'b>,
6060 ) {
6061 let is_multipath_negotiated = self.is_multipath_negotiated();
6062 let space_has_keys = self.crypto_state.has_keys(space_id.encryption_level());
6063 let is_0rtt = space_id == SpaceId::Data && !space_has_keys;
6064 let stats = &mut self.path_stats.get_mut(path_id).frame_tx;
6065 let space = &mut self.spaces[space_id];
6066 let path = &mut self.paths.get_mut(&path_id).expect("known path").data;
6067 space
6068 .for_path(path_id)
6069 .pending_acks
6070 .maybe_ack_non_eliciting();
6071
6072 if !is_0rtt
6074 && !scheduling_info.is_abandoned
6075 && scheduling_info.may_send_data
6076 && mem::replace(&mut space.pending.handshake_done, false)
6077 {
6078 builder.write_frame(frame::HandshakeDone, stats);
6079 }
6080
6081 if !scheduling_info.is_abandoned
6083 && mem::replace(&mut space.for_path(path_id).pending_ping, false)
6084 {
6085 builder.write_frame(frame::Ping, stats);
6086 }
6087
6088 if !scheduling_info.is_abandoned
6090 && mem::replace(&mut space.for_path(path_id).pending_immediate_ack, false)
6091 {
6092 debug_assert_eq!(
6093 space_id,
6094 SpaceId::Data,
6095 "immediate acks must be sent in the data space"
6096 );
6097 builder.write_frame(frame::ImmediateAck, stats);
6098 }
6099
6100 if !scheduling_info.is_abandoned && scheduling_info.may_send_data {
6102 for path_id in space
6103 .number_spaces
6104 .iter_mut()
6105 .filter(|(_, pns)| pns.pending_acks.can_send())
6106 .map(|(&path_id, _)| path_id)
6107 .collect::<Vec<_>>()
6108 {
6109 Self::populate_acks(
6110 now,
6111 self.receiving_ecn,
6112 path_id,
6113 space_id,
6114 space,
6115 is_multipath_negotiated,
6116 builder,
6117 stats,
6118 space_has_keys,
6119 );
6120 }
6121 }
6122
6123 if !scheduling_info.is_abandoned
6125 && scheduling_info.may_send_data
6126 && mem::replace(&mut space.pending.ack_frequency, false)
6127 {
6128 let sequence_number = self.ack_frequency.next_sequence_number();
6129
6130 let config = self.config.ack_frequency_config.as_ref().unwrap();
6132
6133 let max_ack_delay = self.ack_frequency.candidate_max_ack_delay(
6135 path.rtt.get(),
6136 config,
6137 &self.peer_params,
6138 );
6139
6140 let frame = frame::AckFrequency {
6141 sequence: sequence_number,
6142 ack_eliciting_threshold: config.ack_eliciting_threshold,
6143 request_max_ack_delay: max_ack_delay.as_micros().try_into().unwrap_or(VarInt::MAX),
6144 reordering_threshold: config.reordering_threshold,
6145 };
6146 builder.write_frame(frame, stats);
6147
6148 self.ack_frequency
6149 .ack_frequency_sent(path_id, builder.packet_number, max_ack_delay);
6150 }
6151
6152 if !scheduling_info.is_abandoned
6154 && space_id == SpaceId::Data
6155 && path.pending_challenge
6156 && !self.state.is_closed()
6158 && builder.frame_space_remaining() > frame::PathChallenge::SIZE_BOUND
6159 && builder.buf.segment_size() >= usize::from(MIN_INITIAL_SIZE)
6162 {
6163 path.pending_challenge = false;
6164
6165 let token = self.rng.random();
6166 path.record_path_challenge_sent(now, token, path.network_path);
6167 let challenge = frame::PathChallenge(token);
6169 builder.write_frame(challenge, stats);
6170 builder.require_padding();
6171
6172 self.timers.set(
6177 Timer::PerPath(path_id, PathTimer::PathChallengeLost),
6178 now + path.on_path_challenge_pto(),
6179 self.qlog.with_time(now),
6180 );
6181
6182 if is_multipath_negotiated && !path.validated && path.pending_challenge {
6183 space.pending.path_status.insert(path_id);
6185 }
6186
6187 path.pending.observed_address = self
6190 .config
6191 .address_discovery_role
6192 .should_report(&self.peer_params.address_discovery_role);
6193 }
6194
6195 if !scheduling_info.is_abandoned
6197 && space_id == SpaceId::Data
6198 && builder.frame_space_remaining() > frame::PathResponse::SIZE_BOUND
6199 && builder.buf.segment_size() >= usize::from(MIN_INITIAL_SIZE)
6202 && let Some(token) = space.for_path(path_id).pending_path_responses.pop_on_path(path.network_path)
6203 {
6204 let response = frame::PathResponse(token);
6205 builder.write_frame(response, stats);
6206 builder.require_padding();
6207
6208 path.pending.observed_address = self
6212 .config
6213 .address_discovery_role
6214 .should_report(&self.peer_params.address_discovery_role);
6215 }
6216
6217 while space_id == SpaceId::Data
6219 && !scheduling_info.is_abandoned
6220 && scheduling_info.may_send_data
6221 && frame::AddAddress::SIZE_BOUND <= builder.frame_space_remaining()
6222 {
6223 if let Some(added_address) = space.pending.add_address.pop_last() {
6224 builder.write_frame(added_address, stats);
6225 } else {
6226 break;
6227 }
6228 }
6229
6230 while space_id == SpaceId::Data
6232 && !scheduling_info.is_abandoned
6233 && scheduling_info.may_send_data
6234 && frame::RemoveAddress::SIZE_BOUND <= builder.frame_space_remaining()
6235 {
6236 if let Some(removed_address) = space.pending.remove_address.pop_last() {
6237 builder.write_frame(removed_address, stats);
6238 } else {
6239 break;
6240 }
6241 }
6242
6243 while !scheduling_info.is_abandoned
6245 && scheduling_info.may_send_data
6246 && let Some(reach_out) = space
6247 .pending
6248 .reach_out
6249 .pop_if(|frame| builder.frame_space_remaining() >= frame.size())
6250 {
6251 builder.write_frame(reach_out, stats);
6252 }
6253
6254 if space_id == SpaceId::Data
6256 && scheduling_info.is_abandoned
6257 && scheduling_info.may_self_abandon
6258 && frame::PathAbandon::SIZE_BOUND <= builder.frame_space_remaining()
6259 && let Some(error_code) = space.pending.path_abandon.remove(&path_id)
6260 {
6261 let frame = frame::PathAbandon {
6262 path_id,
6263 error_code,
6264 };
6265 builder.write_frame(frame, stats);
6266
6267 self.remote_cids.remove(&path_id);
6270 }
6271 while space_id == SpaceId::Data
6272 && scheduling_info.may_send_data
6273 && frame::PathAbandon::SIZE_BOUND <= builder.frame_space_remaining()
6274 && let Some((abandoned_path_id, error_code)) = space.pending.path_abandon.pop_first()
6275 {
6276 let frame = frame::PathAbandon {
6277 path_id: abandoned_path_id,
6278 error_code,
6279 };
6280 builder.write_frame(frame, stats);
6281
6282 self.remote_cids.remove(&abandoned_path_id);
6285 }
6286
6287 if !scheduling_info.is_abandoned
6289 && space_id == SpaceId::Data
6290 && path.pending.observed_address
6291 {
6292 let frame = ObservedAddr::new(path.network_path.remote, self.next_observed_addr_seq_no);
6293 if builder.frame_space_remaining() > frame.size() {
6294 builder.write_frame(frame, stats);
6295
6296 self.next_observed_addr_seq_no = self.next_observed_addr_seq_no.saturating_add(1u8);
6297 path.pending.observed_address = false;
6298 }
6299 }
6300
6301 while !is_0rtt
6303 && !scheduling_info.is_abandoned
6304 && scheduling_info.may_send_data
6305 && builder.frame_space_remaining() > frame::Crypto::SIZE_BOUND
6306 {
6307 let Some(mut frame) = space.pending.crypto.pop_front() else {
6308 break;
6309 };
6310
6311 let max_crypto_data_size = builder.frame_space_remaining()
6316 - 1 - VarInt::size(unsafe { VarInt::from_u64_unchecked(frame.offset) })
6318 - 2; let len = frame
6321 .data
6322 .len()
6323 .min(2usize.pow(14) - 1)
6324 .min(max_crypto_data_size);
6325
6326 let data = frame.data.split_to(len);
6327 let offset = frame.offset;
6328 let truncated = frame::Crypto { offset, data };
6329 builder.write_frame(truncated, stats);
6330
6331 if !frame.data.is_empty() {
6332 frame.offset += len as u64;
6333 space.pending.crypto.push_front(frame);
6334 }
6335 }
6336
6337 while space_id == SpaceId::Data
6339 && !scheduling_info.is_abandoned
6340 && scheduling_info.may_send_data
6341 && frame::PathStatusAvailable::SIZE_BOUND <= builder.frame_space_remaining()
6342 {
6343 let Some(path_id) = space.pending.path_status.pop_first() else {
6344 break;
6345 };
6346 let Some(path) = self.paths.get(&path_id).map(|path_state| &path_state.data) else {
6347 trace!(%path_id, "discarding queued path status for unknown path");
6348 continue;
6349 };
6350
6351 let seq = path.status.seq();
6352 match path.local_status() {
6353 PathStatus::Available => {
6354 let frame = frame::PathStatusAvailable {
6355 path_id,
6356 status_seq_no: seq,
6357 };
6358 builder.write_frame(frame, stats);
6359 }
6360 PathStatus::Backup => {
6361 let frame = frame::PathStatusBackup {
6362 path_id,
6363 status_seq_no: seq,
6364 };
6365 builder.write_frame(frame, stats);
6366 }
6367 }
6368 }
6369
6370 if space_id == SpaceId::Data
6372 && !scheduling_info.is_abandoned
6373 && scheduling_info.may_send_data
6374 && space.pending.max_path_id
6375 && frame::MaxPathId::SIZE_BOUND <= builder.frame_space_remaining()
6376 {
6377 let frame = frame::MaxPathId(self.local_max_path_id);
6378 builder.write_frame(frame, stats);
6379 space.pending.max_path_id = false;
6380 }
6381
6382 if space_id == SpaceId::Data
6384 && !scheduling_info.is_abandoned
6385 && scheduling_info.may_send_data
6386 && frame::PathsBlocked::SIZE_BOUND <= builder.frame_space_remaining()
6387 && let Some(remote_max_path_id) = space.pending.paths_blocked.take()
6388 {
6389 let frame = frame::PathsBlocked(remote_max_path_id);
6390 builder.write_frame(frame, stats);
6391 }
6392
6393 while space_id == SpaceId::Data
6395 && !scheduling_info.is_abandoned
6396 && scheduling_info.may_send_data
6397 && frame::PathCidsBlocked::SIZE_BOUND <= builder.frame_space_remaining()
6398 {
6399 let Some((path_id, next_seq)) = space.pending.path_cids_blocked.pop_first() else {
6400 break;
6401 };
6402 let frame = frame::PathCidsBlocked { path_id, next_seq };
6403 builder.write_frame(frame, stats);
6404 }
6405
6406 if space_id == SpaceId::Data
6408 && !scheduling_info.is_abandoned
6409 && scheduling_info.may_send_data
6410 {
6411 self.streams
6412 .write_control_frames(builder, &mut space.pending, stats);
6413 }
6414
6415 let cid_len = self
6417 .local_cid_state
6418 .values()
6419 .map(|cid_state| cid_state.cid_len())
6420 .max()
6421 .expect("some local CID state must exist");
6422 let new_cid_size_bound =
6423 frame::NewConnectionId::size_bound(is_multipath_negotiated, cid_len);
6424 while !scheduling_info.is_abandoned
6425 && scheduling_info.may_send_data
6426 && builder.frame_space_remaining() > new_cid_size_bound
6427 {
6428 let Some(issued) = space.pending.new_cids.pop() else {
6429 break;
6430 };
6431 let Some(cid_state) = self.local_cid_state.get(&issued.path_id) else {
6433 debug!(
6434 path = %issued.path_id, seq = issued.sequence,
6435 "dropping queued NEW_CONNECTION_ID for discarded path",
6436 );
6437 continue;
6438 };
6439 let retire_prior_to = cid_state.retire_prior_to();
6440
6441 let cid_path_id = match is_multipath_negotiated {
6442 true => Some(issued.path_id),
6443 false => {
6444 debug_assert_eq!(issued.path_id, PathId::ZERO);
6445 None
6446 }
6447 };
6448 let frame = frame::NewConnectionId {
6449 path_id: cid_path_id,
6450 sequence: issued.sequence,
6451 retire_prior_to,
6452 id: issued.id,
6453 reset_token: issued.reset_token,
6454 };
6455 builder.write_frame(frame, stats);
6456 }
6457
6458 let retire_cid_bound = frame::RetireConnectionId::size_bound(is_multipath_negotiated);
6460 while !scheduling_info.is_abandoned
6461 && scheduling_info.may_send_data
6462 && builder.frame_space_remaining() > retire_cid_bound
6463 {
6464 let (path_id, sequence) = match space.pending.retire_cids.pop() {
6465 Some((PathId::ZERO, seq)) if !is_multipath_negotiated => (None, seq),
6466 Some((path_id, seq)) => (Some(path_id), seq),
6467 None => break,
6468 };
6469 let frame = frame::RetireConnectionId { path_id, sequence };
6470 builder.write_frame(frame, stats);
6471 }
6472
6473 let mut sent_datagrams = false;
6475 while !scheduling_info.is_abandoned
6476 && scheduling_info.may_send_data
6477 && builder.frame_space_remaining() > Datagram::SIZE_BOUND
6478 && space_id == SpaceId::Data
6479 {
6480 match self.datagrams.write(builder, stats) {
6481 true => {
6482 sent_datagrams = true;
6483 }
6484 false => break,
6485 }
6486 }
6487 if self.datagrams.send_blocked && sent_datagrams {
6488 self.events.push_back(Event::DatagramsUnblocked);
6489 self.datagrams.send_blocked = false;
6490 }
6491
6492 let path = &mut self.paths.get_mut(&path_id).expect("known path").data;
6493
6494 if !scheduling_info.is_abandoned && scheduling_info.may_send_data {
6496 while let Some(network_path) = space.pending.new_tokens.pop() {
6497 debug_assert_eq!(space_id, SpaceId::Data);
6498 let ConnectionSide::Server { server_config } = &self.side else {
6499 panic!("NEW_TOKEN frames should not be enqueued by clients");
6500 };
6501
6502 if !network_path.is_probably_same_path(&path.network_path) {
6503 continue;
6508 }
6509
6510 let token = Token::new(
6511 TokenPayload::Validation {
6512 ip: network_path.remote.ip(),
6513 issued: server_config.time_source.now(),
6514 },
6515 &mut self.rng,
6516 );
6517 let new_token = NewToken {
6518 token: token.encode(&*server_config.token_key).into(),
6519 };
6520
6521 if builder.frame_space_remaining() < new_token.size() {
6522 space.pending.new_tokens.push(network_path);
6523 break;
6524 }
6525
6526 builder.write_frame(new_token, stats);
6527 builder.retransmits_mut().new_tokens.push(network_path);
6528 }
6529 }
6530
6531 if !scheduling_info.is_abandoned
6533 && scheduling_info.may_send_data
6534 && space_id == SpaceId::Data
6535 {
6536 self.streams
6537 .write_stream_frames(builder, self.config.send_fairness, stats);
6538 }
6539 }
6540
6541 fn populate_acks<'a, 'b>(
6543 now: Instant,
6544 receiving_ecn: bool,
6545 path_id: PathId,
6546 space_id: SpaceId,
6547 space: &mut PacketSpace,
6548 is_multipath_negotiated: bool,
6549 builder: &mut PacketBuilder<'a, 'b>,
6550 stats: &mut FrameStats,
6551 space_has_keys: bool,
6552 ) {
6553 debug_assert!(space_has_keys, "tried to send ACK in 0-RTT");
6555
6556 debug_assert!(
6557 is_multipath_negotiated || path_id == PathId::ZERO,
6558 "Only PathId::ZERO allowed without multipath (have {path_id:?})"
6559 );
6560 if is_multipath_negotiated {
6561 debug_assert!(
6562 space_id == SpaceId::Data || path_id == PathId::ZERO,
6563 "path acks must be sent in 1RTT space (have {space_id:?})"
6564 );
6565 }
6566
6567 let pns = space.for_path(path_id);
6568 let ranges = pns.pending_acks.ranges();
6569 debug_assert!(!ranges.is_empty(), "can not send empty ACK range");
6570 let ecn = if receiving_ecn {
6571 Some(&pns.ecn_counters)
6572 } else {
6573 None
6574 };
6575
6576 let delay_micros = pns.pending_acks.ack_delay(now).as_micros() as u64;
6577 let ack_delay_exp = TransportParameters::default().ack_delay_exponent;
6579 let delay = delay_micros >> ack_delay_exp.into_inner();
6580
6581 if is_multipath_negotiated && space_id == SpaceId::Data {
6582 if !ranges.is_empty() {
6583 let frame = frame::PathAck::encoder(path_id, delay, ranges, ecn);
6584 builder.write_frame(frame, stats);
6585 }
6586 } else {
6587 builder.write_frame(frame::Ack::encoder(delay, ranges, ecn), stats);
6588 }
6589 }
6590
6591 fn close_common(&mut self) {
6592 trace!("connection closed");
6593 self.timers.reset();
6594 }
6595
6596 fn set_close_timer(&mut self, now: Instant) {
6597 let pto_max = self.max_pto_for_space(self.highest_space);
6600 self.timers.set(
6601 Timer::Conn(ConnTimer::Close),
6602 now + 3 * pto_max,
6603 self.qlog.with_time(now),
6604 );
6605 }
6606
6607 fn handle_peer_params(
6612 &mut self,
6613 params: TransportParameters,
6614 local_cid: ConnectionId,
6615 remote_cid: ConnectionId,
6616 now: Instant,
6617 ) -> Result<(), TransportError> {
6618 if Some(self.original_remote_cid) != params.initial_src_cid
6619 || (self.side.is_client()
6620 && (Some(self.initial_dst_cid) != params.original_dst_cid
6621 || self.retry_src_cid != params.retry_src_cid))
6622 {
6623 return Err(TransportError::TRANSPORT_PARAMETER_ERROR(
6624 "CID authentication failure",
6625 ));
6626 }
6627 if params.initial_max_path_id.is_some() && (local_cid.is_empty() || remote_cid.is_empty()) {
6628 return Err(TransportError::PROTOCOL_VIOLATION(
6629 "multipath must not use zero-length CIDs",
6630 ));
6631 }
6632
6633 self.set_peer_params(params);
6634 self.qlog.emit_peer_transport_params_received(self, now);
6635
6636 Ok(())
6637 }
6638
6639 fn set_peer_params(&mut self, params: TransportParameters) {
6640 self.streams.set_params(¶ms);
6641 self.idle_timeout =
6642 negotiate_max_idle_timeout(self.config.max_idle_timeout, Some(params.max_idle_timeout));
6643 trace!("negotiated max idle timeout {:?}", self.idle_timeout);
6644
6645 if let Some(ref info) = params.preferred_address {
6646 self.remote_cids.get_mut(&PathId::ZERO).expect("not yet abandoned").insert(frame::NewConnectionId {
6648 path_id: None,
6649 sequence: 1,
6650 id: info.connection_id,
6651 reset_token: info.stateless_reset_token,
6652 retire_prior_to: 0,
6653 })
6654 .expect(
6655 "preferred address CID is the first received, and hence is guaranteed to be legal",
6656 );
6657 let remote = self.path_data(PathId::ZERO).network_path.remote;
6658 self.set_reset_token(PathId::ZERO, remote, info.stateless_reset_token);
6659 }
6660 self.ack_frequency.peer_max_ack_delay = get_max_ack_delay(¶ms);
6661
6662 let mut multipath_enabled = false;
6663 if let (Some(local_max_path_id), Some(remote_max_path_id)) = (
6664 self.config.get_initial_max_path_id(),
6665 params.initial_max_path_id,
6666 ) {
6667 self.local_max_path_id = local_max_path_id;
6669 self.remote_max_path_id = remote_max_path_id;
6670 let initial_max_path_id = local_max_path_id.min(remote_max_path_id);
6671 debug!(%initial_max_path_id, "multipath negotiated");
6672 multipath_enabled = true;
6673 }
6674
6675 if let Some((max_locally_allowed_remote_addresses, max_remotely_allowed_remote_addresses)) =
6676 self.config
6677 .max_remote_nat_traversal_addresses
6678 .zip(params.max_remote_nat_traversal_addresses)
6679 {
6680 if multipath_enabled {
6681 let max_local_addresses = max_remotely_allowed_remote_addresses.get();
6682 let max_remote_addresses = max_locally_allowed_remote_addresses.get();
6683 self.n0_nat_traversal = n0_nat_traversal::State::new(
6684 max_remote_addresses,
6685 max_local_addresses,
6686 self.side(),
6687 );
6688 debug!(
6689 %max_remote_addresses, %max_local_addresses,
6690 "n0's nat traversal negotiated"
6691 );
6692 } else {
6693 debug!("n0 nat traversal enabled for both endpoints, but multipath is missing")
6694 }
6695 }
6696
6697 self.peer_params = params;
6698 let peer_max_udp_payload_size =
6699 u16::try_from(self.peer_params.max_udp_payload_size.into_inner()).unwrap_or(u16::MAX);
6700 let address_discovery_negotiated = self
6701 .config
6702 .address_discovery_role
6703 .should_report(&self.peer_params.address_discovery_role);
6704
6705 let path = self.path_data_mut(PathId::ZERO);
6706 path.pending.observed_address = address_discovery_negotiated;
6707 path.mtud
6708 .on_peer_max_udp_payload_size_received(peer_max_udp_payload_size);
6709 }
6710
6711 fn decrypt_packet(
6713 &mut self,
6714 now: Instant,
6715 path_id: PathId,
6716 packet: &mut Packet,
6717 ) -> Result<Option<u64>, Option<TransportError>> {
6718 let result = self
6719 .crypto_state
6720 .decrypt_packet_body(packet, path_id, &self.spaces)?;
6721
6722 let Some(result) = result else {
6723 return Ok(None);
6724 };
6725
6726 if result.outgoing_key_update_acked
6727 && let Some(prev) = self.crypto_state.prev_crypto.as_mut()
6728 {
6729 prev.end_packet = Some((result.packet_number, now));
6730 self.set_key_discard_timer(now, packet.header.space());
6731 }
6732
6733 if result.incoming_key_update {
6734 trace!("key update authenticated");
6735 self.crypto_state
6736 .update_keys(Some((result.packet_number, now)), true);
6737 self.set_key_discard_timer(now, packet.header.space());
6738 }
6739
6740 Ok(Some(result.packet_number))
6741 }
6742
6743 fn peer_supports_ack_frequency(&self) -> bool {
6744 self.peer_params.min_ack_delay.is_some()
6745 }
6746
6747 pub(crate) fn immediate_ack(&mut self, path_id: PathId) {
6752 debug_assert_eq!(
6753 self.highest_space,
6754 SpaceKind::Data,
6755 "immediate ack must be written in the data space"
6756 );
6757 self.spaces[SpaceId::Data]
6758 .for_path(path_id)
6759 .pending_immediate_ack = true;
6760 }
6761
6762 #[cfg(test)]
6764 pub(crate) fn decode_packet(&self, event: &ConnectionEvent) -> Option<Vec<u8>> {
6765 let ConnectionEventInner::Datagram(DatagramConnectionEvent {
6766 path_id,
6767 first_decode,
6768 remaining,
6769 ..
6770 }) = &event.0
6771 else {
6772 return None;
6773 };
6774
6775 if remaining.is_some() {
6776 panic!("Packets should never be coalesced in tests");
6777 }
6778
6779 let decrypted_header = self
6780 .crypto_state
6781 .unprotect_header(first_decode.clone(), self.peer_params.stateless_reset_token)?;
6782
6783 let mut packet = decrypted_header.packet?;
6784 self.crypto_state
6785 .decrypt_packet_body(&mut packet, *path_id, &self.spaces)
6786 .ok()?;
6787
6788 Some(packet.payload.to_vec())
6789 }
6790
6791 #[cfg(test)]
6794 pub(crate) fn bytes_in_flight(&self) -> u64 {
6795 self.path_data(PathId::ZERO).in_flight.bytes
6797 }
6798
6799 #[cfg(test)]
6801 pub(crate) fn congestion_window(&self) -> u64 {
6802 let path = self.path_data(PathId::ZERO);
6803 path.congestion
6804 .window()
6805 .saturating_sub(path.in_flight.bytes)
6806 }
6807
6808 #[cfg(test)]
6810 pub(crate) fn is_idle(&self) -> bool {
6811 let current_timers = self.timers.values();
6812 current_timers
6813 .into_iter()
6814 .filter(|(timer, _)| {
6815 !matches!(
6816 timer,
6817 Timer::Conn(ConnTimer::KeepAlive)
6818 | Timer::PerPath(_, PathTimer::PathKeepAlive)
6819 | Timer::Conn(ConnTimer::PushNewCid)
6820 | Timer::Conn(ConnTimer::KeyDiscard)
6821 )
6822 })
6823 .min_by_key(|(_, time)| *time)
6824 .is_none_or(|(timer, _)| {
6825 matches!(
6826 timer,
6827 Timer::Conn(ConnTimer::Idle) | Timer::PerPath(_, PathTimer::PathIdle)
6828 )
6829 })
6830 }
6831
6832 #[cfg(test)]
6834 pub(crate) fn using_ecn(&self) -> bool {
6835 self.path_data(PathId::ZERO).sending_ecn
6836 }
6837
6838 #[cfg(test)]
6840 pub(crate) fn total_recvd(&self) -> u64 {
6841 self.path_data(PathId::ZERO).total_recvd
6842 }
6843
6844 #[cfg(test)]
6845 pub(crate) fn active_local_cid_seq(&self) -> (u64, u64) {
6846 self.local_cid_state
6847 .get(&PathId::ZERO)
6848 .unwrap()
6849 .active_seq()
6850 }
6851
6852 #[cfg(test)]
6853 #[track_caller]
6854 pub(crate) fn active_local_path_cid_seq(&self, path_id: u32) -> (u64, u64) {
6855 self.local_cid_state
6856 .get(&PathId(path_id))
6857 .unwrap()
6858 .active_seq()
6859 }
6860
6861 #[cfg(test)]
6864 pub(crate) fn rotate_local_cid(&mut self, v: u64, now: Instant) {
6865 let n = self
6866 .local_cid_state
6867 .get_mut(&PathId::ZERO)
6868 .unwrap()
6869 .assign_retire_seq(v);
6870 debug_assert!(!self.state.is_drained()); self.endpoint_events
6872 .push_back(EndpointEventInner::NeedIdentifiers(PathId::ZERO, now, n));
6873 }
6874
6875 #[cfg(test)]
6877 pub(crate) fn active_remote_cid_seq(&self) -> u64 {
6878 self.remote_cids.get(&PathId::ZERO).unwrap().active_seq()
6879 }
6880
6881 #[cfg(test)]
6883 pub(crate) fn path_mtu(&self, path_id: PathId) -> u16 {
6884 self.path_data(path_id).current_mtu()
6885 }
6886
6887 #[cfg(test)]
6889 pub(crate) fn trigger_path_validation(&mut self) {
6890 for path in self.paths.values_mut() {
6891 path.data.pending_challenge = true;
6892 }
6893 }
6894
6895 #[cfg(test)]
6897 pub fn simulate_protocol_violation(&mut self, now: Instant) {
6898 if !self.state.is_closed() {
6899 self.state
6900 .move_to_closed(TransportError::PROTOCOL_VIOLATION("simulated violation"));
6901 self.close_common();
6902 if !self.state.is_drained() {
6903 self.set_close_timer(now);
6904 }
6905 self.connection_close_pending = true;
6906 }
6907 }
6908
6909 fn can_send_1rtt(&self, path_id: PathId, max_size: usize) -> SendableFrames {
6920 let network_path = self.path_data(path_id).network_path;
6921 let space_specific = self
6922 .paths
6923 .get(&path_id)
6924 .is_some_and(|path| path.data.pending_challenge || !path.data.pending.is_empty())
6925 || self.spaces[SpaceKind::Data]
6926 .number_spaces
6927 .get(&path_id)
6928 .is_some_and(|pns| pns.pending_path_responses.has_pending_on_path(network_path));
6929
6930 let other = self.streams.can_send_stream_data()
6932 || self
6933 .datagrams
6934 .outgoing
6935 .front()
6936 .is_some_and(|x| x.size(true) <= max_size);
6937
6938 SendableFrames {
6940 acks: false,
6941 close: false,
6942 space_specific,
6943 other,
6944 }
6945 }
6946
6947 fn kill(&mut self, reason: ConnectionError) {
6949 self.close_common();
6950 self.state
6951 .move_to_drained(Some(reason), &mut self.endpoint_events);
6952 }
6953
6954 pub fn current_mtu(&self) -> u16 {
6961 self.paths
6962 .iter()
6963 .filter(|&(path_id, _path_state)| !self.abandoned_paths.contains(path_id))
6964 .map(|(_path_id, path_state)| path_state.data.current_mtu())
6965 .min()
6966 .unwrap_or(INITIAL_MTU)
6967 }
6968
6969 fn predict_1rtt_overhead(&mut self, pn: u64, path: PathId) -> usize {
6976 let pn_len = PacketNumber::new(
6977 pn,
6978 self.spaces[SpaceId::Data]
6979 .for_path(path)
6980 .largest_acked_packet_pn
6981 .unwrap_or(0),
6982 )
6983 .len();
6984
6985 1 + self
6987 .remote_cids
6988 .get(&path)
6989 .map(|cids| cids.active().len())
6990 .unwrap_or(20) + pn_len
6992 + self.tag_len_1rtt()
6993 }
6994
6995 fn predict_1rtt_overhead_no_pn(&self) -> usize {
6996 let pn_len = 4;
6997
6998 let cid_len = self
6999 .remote_cids
7000 .values()
7001 .map(|cids| cids.active().len())
7002 .max()
7003 .unwrap_or(20); 1 + cid_len + pn_len + self.tag_len_1rtt()
7007 }
7008
7009 fn tag_len_1rtt(&self) -> usize {
7010 let packet_crypto = self
7012 .crypto_state
7013 .encryption_keys(SpaceKind::Data, self.side.side())
7014 .map(|(_header, packet, _level)| packet);
7015 packet_crypto.map_or(16, |x| x.tag_len())
7019 }
7020
7021 fn on_path_validated(&mut self, path_id: PathId) {
7023 self.path_data_mut(path_id).validated = true;
7024 let ConnectionSide::Server { server_config } = &self.side else {
7025 return;
7026 };
7027 let network_path = self.path_data(path_id).network_path;
7028 let new_tokens = &mut self.spaces[SpaceId::Data as usize].pending.new_tokens;
7029 new_tokens.clear();
7030 for _ in 0..server_config.validation_token.sent {
7031 new_tokens.push(network_path);
7032 }
7033 }
7034
7035 fn on_path_status(&mut self, path_id: PathId, status: PathStatus, status_seq_no: VarInt) {
7037 if let Some(path) = self.paths.get_mut(&path_id) {
7038 path.data.status.remote_update(status, status_seq_no);
7039 } else {
7040 debug!("PATH_STATUS_AVAILABLE received unknown path {:?}", path_id);
7041 }
7042 self.events.push_back(
7043 PathEvent::RemoteStatus {
7044 id: path_id,
7045 status,
7046 }
7047 .into(),
7048 );
7049 }
7050
7051 fn max_path_id(&self) -> Option<PathId> {
7060 if self.is_multipath_negotiated() {
7061 Some(self.remote_max_path_id.min(self.local_max_path_id))
7062 } else {
7063 None
7064 }
7065 }
7066
7067 pub(crate) fn is_ipv6(&self) -> bool {
7072 self.paths
7073 .values()
7074 .any(|p| p.data.network_path.remote.is_ipv6())
7075 }
7076
7077 pub fn add_nat_traversal_address(
7079 &mut self,
7080 address: SocketAddr,
7081 ) -> Result<(), n0_nat_traversal::Error> {
7082 if let Some(added) = self.n0_nat_traversal.add_local_address(address)? {
7083 self.spaces[SpaceId::Data].pending.add_address.insert(added);
7084 };
7085 Ok(())
7086 }
7087
7088 pub fn remove_nat_traversal_address(
7092 &mut self,
7093 address: SocketAddr,
7094 ) -> Result<(), n0_nat_traversal::Error> {
7095 if let Some(removed) = self.n0_nat_traversal.remove_local_address(address)? {
7096 self.spaces[SpaceId::Data]
7097 .pending
7098 .remove_address
7099 .insert(removed);
7100 }
7101 Ok(())
7102 }
7103
7104 pub fn get_local_nat_traversal_addresses(
7106 &self,
7107 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> {
7108 self.n0_nat_traversal.get_local_nat_traversal_addresses()
7109 }
7110
7111 pub fn get_remote_nat_traversal_addresses(
7113 &self,
7114 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> {
7115 Ok(self
7116 .n0_nat_traversal
7117 .client_side()?
7118 .get_remote_nat_traversal_addresses())
7119 }
7120
7121 pub fn initiate_nat_traversal_round(
7133 &mut self,
7134 now: Instant,
7135 ) -> Result<Vec<SocketAddr>, n0_nat_traversal::Error> {
7136 if self.state.is_closed() {
7137 return Err(n0_nat_traversal::Error::Closed);
7138 }
7139
7140 let ipv6 = self.is_ipv6();
7141 let client_state = self.n0_nat_traversal.client_side_mut()?;
7142 let (mut reach_out_frames, probed_addrs) =
7143 client_state.initiate_nat_traversal_round(ipv6)?;
7144 if let Some(delay) = self.n0_nat_traversal.retry_delay(self.config.initial_rtt) {
7145 self.timers.set(
7146 Timer::Conn(ConnTimer::NatTraversalProbeRetry),
7147 now + delay,
7148 self.qlog.with_time(now),
7149 );
7150 }
7151
7152 self.spaces[SpaceId::Data]
7153 .pending
7154 .reach_out
7155 .append(&mut reach_out_frames);
7156
7157 Ok(probed_addrs)
7158 }
7159
7160 fn is_handshake_confirmed(&self) -> bool {
7169 !self.is_handshaking() && !self.crypto_state.has_keys(EncryptionLevel::Handshake)
7170 }
7171}
7172
7173impl fmt::Debug for Connection {
7174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7175 f.debug_struct("Connection")
7176 .field("handshake_cid", &self.handshake_cid)
7177 .finish()
7178 }
7179}
7180
7181#[derive(Debug, Default)]
7187struct AbandonedPaths(ArrayRangeSet<ABANDONED_PATH_INLINE_RANGES, u32>);
7188
7189const ABANDONED_PATH_INLINE_RANGES: usize = 16;
7194
7195impl AbandonedPaths {
7196 fn len(&self) -> u32 {
7198 self.0.elts_count()
7199 }
7200
7201 fn max(&self) -> Option<PathId> {
7203 self.0.max().map(PathId::from)
7204 }
7205
7206 fn contains(&self, val: &PathId) -> bool {
7208 self.0.contains(val.as_u32())
7209 }
7210
7211 fn insert(&mut self, val: PathId) {
7213 self.0.insert_one(val.as_u32());
7214 }
7215}
7216
7217pub trait NetworkChangeHint: fmt::Debug + 'static {
7219 fn is_path_recoverable(&self, path_id: PathId, network_path: FourTuple) -> bool;
7228}
7229
7230#[derive(Debug)]
7232enum PollPathSpaceStatus {
7233 NothingToSend {
7235 congestion_blocked: bool,
7237 },
7238 WrotePacket {
7240 last_packet_number: u64,
7242 pad_datagram: PadDatagram,
7256 },
7257 Send {
7264 last_packet_number: u64,
7266 },
7267}
7268
7269#[derive(Debug, Copy, Clone)]
7275struct PathSchedulingInfo {
7276 is_abandoned: bool,
7282 may_send_data: bool,
7300 may_send_close: bool,
7306 may_self_abandon: bool,
7307}
7308
7309#[derive(Debug, Copy, Clone, PartialEq, Eq)]
7310enum PathBlocked {
7311 No,
7312 AntiAmplification,
7313 Congestion,
7314 Pacing,
7315}
7316
7317enum ConnectionSide {
7319 Client {
7320 token: Bytes,
7322 token_store: Arc<dyn TokenStore>,
7323 server_name: String,
7324 },
7325 Server {
7326 server_config: Arc<ServerConfig>,
7327 },
7328}
7329
7330impl ConnectionSide {
7331 fn is_client(&self) -> bool {
7332 self.side().is_client()
7333 }
7334
7335 fn is_server(&self) -> bool {
7336 self.side().is_server()
7337 }
7338
7339 fn side(&self) -> Side {
7340 match *self {
7341 Self::Client { .. } => Side::Client,
7342 Self::Server { .. } => Side::Server,
7343 }
7344 }
7345}
7346
7347impl From<SideArgs> for ConnectionSide {
7348 fn from(side: SideArgs) -> Self {
7349 match side {
7350 SideArgs::Client {
7351 token_store,
7352 server_name,
7353 } => Self::Client {
7354 token: token_store.take(&server_name).unwrap_or_default(),
7355 token_store,
7356 server_name,
7357 },
7358 SideArgs::Server {
7359 server_config,
7360 pref_addr_cid: _,
7361 path_validated: _,
7362 } => Self::Server { server_config },
7363 }
7364 }
7365}
7366
7367pub(crate) enum SideArgs {
7369 Client {
7370 token_store: Arc<dyn TokenStore>,
7371 server_name: String,
7372 },
7373 Server {
7374 server_config: Arc<ServerConfig>,
7375 pref_addr_cid: Option<ConnectionId>,
7376 path_validated: bool,
7377 },
7378}
7379
7380impl SideArgs {
7381 pub(crate) fn pref_addr_cid(&self) -> Option<ConnectionId> {
7382 match *self {
7383 Self::Client { .. } => None,
7384 Self::Server { pref_addr_cid, .. } => pref_addr_cid,
7385 }
7386 }
7387
7388 pub(crate) fn path_validated(&self) -> bool {
7389 match *self {
7390 Self::Client { .. } => true,
7391 Self::Server { path_validated, .. } => path_validated,
7392 }
7393 }
7394
7395 pub(crate) fn side(&self) -> Side {
7396 match *self {
7397 Self::Client { .. } => Side::Client,
7398 Self::Server { .. } => Side::Server,
7399 }
7400 }
7401}
7402
7403#[derive(Debug, Error, Clone, PartialEq, Eq)]
7405pub enum ConnectionError {
7406 #[error("peer doesn't implement any supported version")]
7408 VersionMismatch,
7409 #[error(transparent)]
7411 TransportError(#[from] TransportError),
7412 #[error("aborted by peer: {0}")]
7414 ConnectionClosed(frame::ConnectionClose),
7415 #[error("closed by peer: {0}")]
7417 ApplicationClosed(frame::ApplicationClose),
7418 #[error("reset by peer")]
7420 Reset,
7421 #[error("timed out")]
7427 TimedOut,
7428 #[error("closed")]
7430 LocallyClosed,
7431 #[error("CIDs exhausted")]
7435 CidsExhausted,
7436}
7437
7438impl From<Close> for ConnectionError {
7439 fn from(x: Close) -> Self {
7440 match x {
7441 Close::Connection(reason) => Self::ConnectionClosed(reason),
7442 Close::Application(reason) => Self::ApplicationClosed(reason),
7443 }
7444 }
7445}
7446
7447impl From<ConnectionError> for io::Error {
7449 fn from(x: ConnectionError) -> Self {
7450 use ConnectionError::*;
7451 let kind = match x {
7452 TimedOut => io::ErrorKind::TimedOut,
7453 Reset => io::ErrorKind::ConnectionReset,
7454 ApplicationClosed(_) | ConnectionClosed(_) => io::ErrorKind::ConnectionAborted,
7455 TransportError(_) | VersionMismatch | LocallyClosed | CidsExhausted => {
7456 io::ErrorKind::Other
7457 }
7458 };
7459 Self::new(kind, x)
7460 }
7461}
7462
7463#[derive(Debug, Error, PartialEq, Eq, Clone, Copy)]
7466pub enum PathError {
7467 #[error("multipath extension not negotiated")]
7469 MultipathNotNegotiated,
7470 #[error("the server side may not open a path")]
7472 ServerSideNotAllowed,
7473 #[error("maximum number of concurrent paths reached")]
7475 MaxPathIdReached,
7476 #[error("remoted CIDs exhausted")]
7478 RemoteCidsExhausted,
7479 #[error("path validation failed")]
7481 ValidationFailed,
7482 #[error("invalid remote address")]
7484 InvalidRemoteAddress(SocketAddr),
7485}
7486
7487#[derive(Debug, Error, Clone, Eq, PartialEq)]
7489pub enum ClosePathError {
7490 #[error("Multipath extension not negotiated")]
7492 MultipathNotNegotiated,
7493 #[error("closed path")]
7495 ClosedPath,
7496 #[error("last open path")]
7500 LastOpenPath,
7501}
7502
7503#[derive(Debug, Error, Clone, Copy)]
7505#[error("Multipath extension not negotiated")]
7506pub struct MultipathNotNegotiated {
7507 _private: (),
7508}
7509
7510#[derive(Debug)]
7512pub enum Event {
7513 HandshakeDataReady,
7515 Connected,
7517 HandshakeConfirmed,
7519 ConnectionLost {
7526 reason: ConnectionError,
7528 },
7529 Stream(StreamEvent),
7531 DatagramReceived,
7533 DatagramsUnblocked,
7535 Path(PathEvent),
7537 NatTraversal(n0_nat_traversal::Event),
7539}
7540
7541impl From<PathEvent> for Event {
7542 fn from(source: PathEvent) -> Self {
7543 Self::Path(source)
7544 }
7545}
7546
7547fn get_max_ack_delay(params: &TransportParameters) -> Duration {
7548 Duration::from_micros(params.max_ack_delay.0 * 1000)
7549}
7550
7551const MAX_BACKOFF_EXPONENT: u32 = 16;
7553
7554const MAX_PTO_INTERVAL: Duration = Duration::from_secs(2);
7558
7559const MIN_IDLE_FOR_FAST_PTO: Duration = Duration::from_secs(25);
7561
7562const MAX_PTO_FAST_INTERVAL: Duration = Duration::from_secs(1);
7567
7568const SLOW_RTT_THRESHOLD: Duration =
7573 Duration::from_millis((MAX_PTO_INTERVAL.as_millis() as u64 * 2) / 3);
7574
7575const MIN_PACKET_SPACE: usize = MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE + 32;
7583
7584const MAX_HANDSHAKE_OR_0RTT_HEADER_SIZE: usize =
7590 1 + 4 + 1 + MAX_CID_SIZE + 1 + MAX_CID_SIZE + VarInt::from_u32(u16::MAX as u32).size() + 4;
7591
7592#[derive(Default)]
7593struct SentFrames {
7594 retransmits: ThinRetransmits,
7595 path_retransmits: PathRetransmits,
7596 largest_acked: FxHashMap<PathId, u64>,
7598 stream_frames: StreamMetaVec,
7599 non_retransmits: bool,
7601 requires_padding: bool,
7603}
7604
7605impl SentFrames {
7606 fn is_ack_only(&self, streams: &StreamsState) -> bool {
7608 !self.largest_acked.is_empty()
7609 && !self.non_retransmits
7610 && self.stream_frames.is_empty()
7611 && self.retransmits.is_empty(streams)
7612 }
7613
7614 fn retransmits_mut(&mut self) -> &mut Retransmits {
7615 self.retransmits.get_or_create()
7616 }
7617
7618 fn record_sent_frame(&mut self, frame: frame::EncodableFrame<'_>) {
7619 use frame::EncodableFrame::*;
7620 match frame {
7621 PathAck(path_ack_encoder) => {
7622 if let Some(max) = path_ack_encoder.ranges.max() {
7623 self.largest_acked.insert(path_ack_encoder.path_id, max);
7624 }
7625 }
7626 Ack(ack_encoder) => {
7627 if let Some(max) = ack_encoder.ranges.max() {
7628 self.largest_acked.insert(PathId::ZERO, max);
7629 }
7630 }
7631 Close(_) => { }
7632 PathResponse(_) => self.non_retransmits = true,
7633 HandshakeDone(_) => self.retransmits_mut().handshake_done = true,
7634 ReachOut(frame) => self.retransmits_mut().reach_out.push(frame),
7635 ObservedAddr(_) => self.path_retransmits.observed_address = true,
7636 Ping(_) => self.non_retransmits = true,
7637 ImmediateAck(_) => self.non_retransmits = true,
7638 AckFrequency(_) => self.retransmits_mut().ack_frequency = true,
7639 PathChallenge(_) => self.non_retransmits = true,
7640 Crypto(crypto) => self.retransmits_mut().crypto.push_back(crypto),
7641 PathAbandon(path_abandon) => {
7642 self.retransmits_mut()
7643 .path_abandon
7644 .entry(path_abandon.path_id)
7645 .or_insert(path_abandon.error_code);
7646 }
7647 PathStatusAvailable(frame::PathStatusAvailable { path_id, .. })
7648 | PathStatusBackup(frame::PathStatusBackup { path_id, .. }) => {
7649 self.retransmits_mut().path_status.insert(path_id);
7650 }
7651 MaxPathId(_) => self.retransmits_mut().max_path_id = true,
7652 PathsBlocked(frame::PathsBlocked(path_id)) => {
7653 let paths_blocked = &mut self.retransmits_mut().paths_blocked;
7654 *paths_blocked = cmp::max(*paths_blocked, Some(path_id));
7655 }
7656 PathCidsBlocked(path_cids_blocked) => {
7657 self.retransmits_mut()
7658 .path_cids_blocked
7659 .entry(path_cids_blocked.path_id)
7660 .and_modify(|next_seq| {
7661 *next_seq = cmp::max(*next_seq, path_cids_blocked.next_seq);
7662 })
7663 .or_insert(path_cids_blocked.next_seq);
7664 }
7665 ResetStream(reset) => self
7666 .retransmits_mut()
7667 .reset_stream
7668 .push((reset.id, reset.error_code)),
7669 StopSending(stop_sending) => self.retransmits_mut().stop_sending.push(stop_sending),
7670 NewConnectionId(new_cid) => self.retransmits_mut().new_cids.push(new_cid.issued()),
7671 RetireConnectionId(retire_cid) => self
7672 .retransmits_mut()
7673 .retire_cids
7674 .push((retire_cid.path_id.unwrap_or_default(), retire_cid.sequence)),
7675 Datagram(_) => self.non_retransmits = true,
7676 NewToken(_) => {}
7677 AddAddress(add_address) => {
7678 self.retransmits_mut().add_address.insert(add_address);
7679 }
7680 RemoveAddress(remove_address) => {
7681 self.retransmits_mut().remove_address.insert(remove_address);
7682 }
7683 StreamMeta(stream_meta_encoder) => self.stream_frames.push(stream_meta_encoder.meta),
7684 MaxData(_) => self.retransmits_mut().max_data = true,
7685 MaxStreamData(max) => {
7686 self.retransmits_mut().max_stream_data.insert(max.id);
7687 }
7688 MaxStreams(max_streams) => {
7689 self.retransmits_mut().max_stream_id[max_streams.dir as usize] = true
7690 }
7691 StreamsBlocked(streams_blocked) => {
7692 self.retransmits_mut().streams_blocked[streams_blocked.dir as usize] = true
7693 }
7694 }
7695 }
7696}
7697
7698fn negotiate_max_idle_timeout(x: Option<VarInt>, y: Option<VarInt>) -> Option<Duration> {
7706 match (x, y) {
7707 (Some(VarInt(0)) | None, Some(VarInt(0)) | None) => None,
7708 (Some(VarInt(0)) | None, Some(y)) => Some(Duration::from_millis(y.0)),
7709 (Some(x), Some(VarInt(0)) | None) => Some(Duration::from_millis(x.0)),
7710 (Some(x), Some(y)) => Some(Duration::from_millis(cmp::min(x, y).0)),
7711 }
7712}
7713
7714#[cfg(test)]
7715mod tests {
7716 use super::*;
7717
7718 #[test]
7719 fn negotiate_max_idle_timeout_commutative() {
7720 let test_params = [
7721 (None, None, None),
7722 (None, Some(VarInt(0)), None),
7723 (None, Some(VarInt(2)), Some(Duration::from_millis(2))),
7724 (Some(VarInt(0)), Some(VarInt(0)), None),
7725 (
7726 Some(VarInt(2)),
7727 Some(VarInt(0)),
7728 Some(Duration::from_millis(2)),
7729 ),
7730 (
7731 Some(VarInt(1)),
7732 Some(VarInt(4)),
7733 Some(Duration::from_millis(1)),
7734 ),
7735 ];
7736
7737 for (left, right, result) in test_params {
7738 assert_eq!(negotiate_max_idle_timeout(left, right), result);
7739 assert_eq!(negotiate_max_idle_timeout(right, left), result);
7740 }
7741 }
7742
7743 #[test]
7744 fn abandoned_paths() {
7745 let mut t = AbandonedPaths::default();
7746
7747 t.insert(PathId(0));
7748 t.insert(PathId(1));
7749 assert_eq!(t.len(), 2);
7750 assert_eq!(t.0.range_count(), 1); assert!(t.contains(&PathId(0)));
7752 assert!(t.contains(&PathId(1)));
7753 assert!(!t.contains(&PathId(2)));
7754 assert!(!t.contains(&PathId(3)));
7755 assert_eq!(t.max(), Some(PathId(1)));
7756
7757 t.insert(PathId(3));
7758 assert_eq!(t.len(), 3);
7759 assert_eq!(t.0.range_count(), 2); assert!(t.contains(&PathId(0)));
7761 assert!(t.contains(&PathId(1)));
7762 assert!(!t.contains(&PathId(2)));
7763 assert!(t.contains(&PathId(3)));
7764 assert_eq!(t.max(), Some(PathId(3)));
7765
7766 t.insert(PathId(2));
7767 assert_eq!(t.len(), 4);
7768 assert_eq!(t.0.range_count(), 1); assert!(t.contains(&PathId(0)));
7770 assert!(t.contains(&PathId(1)));
7771 assert!(t.contains(&PathId(2)));
7772 assert!(t.contains(&PathId(3)));
7773 assert_eq!(t.max(), Some(PathId(3)));
7774 }
7775}