1use std::{
2 cmp,
3 collections::{BTreeMap, BTreeSet, VecDeque},
4 mem,
5 ops::{Bound, Index, IndexMut},
6};
7
8use rand::{CryptoRng, RngExt};
9use rustc_hash::{FxHashMap, FxHashSet};
10use sorted_index_buffer::SortedIndexBuffer;
11use tracing::{debug, trace};
12
13use super::{PathId, paths::PathResponses, paths::PathRetransmits};
14use crate::{
15 Dir, Duration, FourTuple, Instant, StreamId, TransportError, TransportErrorCode, VarInt,
16 connection::StreamsState,
17 frame::{self, AddAddress, RemoveAddress},
18 packet::SpaceId,
19 range_set::ArrayRangeSet,
20 shared::IssuedCid,
21};
22
23pub(super) struct PacketSpace {
24 pub(super) pending: Retransmits,
26
27 pub(super) number_spaces: BTreeMap<PathId, PacketNumberSpace>,
33}
34
35impl PacketSpace {
36 pub(super) fn new(now: Instant, space: SpaceId, rng: &mut (impl CryptoRng + ?Sized)) -> Self {
37 let number_space_0 = PacketNumberSpace::new(now, space, rng);
38 Self {
39 pending: Retransmits::default(),
40 number_spaces: BTreeMap::from([(PathId::ZERO, number_space_0)]),
41 }
42 }
43
44 #[cfg(test)]
45 pub(super) fn new_deterministic(now: Instant, space: SpaceId) -> Self {
46 let number_space_0 = PacketNumberSpace::new_deterministic(now, space);
47 Self {
48 pending: Retransmits::default(),
49 number_spaces: BTreeMap::from([(PathId::ZERO, number_space_0)]),
50 }
51 }
52
53 pub(super) fn path_space(&self, path_id: PathId) -> Option<&PacketNumberSpace> {
57 self.number_spaces.get(&path_id)
58 }
59
60 pub(super) fn path_space_mut(&mut self, path_id: PathId) -> Option<&mut PacketNumberSpace> {
64 self.number_spaces.get_mut(&path_id)
65 }
66
67 pub(super) fn for_path(&mut self, path: PathId) -> &mut PacketNumberSpace {
76 self.number_spaces
77 .get_mut(&path)
78 .unwrap_or_else(|| panic!("PacketNumberSpace missing for {path}"))
79 }
80
81 pub(super) fn iter_paths_mut(&mut self) -> impl Iterator<Item = &mut PacketNumberSpace> {
82 self.number_spaces.values_mut()
83 }
84
85 pub(super) fn queue_tail_loss_probe(
98 &mut self,
99 path_id: PathId,
100 request_immediate_ack: bool,
101 streams: &StreamsState,
102 ) {
103 if request_immediate_ack {
104 self.for_path(path_id).pending_immediate_ack = true;
107 }
108
109 if !self.pending.is_empty(streams) {
111 return;
113 }
114
115 for packet in self
117 .number_spaces
118 .values_mut()
119 .flat_map(|s| s.sent_packets.values_mut())
120 {
121 if !packet.retransmits.is_empty(streams) {
122 self.pending |= mem::take(&mut packet.retransmits);
125 return;
126 }
127 }
128
129 if !self.for_path(path_id).pending_immediate_ack {
133 self.for_path(path_id).pending_ping = true;
134 }
135 }
136
137 pub(super) fn can_send(&self, path_id: PathId, streams: &StreamsState) -> SendableFrames {
145 let acks = self
146 .number_spaces
147 .values()
148 .any(|pns| pns.pending_acks.can_send());
149 let space_specific = self.number_spaces.get(&path_id).is_some_and(|s| {
150 s.pending_ping || s.pending_immediate_ack || !s.pending_path_responses.is_empty()
151 });
152 let other = !self.pending.is_empty(streams);
153 SendableFrames {
154 acks,
155 close: false,
156 space_specific,
157 other,
158 }
159 }
160}
161
162impl Index<SpaceId> for [PacketSpace; 3] {
163 type Output = PacketSpace;
164 fn index(&self, space: SpaceId) -> &PacketSpace {
165 &self.as_ref()[space as usize]
166 }
167}
168
169impl IndexMut<SpaceId> for [PacketSpace; 3] {
170 fn index_mut(&mut self, space: SpaceId) -> &mut PacketSpace {
171 &mut self.as_mut()[space as usize]
172 }
173}
174
175#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
180pub(crate) enum SpaceKind {
181 Initial = 0,
183 Handshake = 1,
185 Data = 2,
187}
188
189impl SpaceKind {
190 pub(crate) fn encryption_level(self) -> super::EncryptionLevel {
192 match self {
193 Self::Initial => super::EncryptionLevel::Initial,
194 Self::Handshake => super::EncryptionLevel::Handshake,
195 Self::Data => super::EncryptionLevel::OneRtt,
196 }
197 }
198}
199
200impl Index<SpaceKind> for [PacketSpace; 3] {
201 type Output = PacketSpace;
202 fn index(&self, space: SpaceKind) -> &PacketSpace {
203 &self.as_ref()[space as usize]
204 }
205}
206
207impl IndexMut<SpaceKind> for [PacketSpace; 3] {
208 fn index_mut(&mut self, space: SpaceKind) -> &mut PacketSpace {
209 &mut self.as_mut()[space as usize]
210 }
211}
212
213pub(super) struct PacketNumberSpace {
230 pub(super) open_status: OpenStatus,
241 pub(super) status: PathStatusState,
246
247 pub(super) largest_received_packet_number: Option<u64>,
249 pub(super) next_packet_number: u64,
252 pub(super) largest_acked_packet_pn: Option<u64>,
254 pub(super) largest_acked_packet_send_time: Instant,
255 pub(super) largest_ack_eliciting_sent: u64,
257 pub(super) unacked_non_ack_eliciting_tail: u64,
259 pub(super) sent_packets: SortedIndexBuffer<SentPacket>,
262 pub(super) lost_packets: SortedIndexBuffer<LostPacket>,
265 pub(super) ecn_counters: frame::EcnCounts,
267 pub(super) ecn_feedback: frame::EcnCounts,
274 pub(super) pending_ping: bool,
276 pub(super) pending_acks: PendingAcks,
278 pub(super) pending_immediate_ack: bool,
280 pub(super) pending_path_responses: PathResponses,
286 pub(super) dedup: Dedup,
288
289 pub(super) time_of_last_ack_eliciting_packet: Option<Instant>,
293 pub(super) loss_time: Option<Instant>,
299 pub(super) loss_probes: u32,
301
302 pn_filter: Option<PacketNumberFilter>,
304}
305
306impl PacketNumberSpace {
307 pub(super) fn new(now: Instant, space: SpaceId, rng: &mut (impl CryptoRng + ?Sized)) -> Self {
308 let pn_filter = match space {
309 SpaceId::Initial | SpaceId::Handshake => None,
310 SpaceId::Data => Some(PacketNumberFilter::new(rng)),
311 };
312 Self {
313 open_status: OpenStatus::default(),
314 status: PathStatusState::default(),
315 largest_received_packet_number: None,
316 next_packet_number: 0,
317 largest_acked_packet_pn: None,
318 largest_acked_packet_send_time: now,
319 largest_ack_eliciting_sent: 0,
320 unacked_non_ack_eliciting_tail: 0,
321 sent_packets: SortedIndexBuffer::new(),
322 lost_packets: SortedIndexBuffer::new(),
323 ecn_counters: frame::EcnCounts::ZERO,
324 ecn_feedback: frame::EcnCounts::ZERO,
325 pending_ping: false,
326 pending_acks: PendingAcks::new(),
327 pending_immediate_ack: false,
328 pending_path_responses: PathResponses::default(),
329 dedup: Default::default(),
330 time_of_last_ack_eliciting_packet: None,
331 loss_time: None,
332 loss_probes: 0,
333 pn_filter,
334 }
335 }
336
337 #[cfg(test)]
338 fn new_deterministic(now: Instant, space: SpaceId) -> Self {
339 let pn_filter = match space {
340 SpaceId::Initial | SpaceId::Handshake => None,
341 SpaceId::Data => Some(PacketNumberFilter::disabled()),
342 };
343 Self {
344 open_status: OpenStatus::default(),
345 status: PathStatusState::default(),
346 largest_received_packet_number: None,
347 next_packet_number: 0,
348 largest_acked_packet_pn: None,
349 largest_acked_packet_send_time: now,
350 largest_ack_eliciting_sent: 0,
351 unacked_non_ack_eliciting_tail: 0,
352 sent_packets: SortedIndexBuffer::new(),
353 lost_packets: SortedIndexBuffer::new(),
354 ecn_counters: frame::EcnCounts::ZERO,
355 ecn_feedback: frame::EcnCounts::ZERO,
356 pending_ping: false,
357 pending_acks: PendingAcks::new(),
358 pending_immediate_ack: false,
359 pending_path_responses: PathResponses::default(),
360 dedup: Default::default(),
361 time_of_last_ack_eliciting_packet: None,
362 loss_time: None,
363 loss_probes: 0,
364 pn_filter,
365 }
366 }
367
368 pub(crate) fn remote_status(&self) -> Option<PathStatus> {
369 self.status.remote_status.map(|(_seq, status)| status)
370 }
371
372 pub(crate) fn local_status(&self) -> PathStatus {
373 self.status.local_status
374 }
375
376 pub(super) fn get_tx_number(&mut self, rng: &mut (impl CryptoRng + ?Sized)) -> u64 {
381 assert!(self.next_packet_number < 2u64.pow(62));
383 let mut pn = self.next_packet_number;
384 self.next_packet_number += 1;
385
386 if let Some(ref mut filter) = self.pn_filter
388 && filter.skip_pn(pn, rng)
389 {
390 pn = self.next_packet_number;
391 self.next_packet_number += 1;
392 }
393 pn
394 }
395
396 pub(super) fn peek_tx_number(&mut self) -> u64 {
397 let pn = self.next_packet_number;
398 if let Some(ref filter) = self.pn_filter
399 && pn == filter.next_skipped_packet_number
400 {
401 return pn + 1;
402 }
403 pn
404 }
405
406 pub(super) fn check_ack(&self, range: std::ops::Range<u64>) -> Result<(), TransportError> {
408 if let Some(ref filter) = self.pn_filter
409 && filter
410 .prev_skipped_packet_number
411 .is_some_and(|pn| range.contains(&pn))
412 {
413 return Err(TransportError::PROTOCOL_VIOLATION("unsent packet acked"));
414 }
415 Ok(())
416 }
417
418 pub(super) fn detect_ecn(
420 &mut self,
421 newly_acked: u64,
422 ecn: frame::EcnCounts,
423 ) -> Result<bool, &'static str> {
424 let ect0_increase = ecn
425 .ect0
426 .checked_sub(self.ecn_feedback.ect0)
427 .ok_or("peer ECT(0) count regression")?;
428 let ect1_increase = ecn
429 .ect1
430 .checked_sub(self.ecn_feedback.ect1)
431 .ok_or("peer ECT(1) count regression")?;
432 let ce_increase = ecn
433 .ce
434 .checked_sub(self.ecn_feedback.ce)
435 .ok_or("peer CE count regression")?;
436 let total_increase = ect0_increase + ect1_increase + ce_increase;
437 if total_increase < newly_acked {
438 return Err("ECN bleaching");
439 }
440 if (ect0_increase + ce_increase) < newly_acked || ect1_increase != 0 {
441 return Err("ECN corruption");
442 }
443 self.ecn_feedback = ecn;
448 Ok(ce_increase != 0)
449 }
450
451 pub(super) fn take(&mut self, number: u64) -> Option<SentPacket> {
453 let packet = self.sent_packets.remove(number)?;
454 if !packet.ack_eliciting && number > self.largest_ack_eliciting_sent {
455 self.unacked_non_ack_eliciting_tail =
456 self.unacked_non_ack_eliciting_tail.checked_sub(1).unwrap();
457 }
458 Some(packet)
459 }
460
461 pub(super) fn sent(&mut self, number: u64, packet: SentPacket) -> Option<SentPacket> {
463 const MAX_UNACKED_NON_ACK_ELICTING_TAIL: u64 = 1_000;
470
471 let mut forgotten = None;
472 if packet.ack_eliciting {
473 self.unacked_non_ack_eliciting_tail = 0;
474 self.largest_ack_eliciting_sent = number;
475 } else if self.unacked_non_ack_eliciting_tail > MAX_UNACKED_NON_ACK_ELICTING_TAIL {
476 let oldest_after_ack_eliciting = self
477 .sent_packets
478 .keys_range((
479 Bound::Excluded(self.largest_ack_eliciting_sent),
480 Bound::Unbounded,
481 ))
482 .next()
483 .unwrap();
484 let packet = self
489 .sent_packets
490 .remove(oldest_after_ack_eliciting)
491 .unwrap();
492 debug_assert!(!packet.ack_eliciting);
493 forgotten = Some(packet);
494 } else {
495 self.unacked_non_ack_eliciting_tail += 1;
496 }
497
498 self.sent_packets.insert(number, packet);
499 forgotten
500 }
501
502 pub(super) fn has_in_flight(&self) -> bool {
504 self.sent_packets.values().any(|x| x.size != 0)
508 }
509}
510
511#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
512pub(super) enum OpenStatus {
513 #[default]
515 Pending,
516 Informed,
518}
519
520#[derive(Debug, Clone, Default)]
522pub(super) struct PathStatusState {
523 local_status: PathStatus,
525 local_seq: VarInt,
529 remote_status: Option<(VarInt, PathStatus)>,
531}
532
533impl PathStatusState {
534 pub(super) fn remote_update(&mut self, status: PathStatus, seq: VarInt) {
536 if self.remote_status.is_some_and(|(curr, _)| curr >= seq) {
537 return trace!(%seq, "ignoring path status update");
538 }
539
540 let prev = self.remote_status.replace((seq, status)).map(|(_, s)| s);
541 if prev != Some(status) {
542 debug!(?status, ?seq, "remote changed path status");
543 }
544 }
545
546 pub(super) fn local_update(&mut self, status: PathStatus) -> Option<PathStatus> {
550 if self.local_status == status {
551 return None;
552 }
553
554 self.local_seq = self.local_seq.saturating_add(1u8);
555 Some(std::mem::replace(&mut self.local_status, status))
556 }
557
558 pub(crate) fn seq(&self) -> VarInt {
559 self.local_seq
560 }
561}
562
563#[cfg_attr(test, derive(test_strategy::Arbitrary))]
568#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
569pub enum PathStatus {
570 #[default]
575 Available,
576 Backup,
581}
582
583#[derive(Debug, Clone)]
585pub(super) struct SentPacket {
586 pub(super) path_generation: u64,
589 pub(super) time_sent: Instant,
591 pub(super) size: u16,
595 pub(super) ack_eliciting: bool,
597 pub(super) largest_acked: FxHashMap<PathId, u64>,
599 pub(super) retransmits: ThinRetransmits,
603 pub(super) path_retransmits: PathRetransmits,
605 pub(super) stream_frames: frame::StreamMetaVec,
609}
610
611#[derive(Debug)]
613pub(super) struct LostPacket {
614 pub(super) time_sent: Instant,
616}
617
618#[allow(unreachable_pub)] #[derive(Debug, Default, Clone)]
623pub struct Retransmits {
624 pub(super) max_data: bool,
625 pub(super) max_stream_id: [bool; 2],
626 pub(super) streams_blocked: [bool; 2],
627 pub(super) reset_stream: Vec<(StreamId, VarInt)>,
628 pub(super) stop_sending: Vec<frame::StopSending>,
629 pub(super) max_stream_data: FxHashSet<StreamId>,
630 pub(super) crypto: VecDeque<frame::Crypto>,
631 pub(super) new_cids: PendingNewCids,
632 pub(super) retire_cids: Vec<(PathId, u64)>,
633 pub(super) ack_frequency: bool,
634 pub(super) handshake_done: bool,
635 pub(super) max_path_id: bool,
637 pub(super) paths_blocked: Option<PathId>,
645 pub(super) new_tokens: Vec<FourTuple>,
662 pub(super) path_abandon: BTreeMap<PathId, TransportErrorCode>,
664 pub(super) path_status: BTreeSet<PathId>,
667 pub(super) path_cids_blocked: BTreeMap<PathId, VarInt>,
673
674 pub(super) add_address: BTreeSet<AddAddress>,
677 pub(super) remove_address: BTreeSet<RemoveAddress>,
679 pub(super) reach_out: PendingReachOutFrames,
681}
682
683impl Retransmits {
684 pub(super) fn is_empty(&self, streams: &StreamsState) -> bool {
685 let Self {
686 max_data,
687 max_stream_id,
688 streams_blocked,
689 reset_stream,
690 stop_sending,
691 max_stream_data,
692 crypto,
693 new_cids,
694 retire_cids,
695 ack_frequency,
696 handshake_done,
697 max_path_id,
698 paths_blocked,
699 new_tokens,
700 path_abandon,
701 path_status,
702 path_cids_blocked,
703 add_address,
704 remove_address,
705 reach_out,
706 } = &self;
707 !max_data
708 && !max_stream_id.iter().any(|x| *x)
709 && !streams_blocked.iter().any(|x| *x)
710 && reset_stream.is_empty()
711 && stop_sending.is_empty()
712 && max_stream_data
713 .iter()
714 .all(|&id| !streams.can_send_flow_control(id))
715 && crypto.is_empty()
716 && new_cids.is_empty()
717 && retire_cids.is_empty()
718 && !ack_frequency
719 && !handshake_done
720 && !max_path_id
721 && paths_blocked.is_none()
722 && new_tokens.is_empty()
723 && path_abandon.is_empty()
724 && path_status.is_empty()
725 && path_cids_blocked.is_empty()
726 && add_address.is_empty()
727 && remove_address.is_empty()
728 && reach_out.is_empty()
729 }
730}
731
732impl ::std::ops::BitOrAssign for Retransmits {
733 fn bitor_assign(&mut self, rhs: Self) {
734 let Self {
735 max_data,
736 max_stream_id,
737 streams_blocked,
738 reset_stream,
739 stop_sending,
740 max_stream_data,
741 crypto,
742 new_cids,
743 retire_cids,
744 ack_frequency,
745 handshake_done,
746 max_path_id,
747 paths_blocked,
748 new_tokens,
749 mut path_abandon,
750 mut path_status,
751 mut path_cids_blocked,
752 add_address,
753 remove_address,
754 mut reach_out,
755 } = rhs;
756
757 self.max_data |= max_data;
760 for dir in Dir::iter() {
761 self.max_stream_id[dir as usize] |= max_stream_id[dir as usize];
762 self.streams_blocked[dir as usize] |= streams_blocked[dir as usize];
763 }
764 self.reset_stream.extend_from_slice(&reset_stream);
765 self.stop_sending.extend_from_slice(&stop_sending);
766 self.max_stream_data.extend(&max_stream_data);
767 for crypto in crypto.into_iter().rev() {
768 self.crypto.push_front(crypto);
769 }
770 self.new_cids.extend(&new_cids);
771 self.retire_cids.extend(retire_cids);
772 self.ack_frequency |= ack_frequency;
773 self.handshake_done |= handshake_done;
774 self.max_path_id |= max_path_id;
775 self.paths_blocked = cmp::max(self.paths_blocked, paths_blocked);
776 self.new_tokens.extend_from_slice(&new_tokens);
777 self.path_abandon.append(&mut path_abandon);
778 self.path_status.append(&mut path_status);
779 self.path_cids_blocked.append(&mut path_cids_blocked);
780 self.add_address.extend(add_address.iter().copied());
781 self.remove_address.extend(remove_address.iter().copied());
782 self.reach_out.append(&mut reach_out);
783 }
784}
785
786impl ::std::ops::BitOrAssign<ThinRetransmits> for Retransmits {
787 fn bitor_assign(&mut self, rhs: ThinRetransmits) {
788 let ThinRetransmits { retransmits } = rhs;
789 if let Some(retransmits) = retransmits {
790 self.bitor_assign(*retransmits)
791 }
792 }
793}
794
795impl ::std::iter::FromIterator<Self> for Retransmits {
796 fn from_iter<T>(iter: T) -> Self
797 where
798 T: IntoIterator<Item = Self>,
799 {
800 let mut result = Self::default();
801 for packet in iter {
802 result |= packet;
803 }
804 result
805 }
806}
807
808#[derive(Clone, Debug, Default)]
815pub(super) struct PendingNewCids {
816 cids: Vec<IssuedCid>,
818 sorted: bool,
820}
821
822impl PendingNewCids {
823 pub(super) fn push(&mut self, cid: IssuedCid) {
825 self.cids.push(cid);
826 self.sorted = false;
827 }
828
829 pub(super) fn pop(&mut self) -> Option<IssuedCid> {
831 if !mem::replace(&mut self.sorted, true) {
832 self.cids
833 .sort_by_key(|cid| cmp::Reverse((cid.path_id, cid.sequence)));
834 }
835 self.cids.pop()
836 }
837
838 pub(super) fn is_empty(&self) -> bool {
839 self.cids.is_empty()
840 }
841
842 pub(super) fn extend(&mut self, other: &Self) {
843 self.cids.extend(&other.cids);
844 self.sorted = false;
845 }
846
847 pub(super) fn retain<F>(&mut self, f: F)
848 where
849 F: FnMut(&IssuedCid) -> bool,
850 {
851 self.cids.retain(f);
852 }
853}
854
855#[derive(Debug, Default, Clone)]
862pub(crate) struct PendingReachOutFrames {
863 round: VarInt,
865 frames: Vec<frame::ReachOut>,
867}
868
869impl PendingReachOutFrames {
870 pub(crate) fn len(&self) -> usize {
871 self.frames.len()
872 }
873
874 pub(crate) fn is_empty(&self) -> bool {
875 self.frames.is_empty()
876 }
877
878 pub(crate) fn push(&mut self, frame: frame::ReachOut) {
879 if frame.round < self.round {
880 return;
881 } else if frame.round > self.round {
882 self.round = frame.round;
883 self.frames.clear();
884 }
885 self.frames.push(frame);
886 }
887
888 pub(crate) fn append(&mut self, other: &mut Self) {
889 if other.round < self.round {
890 other.frames.clear();
891 return;
892 } else if other.round > self.round {
893 self.round = other.round;
894 self.frames.clear();
895 }
896 self.frames.append(&mut other.frames);
897 }
898
899 pub(crate) fn pop_if(
900 &mut self,
901 predicate: impl FnOnce(&mut frame::ReachOut) -> bool,
902 ) -> Option<frame::ReachOut> {
903 self.frames.pop_if(predicate)
904 }
905}
906
907impl FromIterator<frame::ReachOut> for PendingReachOutFrames {
908 fn from_iter<T: IntoIterator<Item = frame::ReachOut>>(iter: T) -> Self {
909 let iter = iter.into_iter();
910 let size_hint = iter.size_hint();
911 let mut this = Self {
912 round: Default::default(),
913 frames: Vec::with_capacity(size_hint.1.unwrap_or(size_hint.0)),
914 };
915 for frame in iter {
916 this.push(frame);
917 }
918 this
919 }
920}
921
922#[derive(Debug, Default, Clone)]
924pub(super) struct ThinRetransmits {
925 retransmits: Option<Box<Retransmits>>,
926}
927
928impl ThinRetransmits {
929 pub(super) fn is_empty(&self, streams: &StreamsState) -> bool {
931 match &self.retransmits {
932 Some(retransmits) => retransmits.is_empty(streams),
933 None => true,
934 }
935 }
936
937 pub(super) fn get(&self) -> Option<&Retransmits> {
939 self.retransmits.as_deref()
940 }
941
942 pub(super) fn get_mut(&mut self) -> Option<&mut Retransmits> {
944 self.retransmits.as_deref_mut()
945 }
946
947 pub(super) fn get_or_create(&mut self) -> &mut Retransmits {
951 if self.retransmits.is_none() {
952 self.retransmits = Some(Box::default());
953 }
954 self.retransmits.as_deref_mut().unwrap()
955 }
956}
957
958#[derive(Debug, Default)]
970pub(super) struct Dedup {
971 window: Window,
972 next: u64,
974}
975
976impl Dedup {
977 #[cfg(test)]
979 pub(super) fn new() -> Self {
980 Self { window: 0, next: 0 }
981 }
982
983 fn highest(&self) -> u64 {
985 self.next - 1
986 }
987
988 pub(super) fn insert(&mut self, packet: u64) -> bool {
992 if let Some(diff) = packet.checked_sub(self.next) {
993 self.window = ((self.window << 1) | 1)
995 .checked_shl(cmp::min(diff, u64::from(u32::MAX)) as u32)
996 .unwrap_or(0);
997 self.next = packet + 1;
998 false
999 } else if self.highest() - packet < WINDOW_SIZE {
1000 if let Some(bit) = (self.highest() - packet).checked_sub(1) {
1002 let mask = 1 << bit;
1004 let duplicate = self.window & mask != 0;
1005 self.window |= mask;
1006 duplicate
1007 } else {
1008 true
1010 }
1011 } else {
1012 true
1014 }
1015 }
1016
1017 fn smallest_missing_in_interval(&self, lower_bound: u64, upper_bound: u64) -> Option<u64> {
1021 debug_assert!(lower_bound <= upper_bound);
1022 debug_assert!(upper_bound <= self.highest());
1023 const BITFIELD_SIZE: u64 = Window::BITS as u64;
1024
1025 let lower_bound = lower_bound + 1;
1029 let upper_bound = upper_bound.saturating_sub(1);
1030
1031 let start_offset = (self.highest() - upper_bound).max(1) - 1;
1034 if start_offset >= BITFIELD_SIZE {
1035 return None;
1038 }
1039
1040 let end_offset_exclusive = self.highest().saturating_sub(lower_bound);
1041
1042 let range_len = end_offset_exclusive
1045 .saturating_sub(start_offset)
1046 .min(BITFIELD_SIZE);
1047 if range_len == 0 {
1048 return None;
1049 }
1050
1051 let mask = if range_len == BITFIELD_SIZE {
1054 u128::MAX
1055 } else {
1056 ((1u128 << range_len) - 1) << start_offset
1057 };
1058 let gaps = !self.window & mask;
1059
1060 let smallest_missing_offset = 128 - gaps.leading_zeros() as u64;
1061 let smallest_missing_packet = self.highest() - smallest_missing_offset;
1062
1063 if smallest_missing_packet <= upper_bound {
1064 Some(smallest_missing_packet)
1065 } else {
1066 None
1067 }
1068 }
1069
1070 fn missing_in_interval(&self, lower_bound: u64, upper_bound: u64) -> bool {
1074 self.smallest_missing_in_interval(lower_bound, upper_bound)
1075 .is_some()
1076 }
1077}
1078
1079type Window = u128;
1084
1085const WINDOW_SIZE: u64 = 1 + size_of::<Window>() as u64 * 8;
1087#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1091pub(super) struct SendableFrames {
1092 pub(super) acks: bool,
1094 pub(super) close: bool,
1096 pub(super) space_specific: bool,
1104 pub(super) other: bool,
1106}
1107
1108impl SendableFrames {
1109 pub(super) fn empty() -> Self {
1111 Self {
1112 acks: false,
1113 close: false,
1114 space_specific: false,
1115 other: false,
1116 }
1117 }
1118
1119 pub(super) fn is_ack_eliciting(&self) -> bool {
1121 let Self {
1122 acks: _,
1123 close,
1124 space_specific,
1125 other,
1126 } = *self;
1127 if close {
1128 return false;
1130 }
1131 space_specific || other
1132 }
1133
1134 pub(super) fn is_empty(&self) -> bool {
1136 let Self {
1137 acks,
1138 close,
1139 space_specific,
1140 other,
1141 } = *self;
1142 !acks && !close && !space_specific && !other
1143 }
1144}
1145
1146impl ::std::ops::BitOrAssign for SendableFrames {
1147 fn bitor_assign(&mut self, rhs: Self) {
1148 let Self {
1149 acks,
1150 close,
1151 space_specific,
1152 other,
1153 } = rhs;
1154
1155 self.acks |= acks;
1156 self.close |= close;
1157 self.space_specific |= space_specific;
1158 self.other |= other;
1159 }
1160}
1161
1162#[derive(Debug)]
1163pub(super) struct PendingAcks {
1164 immediate_ack_required: bool,
1169 ack_eliciting_since_last_ack_sent: u64,
1173 non_ack_eliciting_since_last_ack_sent: u64,
1174 ack_eliciting_threshold: u64,
1175 reordering_threshold: u64,
1184 earliest_ack_eliciting_since_last_ack_sent: Option<Instant>,
1187 ranges: ArrayRangeSet,
1193 largest_packet: Option<(u64, Instant)>,
1197 largest_ack_eliciting_packet: Option<u64>,
1199 largest_acked: Option<u64>,
1201}
1202
1203impl PendingAcks {
1204 fn new() -> Self {
1205 Self {
1206 immediate_ack_required: false,
1207 ack_eliciting_since_last_ack_sent: 0,
1208 non_ack_eliciting_since_last_ack_sent: 0,
1209 ack_eliciting_threshold: 1,
1210 reordering_threshold: 1,
1211 earliest_ack_eliciting_since_last_ack_sent: None,
1212 ranges: Default::default(),
1213 largest_packet: Default::default(),
1214 largest_ack_eliciting_packet: Default::default(),
1215 largest_acked: Default::default(),
1216 }
1217 }
1218
1219 pub(super) fn set_ack_frequency_params(&mut self, frame: &frame::AckFrequency) {
1220 self.ack_eliciting_threshold = frame.ack_eliciting_threshold.into_inner();
1221 self.reordering_threshold = frame.reordering_threshold.into_inner();
1222 }
1223
1224 pub(super) fn set_immediate_ack_required(&mut self) {
1225 self.immediate_ack_required = true;
1226 }
1227
1228 pub(super) fn on_max_ack_delay_timeout(&mut self) {
1229 self.immediate_ack_required = self.ack_eliciting_since_last_ack_sent > 0;
1230 }
1231
1232 pub(super) fn max_ack_delay_timeout(&self, max_ack_delay: Duration) -> Option<Instant> {
1233 self.earliest_ack_eliciting_since_last_ack_sent
1234 .map(|earliest_unacked| earliest_unacked + max_ack_delay)
1235 }
1236
1237 pub(super) fn can_send(&self) -> bool {
1246 self.immediate_ack_required && !self.ranges.is_empty()
1247 }
1248
1249 pub(super) fn ack_delay(&self, now: Instant) -> Duration {
1251 self.largest_packet
1252 .map_or_else(Duration::default, |(_, received)| now - received)
1253 }
1254
1255 pub(super) fn packet_received(
1259 &mut self,
1260 now: Instant,
1261 packet_number: u64,
1262 ack_eliciting: bool,
1263 dedup: &Dedup,
1264 ) -> bool {
1265 if !ack_eliciting {
1266 self.non_ack_eliciting_since_last_ack_sent += 1;
1267 return false;
1268 }
1269
1270 let prev_largest_ack_eliciting = self.largest_ack_eliciting_packet.unwrap_or(0);
1271
1272 self.largest_ack_eliciting_packet = self
1274 .largest_ack_eliciting_packet
1275 .map(|pn| pn.max(packet_number))
1276 .or(Some(packet_number));
1277
1278 self.ack_eliciting_since_last_ack_sent += 1;
1280 self.immediate_ack_required |=
1281 self.ack_eliciting_since_last_ack_sent > self.ack_eliciting_threshold;
1282
1283 self.immediate_ack_required |=
1285 self.is_out_of_order(packet_number, prev_largest_ack_eliciting, dedup);
1286
1287 if self.earliest_ack_eliciting_since_last_ack_sent.is_none() && !self.can_send() {
1289 self.earliest_ack_eliciting_since_last_ack_sent = Some(now);
1290 return true;
1291 }
1292
1293 false
1294 }
1295
1296 fn is_out_of_order(
1297 &self,
1298 packet_number: u64,
1299 prev_largest_ack_eliciting: u64,
1300 dedup: &Dedup,
1301 ) -> bool {
1302 match self.reordering_threshold {
1303 0 => false,
1304 1 => {
1305 packet_number < prev_largest_ack_eliciting
1307 || dedup.missing_in_interval(prev_largest_ack_eliciting, packet_number)
1308 }
1309 _ => {
1310 let Some((largest_acked, largest_unacked)) =
1313 self.largest_acked.zip(self.largest_ack_eliciting_packet)
1314 else {
1315 return false;
1316 };
1317 if self.reordering_threshold > largest_acked {
1318 return false;
1319 }
1320 let largest_reported = largest_acked - self.reordering_threshold + 1;
1323 let Some(smallest_missing_unreported) =
1324 dedup.smallest_missing_in_interval(largest_reported, largest_unacked)
1325 else {
1326 return false;
1327 };
1328 largest_unacked - smallest_missing_unreported >= self.reordering_threshold
1329 }
1330 }
1331 }
1332
1333 pub(super) fn acks_sent(&mut self) {
1337 self.immediate_ack_required = false;
1347 self.ack_eliciting_since_last_ack_sent = 0;
1348 self.non_ack_eliciting_since_last_ack_sent = 0;
1349 self.earliest_ack_eliciting_since_last_ack_sent = None;
1350 self.largest_acked = self.largest_ack_eliciting_packet;
1351 }
1352
1353 pub(super) fn insert_one(&mut self, packet: u64, now: Instant) {
1355 self.ranges.insert_one(packet);
1356
1357 if self.largest_packet.is_none_or(|(pn, _)| packet > pn) {
1358 self.largest_packet = Some((packet, now));
1359 }
1360
1361 if self.ranges.range_count() > MAX_ACK_BLOCKS {
1362 self.ranges.pop_min();
1363 }
1364 }
1365
1366 pub(super) fn subtract_below(&mut self, max: u64) {
1368 self.ranges.remove(0..(max + 1));
1369 }
1370
1371 pub(super) fn ranges(&self) -> &ArrayRangeSet {
1373 &self.ranges
1374 }
1375
1376 pub(super) fn maybe_ack_non_eliciting(&mut self) {
1382 const LAZY_ACK_THRESHOLD: u64 = 10;
1387 if self.non_ack_eliciting_since_last_ack_sent > LAZY_ACK_THRESHOLD {
1388 self.immediate_ack_required = true;
1389 }
1390 }
1391}
1392
1393pub(super) struct PacketNumberFilter {
1410 next_skipped_packet_number: u64,
1412 prev_skipped_packet_number: Option<u64>,
1414 exponent: u32,
1416}
1417
1418impl PacketNumberFilter {
1419 pub(super) fn new(rng: &mut (impl CryptoRng + ?Sized)) -> Self {
1420 let exponent = 6;
1422 Self {
1423 next_skipped_packet_number: rng.random_range(0..2u64.saturating_pow(exponent)),
1424 prev_skipped_packet_number: None,
1425 exponent,
1426 }
1427 }
1428
1429 #[cfg(test)]
1430 pub(super) fn disabled() -> Self {
1431 Self {
1432 next_skipped_packet_number: u64::MAX,
1433 prev_skipped_packet_number: None,
1434 exponent: u32::MAX,
1435 }
1436 }
1437
1438 pub(super) fn skip_pn(&mut self, n: u64, rng: &mut (impl CryptoRng + ?Sized)) -> bool {
1440 if n != self.next_skipped_packet_number {
1441 return false;
1442 }
1443
1444 trace!("skipping pn {n}");
1445 self.prev_skipped_packet_number = Some(self.next_skipped_packet_number);
1447 let next_exponent = self.exponent.saturating_add(1);
1448 self.next_skipped_packet_number = rng
1449 .random_range(2u64.saturating_pow(self.exponent)..2u64.saturating_pow(next_exponent));
1450 self.exponent = next_exponent;
1451 true
1452 }
1453}
1454
1455const MAX_ACK_BLOCKS: usize = 64;
1457
1458#[cfg(test)]
1459mod test {
1460 use rand::Rng;
1461 use rand::seq::SliceRandom;
1462
1463 use crate::token::ResetToken;
1464 use crate::{ConnectionIdGenerator, RandomConnectionIdGenerator};
1465
1466 use super::*;
1467
1468 #[test]
1469 fn sanity() {
1470 let mut dedup = Dedup::new();
1471 assert!(!dedup.insert(0));
1472 assert_eq!(dedup.next, 1);
1473 assert_eq!(dedup.window, 0b1);
1474 assert!(dedup.insert(0));
1475 assert_eq!(dedup.next, 1);
1476 assert_eq!(dedup.window, 0b1);
1477 assert!(!dedup.insert(1));
1478 assert_eq!(dedup.next, 2);
1479 assert_eq!(dedup.window, 0b11);
1480 assert!(!dedup.insert(2));
1481 assert_eq!(dedup.next, 3);
1482 assert_eq!(dedup.window, 0b111);
1483 assert!(!dedup.insert(4));
1484 assert_eq!(dedup.next, 5);
1485 assert_eq!(dedup.window, 0b11110);
1486 assert!(!dedup.insert(7));
1487 assert_eq!(dedup.next, 8);
1488 assert_eq!(dedup.window, 0b1111_0100);
1489 assert!(dedup.insert(4));
1490 assert!(!dedup.insert(3));
1491 assert_eq!(dedup.next, 8);
1492 assert_eq!(dedup.window, 0b1111_1100);
1493 assert!(!dedup.insert(6));
1494 assert_eq!(dedup.next, 8);
1495 assert_eq!(dedup.window, 0b1111_1101);
1496 assert!(!dedup.insert(5));
1497 assert_eq!(dedup.next, 8);
1498 assert_eq!(dedup.window, 0b1111_1111);
1499 }
1500
1501 #[test]
1502 fn happypath() {
1503 let mut dedup = Dedup::new();
1504 for i in 0..(2 * WINDOW_SIZE) {
1505 assert!(!dedup.insert(i));
1506 for j in 0..=i {
1507 assert!(dedup.insert(j));
1508 }
1509 }
1510 }
1511
1512 #[test]
1513 fn jump() {
1514 let mut dedup = Dedup::new();
1515 dedup.insert(2 * WINDOW_SIZE);
1516 assert!(dedup.insert(WINDOW_SIZE));
1517 assert_eq!(dedup.next, 2 * WINDOW_SIZE + 1);
1518 assert_eq!(dedup.window, 0);
1519 assert!(!dedup.insert(WINDOW_SIZE + 1));
1520 assert_eq!(dedup.next, 2 * WINDOW_SIZE + 1);
1521 assert_eq!(dedup.window, 1 << (WINDOW_SIZE - 2));
1522 }
1523
1524 #[test]
1525 fn dedup_has_missing() {
1526 let mut dedup = Dedup::new();
1527
1528 dedup.insert(0);
1529 assert!(!dedup.missing_in_interval(0, 0));
1530
1531 dedup.insert(1);
1532 assert!(!dedup.missing_in_interval(0, 1));
1533
1534 dedup.insert(3);
1535 assert!(dedup.missing_in_interval(1, 3));
1536
1537 dedup.insert(4);
1538 assert!(!dedup.missing_in_interval(3, 4));
1539 assert!(dedup.missing_in_interval(0, 4));
1540
1541 dedup.insert(2);
1542 assert!(!dedup.missing_in_interval(0, 4));
1543 }
1544
1545 #[test]
1546 fn dedup_outside_of_window_has_missing() {
1547 let mut dedup = Dedup::new();
1548
1549 for i in 0..140 {
1550 dedup.insert(i);
1551 }
1552
1553 assert!(!dedup.missing_in_interval(0, 4));
1555 dedup.insert(160);
1556 assert!(!dedup.missing_in_interval(0, 4));
1557 assert!(!dedup.missing_in_interval(0, 140));
1558 assert!(dedup.missing_in_interval(0, 160));
1559 }
1560
1561 #[test]
1562 fn dedup_smallest_missing() {
1563 let mut dedup = Dedup::new();
1564
1565 dedup.insert(0);
1566 assert_eq!(dedup.smallest_missing_in_interval(0, 0), None);
1567
1568 dedup.insert(1);
1569 assert_eq!(dedup.smallest_missing_in_interval(0, 1), None);
1570
1571 dedup.insert(5);
1572 dedup.insert(7);
1573 assert_eq!(dedup.smallest_missing_in_interval(0, 7), Some(2));
1574 assert_eq!(dedup.smallest_missing_in_interval(5, 7), Some(6));
1575
1576 dedup.insert(2);
1577 assert_eq!(dedup.smallest_missing_in_interval(1, 7), Some(3));
1578
1579 dedup.insert(170);
1580 dedup.insert(172);
1581 dedup.insert(300);
1582 assert_eq!(dedup.smallest_missing_in_interval(170, 172), None);
1583
1584 dedup.insert(500);
1585 assert_eq!(dedup.smallest_missing_in_interval(0, 500), Some(372));
1586 assert_eq!(dedup.smallest_missing_in_interval(0, 373), Some(372));
1587 assert_eq!(dedup.smallest_missing_in_interval(0, 372), None);
1588 }
1589
1590 #[test]
1591 fn pending_acks_first_packet_is_not_considered_reordered() {
1592 let mut acks = PendingAcks::new();
1593 let mut dedup = Dedup::new();
1594 dedup.insert(0);
1595 acks.packet_received(Instant::now(), 0, true, &dedup);
1596 assert!(!acks.immediate_ack_required);
1597 }
1598
1599 #[test]
1600 fn pending_acks_after_immediate_ack_set() {
1601 let mut acks = PendingAcks::new();
1602 let mut dedup = Dedup::new();
1603
1604 dedup.insert(0);
1606 let now = Instant::now();
1607 acks.insert_one(0, now);
1608 acks.packet_received(now, 0, true, &dedup);
1609
1610 assert!(!acks.ranges.is_empty());
1612 assert!(!acks.can_send());
1613
1614 acks.set_immediate_ack_required();
1616 assert!(acks.can_send());
1617 }
1618
1619 #[test]
1620 fn pending_acks_ack_delay() {
1621 let mut acks = PendingAcks::new();
1622 let mut dedup = Dedup::new();
1623
1624 let t1 = Instant::now();
1625 let t2 = t1 + Duration::from_millis(2);
1626 let t3 = t2 + Duration::from_millis(5);
1627 assert_eq!(acks.ack_delay(t1), Duration::from_millis(0));
1628 assert_eq!(acks.ack_delay(t2), Duration::from_millis(0));
1629 assert_eq!(acks.ack_delay(t3), Duration::from_millis(0));
1630
1631 dedup.insert(0);
1633 acks.insert_one(0, t1);
1634 acks.packet_received(t1, 0, true, &dedup);
1635 assert_eq!(acks.ack_delay(t1), Duration::from_millis(0));
1636 assert_eq!(acks.ack_delay(t2), Duration::from_millis(2));
1637 assert_eq!(acks.ack_delay(t3), Duration::from_millis(7));
1638
1639 dedup.insert(3);
1641 acks.insert_one(3, t2);
1642 acks.packet_received(t2, 3, true, &dedup);
1643 assert_eq!(acks.ack_delay(t2), Duration::from_millis(0));
1644 assert_eq!(acks.ack_delay(t3), Duration::from_millis(5));
1645
1646 dedup.insert(2);
1648 acks.insert_one(2, t3);
1649 acks.packet_received(t3, 2, true, &dedup);
1650 assert_eq!(acks.ack_delay(t3), Duration::from_millis(5));
1651 }
1652
1653 #[test]
1654 fn sent_packet_size() {
1655 assert!(size_of::<SentPacket>() <= 128);
1658 }
1659
1660 #[test]
1661 fn pending_new_cids() {
1662 #[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))]
1663 use aws_lc_rs::hmac;
1664 #[cfg(feature = "ring")]
1665 use ring::hmac;
1666
1667 let mut cid_generator = RandomConnectionIdGenerator::new(8);
1668 let mut reset_key = [0; 64];
1669 rand::rng().fill_bytes(&mut reset_key);
1670 let hmac = hmac::Key::new(hmac::HMAC_SHA256, &reset_key);
1671
1672 let cid_a = cid_generator.generate_cid();
1673 let a = IssuedCid {
1674 path_id: PathId::ZERO,
1675 sequence: 1,
1676 id: cid_a,
1677 reset_token: ResetToken::new(&hmac, cid_a),
1678 };
1679 let cid_b = cid_generator.generate_cid();
1680 let b = IssuedCid {
1681 path_id: PathId::ZERO,
1682 sequence: 2,
1683 id: cid_b,
1684 reset_token: ResetToken::new(&hmac, cid_b),
1685 };
1686 let cid_c = cid_generator.generate_cid();
1687 let c = IssuedCid {
1688 path_id: PathId(1),
1689 sequence: 1,
1690 id: cid_c,
1691 reset_token: ResetToken::new(&hmac, cid_c),
1692 };
1693
1694 let mut pending_cids = PendingNewCids::default();
1695
1696 for _ in 0..9 {
1697 let mut input = vec![a, b, c];
1699 input.shuffle(&mut rand::rng());
1700 for cid in input {
1701 pending_cids.push(cid);
1702 }
1703
1704 assert_eq!(pending_cids.pop().map(|i| i.id), Some(a.id));
1706 assert_eq!(pending_cids.pop().map(|i| i.id), Some(b.id));
1707 assert_eq!(pending_cids.pop().map(|i| i.id), Some(c.id));
1708 assert!(pending_cids.pop().is_none());
1709 }
1710 }
1711}