noq_proto/connection/
spaces.rs

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    /// Data to send
25    pub(super) pending: Retransmits,
26
27    /// Multipath packet number spaces
28    ///
29    /// Each [`PathId`] has it's own [`PacketNumberSpace`].  Only the [`SpaceId::Data`] can
30    /// have multiple packet number spaces, the other spaces only have a number space for
31    /// `PathId::ZERO`, which is populated at creation.
32    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    /// Returns the [`PacketNumberSpace`] for a path
54    ///
55    /// When multipath is disabled use [`PathId::ZERO`].
56    pub(super) fn path_space(&self, path_id: PathId) -> Option<&PacketNumberSpace> {
57        self.number_spaces.get(&path_id)
58    }
59
60    /// Returns a mutable reference to the [`PacketNumberSpace`] for a path
61    ///
62    /// When multipath is disabled use [`PathId::ZERO`].
63    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    /// Returns the [`PacketNumberSpace`] for a path
68    ///
69    /// When multipath is disabled use `PathId::ZERO`.
70    // TODO(flub): Note that this only exists as `&mut self` because it creates a new
71    //    [`PacketNumberSpace`] if one is not yet available for a path.  This forces a few
72    //    more `&mut` references to users than strictly needed.  An alternative would be to
73    //    return an Option but that would need to be handled for all callers.  This could be
74    //    worth exploring once we have all the main multipath bits fitted.
75    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    /// Queue data for a tail loss probe (or anti-amplification deadlock prevention) packet
86    ///
87    /// Probes are sent similarly to normal packets when an expected ACK has not arrived. We never
88    /// deem a packet lost until we receive an ACK that should have included it, but if a trailing
89    /// run of packets (or their ACKs) are lost, this might not happen in a timely fashion. We send
90    /// probe packets to force an ACK, and exempt them from congestion control to prevent a deadlock
91    /// when the congestion window is filled with lost tail packets.
92    ///
93    /// We prefer to send new data, to make the most efficient use of bandwidth. If there's no data
94    /// waiting to be sent, then we retransmit in-flight data to reduce odds of loss. If there's no
95    /// in-flight data either, we're probably a client guarding against a handshake
96    /// anti-amplification deadlock and we just make something up.
97    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            // The probe should be ACKed without delay (should only be used in the Data space and
105            // when the peer supports the acknowledgement frequency extension)
106            self.for_path(path_id).pending_immediate_ack = true;
107        }
108
109        // We prefer to send new data to make most efficient use of bandwidth.
110        if !self.pending.is_empty(streams) {
111            // There's real data to send here, no need to make something up
112            return;
113        }
114
115        // Retransmit data from the oldest in-flight data from any path
116        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                // Remove retransmitted data from the old packet so we don't end up retransmitting
123                // it *again* even if the copy we're sending now gets acknowledged.
124                self.pending |= mem::take(&mut packet.retransmits);
125                return;
126            }
127        }
128
129        // Nothing new to send and nothing to retransmit, so fall back on a ping. This should only
130        // happen in rare cases during the handshake when the server becomes blocked by
131        // anti-amplification.
132        if !self.for_path(path_id).pending_immediate_ack {
133            self.for_path(path_id).pending_ping = true;
134        }
135    }
136
137    /// Whether there is anything to send in this space
138    ///
139    /// For the data space [`Connection::can_send_1rtt`] also needs to be consulted. Prefer
140    /// to use [`Connection::space_can_send`] which handles this.
141    ///
142    /// [`Connection::can_send_1rtt`]: super::Connection::can_send_1rtt
143    /// [`Connection::space_can_send`]: super::Connection::space_can_send
144    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/// The three QUIC packet number space kinds
176///
177/// Unlike [`SpaceId`], this always has exactly three variants — it represents the
178/// encryption level / space kind, not a specific packet number space identity.
179#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
180pub(crate) enum SpaceKind {
181    /// Initial packets (client and server).
182    Initial = 0,
183    /// Handshake packets.
184    Handshake = 1,
185    /// Data (1-RTT and 0-RTT)
186    Data = 2,
187}
188
189impl SpaceKind {
190    /// Returns the encryption level for this space kind.
191    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
213/// The state of a single packet number space.
214///
215/// In RFC9000 there are 3 packet number spaces: Initial, Handshake and Data. In QUIC
216/// Multipath there are multiple packet number spaces for Data, each identified by a
217/// [`PathId`].
218///
219/// This contains the state for a packet number space which is not specific to the 4-tuple
220/// this space is currently using. The 4-tuple specific state, like congestion controller,
221/// pacing, ECN, MTU etc, is stored in [`PathData`].
222///
223/// Note that the `Initial`, `Handshake` and `Data(PathId(0))` space all share the same
224/// [`PathData`].
225///
226/// You should access this via [`PacketSpace::for_path`].
227///
228/// [`PathData`]: super::paths::PathData
229pub(super) struct PacketNumberSpace {
230    /// Whether the path has already been considered opened from an application perspective.
231    ///
232    /// This means, for paths other than the original [`PathId::ZERO`], a first path
233    /// challenge has been responded to, regardless of the initial validation status of the
234    /// path. This state is irreversible, since it's not affected by the path being closed.
235    ///
236    /// Sending a PATH_CHALLENGE and receiving a valid response before the application is
237    /// informed of the path, is a way to ensure the path is usable before it is
238    /// reported. This is not required by the spec, and in the future might be changed for
239    /// simply requiring a first ack'd packet.
240    pub(super) open_status: OpenStatus,
241    /// The QUIC-MULTIPATH path status.
242    ///
243    /// This field is unused for the Initial and Handshake spaces, and when multipath is not
244    /// negotiated.
245    pub(super) status: PathStatusState,
246
247    /// Highest received packet number, if any
248    pub(super) largest_received_packet_number: Option<u64>,
249    /// The packet number of the next packet that will be sent, if any. In the Data space, the
250    /// packet number stored here is sometimes skipped by [`PacketNumberFilter`] logic.
251    pub(super) next_packet_number: u64,
252    /// The largest packet number the remote peer acknowledged in an ACK frame.
253    pub(super) largest_acked_packet_pn: Option<u64>,
254    pub(super) largest_acked_packet_send_time: Instant,
255    /// The highest-numbered ACK-eliciting packet we've sent
256    pub(super) largest_ack_eliciting_sent: u64,
257    /// Number of packets in `sent_packets` with numbers above `largest_ack_eliciting_sent`
258    pub(super) unacked_non_ack_eliciting_tail: u64,
259    /// Transmitted but not acked
260    // We use a BTreeMap here so we can efficiently query by range on ACK and for loss detection
261    pub(super) sent_packets: SortedIndexBuffer<SentPacket>,
262    /// Packets that were deemed lost
263    // Older packets are regularly removed in `Connection::drain_lost_packets`.
264    pub(super) lost_packets: SortedIndexBuffer<LostPacket>,
265    /// Number of explicit congestion notification codepoints seen on incoming packets
266    pub(super) ecn_counters: frame::EcnCounts,
267    /// Recent ECN counters sent by the peer in ACK frames
268    ///
269    /// Updated (and inspected) whenever we receive an ACK with a new highest acked packet
270    /// number. Stored per-space to simplify verification, which would otherwise have difficulty
271    /// distinguishing between ECN bleaching and counts having been updated by a near-simultaneous
272    /// ACK already processed in another space.
273    pub(super) ecn_feedback: frame::EcnCounts,
274    /// A PING frame needs to be sent on this path.
275    pub(super) pending_ping: bool,
276    /// Packet numbers to acknowledge.
277    pub(super) pending_acks: PendingAcks,
278    /// An IMMEDIATE_ACK (draft-ietf-quic-ack-frequency) frame needs to be sent on this path.
279    pub(super) pending_immediate_ack: bool,
280    /// Responses to path challenges that need to be sent, on and off-path.
281    ///
282    /// Responses are only tied to the 4-tuple they were received on, not to a specific path
283    /// generation. Whether the response is on or off-path only depends on the path's
284    /// 4-tuple at sending time.
285    pub(super) pending_path_responses: PathResponses,
286    /// Packet deduplicator
287    pub(super) dedup: Dedup,
288
289    //
290    // Loss Detection
291    /// The time the most recently sent retransmittable packet was sent.
292    pub(super) time_of_last_ack_eliciting_packet: Option<Instant>,
293    /// Earliest time when we might declare a packet lost.
294    ///
295    /// The time at which the earliest sent packet in this space will be considered lost
296    /// based on exceeding the reordering window in time. Only set for packets numbered
297    /// prior to a packet that has been acknowledged.
298    pub(super) loss_time: Option<Instant>,
299    /// Number of tail loss probes to send
300    pub(super) loss_probes: u32,
301
302    /// Packet numbers to skip, only used in the data package space.
303    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    /// Get the next outgoing packet number in this space
377    ///
378    /// In the Data space, the connection's [`PacketNumberFilter`] must be used rather than calling
379    /// this directly.
380    pub(super) fn get_tx_number(&mut self, rng: &mut (impl CryptoRng + ?Sized)) -> u64 {
381        // TODO: Handle packet number overflow gracefully
382        assert!(self.next_packet_number < 2u64.pow(62));
383        let mut pn = self.next_packet_number;
384        self.next_packet_number += 1;
385
386        // Skip this number if the filter says so, only enabled in the data space
387        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    /// Checks whether a skipped packet number was ACKed.
407    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    /// Verifies sanity of an ECN block and returns whether congestion was encountered.
419    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        // If total_increase > newly_acked (which happens when ACKs are lost), this is required by
444        // the draft so that long-term drift does not occur. If =, then the only question is whether
445        // to count CE packets as CE or ECT0. Recording them as CE is more consistent and keeps the
446        // congestion check obvious.
447        self.ecn_feedback = ecn;
448        Ok(ce_increase != 0)
449    }
450
451    /// Stop tracking sent packet `number`, and return what we knew about it
452    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    /// May return a packet that should be forgotten
462    pub(super) fn sent(&mut self, number: u64, packet: SentPacket) -> Option<SentPacket> {
463        // Retain state for at most this many non-ACK-eliciting packets sent after the most recently
464        // sent ACK-eliciting packet. We're never guaranteed to receive an ACK for those, and we
465        // can't judge them as lost without an ACK, so to limit memory in applications which receive
466        // packets but don't send ACK-eliciting data for long periods use we must eventually start
467        // forgetting about them, although it might also be reasonable to just kill the connection
468        // due to weird peer behavior.
469        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            // Per https://www.rfc-editor.org/rfc/rfc9000.html#name-frames-and-frame-types,
485            // non-ACK-eliciting packets must only contain PADDING, ACK, and CONNECTION_CLOSE
486            // frames, which require no special handling on ACK or loss beyond removal from
487            // in-flight counters if padded.
488            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    /// Whether any congestion-controlled packets in this space are not yet acknowledged or lost
503    pub(super) fn has_in_flight(&self) -> bool {
504        // The number of non-congestion-controlled (i.e. size == 0) packets in flight at a time
505        // should be small, since otherwise congestion control wouldn't be effective. Therefore,
506        // this shouldn't need to visit many packets before finishing one way or another.
507        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    /// The application has not yet been informed of this path.
514    #[default]
515    Pending,
516    /// The application has been informed of this path.
517    Informed,
518}
519
520/// State for QUIC-MULTIPATH PATH_STATUS_AVAILABLE and PATH_STATUS_BACKUP frames
521#[derive(Debug, Clone, Default)]
522pub(super) struct PathStatusState {
523    /// The local status
524    local_status: PathStatus,
525    /// Local sequence number, for both PATH_STATUS_AVAILABLE and PATH_STATUS_BACKUP
526    ///
527    /// This is the number of the *next* path status frame to be sent.
528    local_seq: VarInt,
529    /// The status set by the remote
530    remote_status: Option<(VarInt, PathStatus)>,
531}
532
533impl PathStatusState {
534    /// To be called on received PATH_STATUS_AVAILABLE/PATH_STATUS_BACKUP frames
535    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    /// Updates the local status
547    ///
548    /// If the local status changed, the previous value is returned
549    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/// The QUIC-MULTIPATH path status
564///
565/// See section "3.3 Path Status Management":
566/// <https://quicwg.org/multipath/draft-ietf-quic-multipath.html#name-path-status-management>
567#[cfg_attr(test, derive(test_strategy::Arbitrary))]
568#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
569pub enum PathStatus {
570    /// Paths marked with as available will be used when scheduling packets
571    ///
572    /// If multiple paths are available, packets will be scheduled on whichever has
573    /// capacity.
574    #[default]
575    Available,
576    /// Paths marked as backup will only be used if there are no available paths
577    ///
578    /// If the max_idle_timeout is specified the path will be kept alive so that it does not
579    /// expire.
580    Backup,
581}
582
583/// Represents one or more packets subject to retransmission
584#[derive(Debug, Clone)]
585pub(super) struct SentPacket {
586    /// [`PathData::generation`](super::PathData::generation) of the path on which this packet was
587    /// sent
588    pub(super) path_generation: u64,
589    /// The time the packet was sent.
590    pub(super) time_sent: Instant,
591    /// The number of bytes sent in the packet, not including UDP or IP overhead, but including
592    /// QUIC framing overhead. Zero if this packet is not counted towards congestion control,
593    /// i.e. not an "in flight" packet.
594    pub(super) size: u16,
595    /// Whether an acknowledgement is expected directly in response to this packet.
596    pub(super) ack_eliciting: bool,
597    /// The largest packet number acknowledged by this packet
598    pub(super) largest_acked: FxHashMap<PathId, u64>,
599    /// Data which needs to be retransmitted in case the packet is lost.
600    ///
601    /// These might be retransmitted over any available path in the same [`SpaceKind`].
602    pub(super) retransmits: ThinRetransmits,
603    /// Retransmittable data specific to a path generation.
604    pub(super) path_retransmits: PathRetransmits,
605    /// Metadata for stream frames in a packet
606    ///
607    /// The actual application data is stored with the stream state.
608    pub(super) stream_frames: frame::StreamMetaVec,
609}
610
611/// Represents one or more packets that are deemed lost.
612#[derive(Debug)]
613pub(super) struct LostPacket {
614    /// The time the packet was sent.
615    pub(super) time_sent: Instant,
616}
617
618/// Retransmittable data queue.
619///
620/// Data in this queue must be retransmittable over any path in the same [`SpaceKind`].
621#[allow(unreachable_pub)] // fuzzing only
622#[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    /// Whether we should inform the peer we will allow higher [`PathId`]s.
636    pub(super) max_path_id: bool,
637    /// Whether we should inform the peer that their max [`PathId`] is blocking our attempt to open
638    /// new paths.
639    ///
640    /// Stores the remote_max_path_id at the time this was generated.
641    /// This frame is entirely informational, so when it's retransmitted, the remote_max_path_id is
642    /// intentionally not updated to preserve the fact that this was the state of the client at
643    /// some point.
644    pub(super) paths_blocked: Option<PathId>,
645    /// For each enqueued NEW_TOKEN frame, a copy of the path's remote address
646    ///
647    /// There are 2 reasons this is unusual:
648    ///
649    /// - If the path changes, NEW_TOKEN frames bound for the old path are not retransmitted on the
650    ///   new path. That is why this field stores the remote address: so that ones for old paths
651    ///   can be filtered out.
652    /// - If a token is lost, a new randomly generated token is re-transmitted, rather than the
653    ///   original. This is so that if both transmissions are received, the client won't risk
654    ///   sending the same token twice. That is why this field does _not_ store any actual token.
655    ///
656    /// It is true that a QUIC endpoint will only want to effectively have NEW_TOKEN frames
657    /// enqueued for its current path at a given point in time. Based on that, we could conceivably
658    /// change this from a vector to an `Option<(FourTuple, usize)>` or just a `usize` or
659    /// something. However, due to the architecture of noq, it is considerably simpler to not do
660    /// that; consider what such a change would mean for implementing `BitOrAssign` on Self.
661    pub(super) new_tokens: Vec<FourTuple>,
662    /// Paths which need to be abandoned
663    pub(super) path_abandon: BTreeMap<PathId, TransportErrorCode>,
664    /// If a [`frame::PathStatusAvailable`] and [`frame::PathStatusBackup`] need to be sent for a
665    /// path
666    pub(super) path_status: BTreeSet<PathId>,
667    /// Whether a PATH_CIDS_BLOCKED frame needs to be sent for a path.
668    ///
669    /// Stores the next_seq number for the blocked path. This number can be "outdated" at the time
670    /// of sending when this is a retransmission. This is intentional, as this frame is purely
671    /// informational, and this would preserve this information.
672    pub(super) path_cids_blocked: BTreeMap<PathId, VarInt>,
673
674    // Nat traversal data
675    /// Addresses to report in `ADD_ADDRESS` frames
676    pub(super) add_address: BTreeSet<AddAddress>,
677    /// Address IDs to remove in `REMOVE_ADDRESS` frames
678    pub(super) remove_address: BTreeSet<RemoveAddress>,
679    /// Round and local addresses to advertise in `REACH_OUT` frames
680    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        // We reduce in-stream head-of-line blocking by queueing retransmits before other data for
758        // STREAM and CRYPTO frames.
759        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/// The queue of new CIDs to be transmitted to the peer.
809///
810/// This queue is always sorted, so that popping off the last item is always the lowest
811/// sequence number of the lowest path ID. Which is the CID you want to be issued next.
812///
813/// This is but a newtype over a `Vec` to enforce the sorted invariant.
814#[derive(Clone, Debug, Default)]
815pub(super) struct PendingNewCids {
816    /// The CIDs themselves.
817    cids: Vec<IssuedCid>,
818    /// Whether [`Self::cids`] is sorted or not.
819    sorted: bool,
820}
821
822impl PendingNewCids {
823    /// Inserts an issued CID into the queue.
824    pub(super) fn push(&mut self, cid: IssuedCid) {
825        self.cids.push(cid);
826        self.sorted = false;
827    }
828
829    /// Pops the next issued CID to transmit from the queue.
830    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/// Logically a Vec of REACH_OUT frames queued for transmit.
856///
857/// This keeps track of the highest round ID and automatically drops frames with a lower
858/// round ID.
859///
860/// The API is directly modelled on [`Vec`].
861#[derive(Debug, Default, Clone)]
862pub(crate) struct PendingReachOutFrames {
863    /// The round ID of the REACH_OUT frames currently pending.
864    round: VarInt,
865    /// The REACH_OUT frames, always all having the same round ID.
866    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/// A variant of `Retransmits` which only allocates storage when required
923#[derive(Debug, Default, Clone)]
924pub(super) struct ThinRetransmits {
925    retransmits: Option<Box<Retransmits>>,
926}
927
928impl ThinRetransmits {
929    /// Returns `true` if no retransmits are necessary
930    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    /// Returns a reference to the retransmits stored in this box
938    pub(super) fn get(&self) -> Option<&Retransmits> {
939        self.retransmits.as_deref()
940    }
941
942    /// Returns a mutable reference to the retransmits stored in this box
943    pub(super) fn get_mut(&mut self) -> Option<&mut Retransmits> {
944        self.retransmits.as_deref_mut()
945    }
946
947    /// Returns a mutable reference to the stored retransmits
948    ///
949    /// This function will allocate a backing storage if required.
950    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/// RFC4303-style sliding window packet number deduplicator.
959///
960/// A contiguous bitfield, where each bit corresponds to a packet number and the rightmost bit is
961/// always set. A set bit represents a packet that has been successfully authenticated. Bits left of
962/// the window are assumed to be set.
963///
964/// ```text
965/// ...xxxxxxxxx 1 0
966///     ^        ^ ^
967/// window highest next
968/// ```
969#[derive(Debug, Default)]
970pub(super) struct Dedup {
971    window: Window,
972    /// Lowest packet number higher than all yet authenticated.
973    next: u64,
974}
975
976impl Dedup {
977    /// Construct an empty window positioned at the start.
978    #[cfg(test)]
979    pub(super) fn new() -> Self {
980        Self { window: 0, next: 0 }
981    }
982
983    /// Highest packet number authenticated.
984    fn highest(&self) -> u64 {
985        self.next - 1
986    }
987
988    /// Record a newly authenticated packet number.
989    ///
990    /// Returns whether the packet might be a duplicate.
991    pub(super) fn insert(&mut self, packet: u64) -> bool {
992        if let Some(diff) = packet.checked_sub(self.next) {
993            // Right of window
994            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            // Within window
1001            if let Some(bit) = (self.highest() - packet).checked_sub(1) {
1002                // < highest
1003                let mask = 1 << bit;
1004                let duplicate = self.window & mask != 0;
1005                self.window |= mask;
1006                duplicate
1007            } else {
1008                // == highest
1009                true
1010            }
1011        } else {
1012            // Left of window
1013            true
1014        }
1015    }
1016
1017    /// Returns the packet number of the smallest packet missing between the provided interval
1018    ///
1019    /// If there are no missing packets, returns `None`
1020    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        // Since we already know the packets at the boundaries have been received, we only need to
1026        // check those in between them (this removes the necessity of extra logic to deal with the
1027        // highest packet, which is stored outside the bitfield)
1028        let lower_bound = lower_bound + 1;
1029        let upper_bound = upper_bound.saturating_sub(1);
1030
1031        // Note: the offsets are counted from the right
1032        // The highest packet is not included in the bitfield, so we subtract 1 to account for that
1033        let start_offset = (self.highest() - upper_bound).max(1) - 1;
1034        if start_offset >= BITFIELD_SIZE {
1035            // The start offset is outside of the window. All packets outside of the window are
1036            // considered to be received.
1037            return None;
1038        }
1039
1040        let end_offset_exclusive = self.highest().saturating_sub(lower_bound);
1041
1042        // The range is clamped at the edge of the window, because any earlier packets are
1043        // considered to be received
1044        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        // Ensure the shift is within bounds (we already know start_offset < BITFIELD_SIZE,
1052        // because of the early return)
1053        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    /// Returns true if there are any missing packets between the provided interval
1071    ///
1072    /// The provided packet numbers must have been received before calling this function
1073    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
1079/// Inner bitfield type.
1080///
1081/// Because QUIC never reuses packet numbers, this only needs to be large enough to deal with
1082/// packets that are reordered but still delivered in a timely manner.
1083type Window = u128;
1084
1085/// Number of packets tracked by `Dedup`.
1086const WINDOW_SIZE: u64 = 1 + size_of::<Window>() as u64 * 8;
1087/// Indicates which data is available for sending
1088///
1089/// This applies to a particular space ID that was queried and all refers to on-path data.
1090#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1091pub(super) struct SendableFrames {
1092    /// Whether there are ACK frames to send, these are not ack-eliciting.
1093    pub(super) acks: bool,
1094    /// Whether there is a CONNECTION_CLOSE to send, this is not ack-eliciting.
1095    pub(super) close: bool,
1096    /// Whether there are any frames that must be sent on this specific space.
1097    ///
1098    /// A space here in the sense of a QUIC Multipath packet number space: `Initial`,
1099    /// `Handshake` and all `Data(PathId)` spaces.
1100    ///
1101    /// These are ack-eliciting. Some frames are scheduled per path, e.g. PING,
1102    /// IMMEDIATE_ACK, PATH_CHALLENGE or PATH_RESPONSE.
1103    pub(super) space_specific: bool,
1104    /// Whether there are any other frames to send, these are ack-eliciting.
1105    pub(super) other: bool,
1106}
1107
1108impl SendableFrames {
1109    /// Returns that no data is available for sending
1110    pub(super) fn empty() -> Self {
1111        Self {
1112            acks: false,
1113            close: false,
1114            space_specific: false,
1115            other: false,
1116        }
1117    }
1118
1119    /// Whether an ack-eliciting packet will be sent.
1120    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            // No ack-eliciting frames are included with a CONNECTION_CLOSE, only acks.
1129            return false;
1130        }
1131        space_specific || other
1132    }
1133
1134    /// Whether no data is sendable.
1135    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    /// Whether we should send an ACK immediately, even if that means sending an ACK-only packet
1165    ///
1166    /// When `immediate_ack_required` is false, the normal behavior is to send ACK frames only when
1167    /// there is other data to send, or when the `MaxAckDelay` timer expires.
1168    immediate_ack_required: bool,
1169    /// The number of ack-eliciting packets received since the last ACK frame was sent
1170    ///
1171    /// Once the count _exceeds_ `ack_eliciting_threshold`, an immediate ACK is required
1172    ack_eliciting_since_last_ack_sent: u64,
1173    non_ack_eliciting_since_last_ack_sent: u64,
1174    ack_eliciting_threshold: u64,
1175    /// The reordering threshold, controlling how we respond to out-of-order ack-eliciting packets
1176    ///
1177    /// Different values enable different behavior:
1178    ///
1179    /// * `0`: no special action is taken
1180    /// * `1`: an ACK is immediately sent if it is out-of-order according to RFC 9000
1181    /// * `>1`: an ACK is immediately sent if it is out-of-order according to the ACK frequency
1182    ///   draft
1183    reordering_threshold: u64,
1184    /// The earliest ack-eliciting packet since the last ACK was sent, used to calculate the moment
1185    /// upon which `max_ack_delay` elapses
1186    earliest_ack_eliciting_since_last_ack_sent: Option<Instant>,
1187    /// Packet number ranges for which to still send acknowledgements.
1188    ///
1189    /// These are packet number ranges of ack-eliciting packets the peer has sent and which
1190    /// need to be acknowledged.  Packet numbers are only removed from here once the peer has
1191    /// acknowledged the ACKs for them.
1192    ranges: ArrayRangeSet,
1193    /// The largest packet number received and the time it was received
1194    ///
1195    /// Used to calculate ACK delay in [`PendingAcks::ack_delay`].
1196    largest_packet: Option<(u64, Instant)>,
1197    /// The ack-eliciting packet we have received with the largest packet number
1198    largest_ack_eliciting_packet: Option<u64>,
1199    /// The largest acknowledged packet number sent in an ACK frame
1200    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    /// Whether any ACK frames SHOULD be sent
1238    ///
1239    /// This is used in the top-level [`Connection::space_can_send`], so determines if a
1240    /// packet will be built. It is often possible to construct new ACK ranges to send
1241    /// before this returns `true`. This results in more ACK frames being sent, and
1242    /// processing those at the receiver costs CPU for very little improvements.
1243    ///
1244    /// [`Connection::space_can_send`]: super::Connection::space_can_send
1245    pub(super) fn can_send(&self) -> bool {
1246        self.immediate_ack_required && !self.ranges.is_empty()
1247    }
1248
1249    /// Returns the delay since the packet with the largest packet number was received
1250    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    /// Handle receipt of a new packet
1256    ///
1257    /// Returns true if the max ack delay timer should be armed
1258    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        // Track largest ack-eliciting packet
1273        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        // Handle ack_eliciting_threshold
1279        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        // Handle out-of-order packets
1284        self.immediate_ack_required |=
1285            self.is_out_of_order(packet_number, prev_largest_ack_eliciting, dedup);
1286
1287        // Arm max_ack_delay timer if necessary
1288        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                // From https://www.rfc-editor.org/rfc/rfc9000#section-13.2.1-7
1306                packet_number < prev_largest_ack_eliciting
1307                    || dedup.missing_in_interval(prev_largest_ack_eliciting, packet_number)
1308            }
1309            _ => {
1310                // From acknowledgement frequency draft, section 6.1: send an ACK immediately if
1311                // doing so would cause the sender to detect a new packet loss
1312                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                // The largest packet number that could be declared lost without a new ACK being
1321                // sent
1322                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    /// Should be called whenever ACKs have been sent
1334    ///
1335    /// This will suppress sending further ACKs until additional ACK eliciting frames arrive
1336    pub(super) fn acks_sent(&mut self) {
1337        // It is possible (though unlikely) that the ACKs we just sent do not cover all the
1338        // ACK-eliciting packets we have received (e.g. if there is not enough room in the packet to
1339        // fit all the ranges). To keep things simple, however, we assume they do. If there are
1340        // indeed some ACKs that weren't covered, the packets might be ACKed later anyway, because
1341        // they are still contained in `self.ranges`. If we somehow fail to send the ACKs at a later
1342        // moment, the peer will assume the packets got lost and will retransmit their frames in a
1343        // new packet, which is suboptimal, because we already received them. Our assumption here is
1344        // that simplicity results in code that is more performant, even in the presence of
1345        // occasional redundant retransmits.
1346        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    /// Insert one packet that needs to be acknowledged
1354    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    /// Remove ACKs of packets numbered at or below `max` from the set of pending ACKs
1367    pub(super) fn subtract_below(&mut self, max: u64) {
1368        self.ranges.remove(0..(max + 1));
1369    }
1370
1371    /// Returns the set of currently pending ACK ranges
1372    pub(super) fn ranges(&self) -> &ArrayRangeSet {
1373        &self.ranges
1374    }
1375
1376    /// Queue an ACK if a significant number of non-ACK-eliciting packets have not yet been
1377    /// acknowledged
1378    ///
1379    /// Should be called immediately before a non-probing packet is composed, when we've already
1380    /// committed to sending a packet regardless.
1381    pub(super) fn maybe_ack_non_eliciting(&mut self) {
1382        // If we're going to send a packet anyway, and we've received a significant number of
1383        // non-ACK-eliciting packets, then include an ACK to help the peer perform timely loss
1384        // detection even if they're not sending any ACK-eliciting packets themselves. Exact
1385        // threshold chosen somewhat arbitrarily.
1386        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
1393/// Helper for mitigating [optimistic ACK attacks]
1394///
1395/// A malicious peer could prompt the local application to begin a large data transfer, and then
1396/// send ACKs without first waiting for data to be received. This could defeat congestion control,
1397/// allowing the connection to consume disproportionate resources. We therefore occasionally skip
1398/// packet numbers, and classify any ACK referencing a skipped packet number as a transport error.
1399///
1400/// Skipped packet numbers occur only in the application data space (where costly transfers might
1401/// take place) and are distributed exponentially to reflect the reduced likelihood and impact of
1402/// bad behavior from a peer that has been well-behaved for an extended period.
1403///
1404/// ACKs for packet numbers that have not yet been allocated are also a transport error, but an
1405/// attacker with knowledge of the congestion control algorithm in use could time falsified ACKs to
1406/// arrive after the packets they reference are sent.
1407///
1408/// [optimistic ACK attacks]: https://www.rfc-editor.org/rfc/rfc9000.html#name-optimistic-ack-attack
1409pub(super) struct PacketNumberFilter {
1410    /// Next outgoing packet number to skip
1411    next_skipped_packet_number: u64,
1412    /// Most recently skipped packet number
1413    prev_skipped_packet_number: Option<u64>,
1414    /// Next packet number to skip is randomly selected from 2^n..2^n+1
1415    exponent: u32,
1416}
1417
1418impl PacketNumberFilter {
1419    pub(super) fn new(rng: &mut (impl CryptoRng + ?Sized)) -> Self {
1420        // First skipped PN is in 0..64
1421        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    /// Whether to use the provided packet number (false) or to skip it (true)
1439    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        // Skip this packet number, and choose the next one to skip
1446        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
1455/// Ensures we can always fit all our ACKs in a single minimum-MTU packet with room to spare
1456const 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        // 0 and 4 are outside of the window
1554        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        // Receive ack-eliciting packet
1605        dedup.insert(0);
1606        let now = Instant::now();
1607        acks.insert_one(0, now);
1608        acks.packet_received(now, 0, true, &dedup);
1609
1610        // Sanity check
1611        assert!(!acks.ranges.is_empty());
1612        assert!(!acks.can_send());
1613
1614        // Can send ACK after max_ack_delay exceeded
1615        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        // In-order packet
1632        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        // Out of order (higher than expected)
1640        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        // Out of order (lower than expected, so previous instant is kept)
1647        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        // The tracking state of sent packets should be minimal, and not grow
1656        // over time.
1657        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            // Push CIDs in a random order
1698            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            // Pop order is always the same
1705            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}