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::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
242    /// Highest received packet number, if any
243    pub(super) largest_received_packet_number: Option<u64>,
244    /// The packet number of the next packet that will be sent, if any. In the Data space, the
245    /// packet number stored here is sometimes skipped by [`PacketNumberFilter`] logic.
246    pub(super) next_packet_number: u64,
247    /// The largest packet number the remote peer acknowledged in an ACK frame.
248    pub(super) largest_acked_packet_pn: Option<u64>,
249    pub(super) largest_acked_packet_send_time: Instant,
250    /// The highest-numbered ACK-eliciting packet we've sent
251    pub(super) largest_ack_eliciting_sent: u64,
252    /// Number of packets in `sent_packets` with numbers above `largest_ack_eliciting_sent`
253    pub(super) unacked_non_ack_eliciting_tail: u64,
254    /// Transmitted but not acked
255    // We use a BTreeMap here so we can efficiently query by range on ACK and for loss detection
256    pub(super) sent_packets: SortedIndexBuffer<SentPacket>,
257    /// Packets that were deemed lost
258    // Older packets are regularly removed in `Connection::drain_lost_packets`.
259    pub(super) lost_packets: SortedIndexBuffer<LostPacket>,
260    /// Number of explicit congestion notification codepoints seen on incoming packets
261    pub(super) ecn_counters: frame::EcnCounts,
262    /// Recent ECN counters sent by the peer in ACK frames
263    ///
264    /// Updated (and inspected) whenever we receive an ACK with a new highest acked packet
265    /// number. Stored per-space to simplify verification, which would otherwise have difficulty
266    /// distinguishing between ECN bleaching and counts having been updated by a near-simultaneous
267    /// ACK already processed in another space.
268    pub(super) ecn_feedback: frame::EcnCounts,
269    /// A PING frame needs to be sent on this path.
270    pub(super) pending_ping: bool,
271    /// Packet numbers to acknowledge.
272    pub(super) pending_acks: PendingAcks,
273    /// An IMMEDIATE_ACK (draft-ietf-quic-ack-frequency) frame needs to be sent on this path.
274    pub(super) pending_immediate_ack: bool,
275    /// Responses to path challenges that need to be sent, on and off-path.
276    ///
277    /// Responses are only tied to the 4-tuple they were received on, not to a specific path
278    /// generation. Whether the response is on or off-path only depends on the path's
279    /// 4-tuple at sending time.
280    pub(super) pending_path_responses: PathResponses,
281    /// Packet deduplicator
282    pub(super) dedup: Dedup,
283
284    //
285    // Loss Detection
286    //
287    /// The time the most recently sent retransmittable packet was sent.
288    pub(super) time_of_last_ack_eliciting_packet: Option<Instant>,
289    /// Earliest time when we might declare a packet lost.
290    ///
291    /// The time at which the earliest sent packet in this space will be considered lost
292    /// based on exceeding the reordering window in time. Only set for packets numbered
293    /// prior to a packet that has been acknowledged.
294    pub(super) loss_time: Option<Instant>,
295    /// Number of tail loss probes to send
296    pub(super) loss_probes: u32,
297
298    /// Packet numbers to skip, only used in the data package space.
299    pn_filter: Option<PacketNumberFilter>,
300}
301
302impl PacketNumberSpace {
303    pub(super) fn new(now: Instant, space: SpaceId, rng: &mut (impl CryptoRng + ?Sized)) -> Self {
304        let pn_filter = match space {
305            SpaceId::Initial | SpaceId::Handshake => None,
306            SpaceId::Data => Some(PacketNumberFilter::new(rng)),
307        };
308        Self {
309            open_status: OpenStatus::default(),
310            largest_received_packet_number: None,
311            next_packet_number: 0,
312            largest_acked_packet_pn: None,
313            largest_acked_packet_send_time: now,
314            largest_ack_eliciting_sent: 0,
315            unacked_non_ack_eliciting_tail: 0,
316            sent_packets: SortedIndexBuffer::new(),
317            lost_packets: SortedIndexBuffer::new(),
318            ecn_counters: frame::EcnCounts::ZERO,
319            ecn_feedback: frame::EcnCounts::ZERO,
320            pending_ping: false,
321            pending_acks: PendingAcks::new(),
322            pending_immediate_ack: false,
323            pending_path_responses: PathResponses::default(),
324            dedup: Default::default(),
325            time_of_last_ack_eliciting_packet: None,
326            loss_time: None,
327            loss_probes: 0,
328            pn_filter,
329        }
330    }
331
332    #[cfg(test)]
333    fn new_deterministic(now: Instant, space: SpaceId) -> Self {
334        let pn_filter = match space {
335            SpaceId::Initial | SpaceId::Handshake => None,
336            SpaceId::Data => Some(PacketNumberFilter::disabled()),
337        };
338        Self {
339            open_status: OpenStatus::default(),
340            largest_received_packet_number: None,
341            next_packet_number: 0,
342            largest_acked_packet_pn: None,
343            largest_acked_packet_send_time: now,
344            largest_ack_eliciting_sent: 0,
345            unacked_non_ack_eliciting_tail: 0,
346            sent_packets: SortedIndexBuffer::new(),
347            lost_packets: SortedIndexBuffer::new(),
348            ecn_counters: frame::EcnCounts::ZERO,
349            ecn_feedback: frame::EcnCounts::ZERO,
350            pending_ping: false,
351            pending_acks: PendingAcks::new(),
352            pending_immediate_ack: false,
353            pending_path_responses: PathResponses::default(),
354            dedup: Default::default(),
355            time_of_last_ack_eliciting_packet: None,
356            loss_time: None,
357            loss_probes: 0,
358            pn_filter,
359        }
360    }
361
362    /// Get the next outgoing packet number in this space
363    ///
364    /// In the Data space, the connection's [`PacketNumberFilter`] must be used rather than calling
365    /// this directly.
366    pub(super) fn get_tx_number(&mut self, rng: &mut (impl CryptoRng + ?Sized)) -> u64 {
367        // TODO: Handle packet number overflow gracefully
368        assert!(self.next_packet_number < 2u64.pow(62));
369        let mut pn = self.next_packet_number;
370        self.next_packet_number += 1;
371
372        // Skip this number if the filter says so, only enabled in the data space
373        if let Some(ref mut filter) = self.pn_filter
374            && filter.skip_pn(pn, rng)
375        {
376            pn = self.next_packet_number;
377            self.next_packet_number += 1;
378        }
379        pn
380    }
381
382    pub(super) fn peek_tx_number(&mut self) -> u64 {
383        let pn = self.next_packet_number;
384        if let Some(ref filter) = self.pn_filter
385            && pn == filter.next_skipped_packet_number
386        {
387            return pn + 1;
388        }
389        pn
390    }
391
392    /// Checks whether a skipped packet number was ACKed.
393    pub(super) fn check_ack(&self, range: std::ops::Range<u64>) -> Result<(), TransportError> {
394        if let Some(ref filter) = self.pn_filter
395            && filter
396                .prev_skipped_packet_number
397                .is_some_and(|pn| range.contains(&pn))
398        {
399            return Err(TransportError::PROTOCOL_VIOLATION("unsent packet acked"));
400        }
401        Ok(())
402    }
403
404    /// Verifies sanity of an ECN block and returns whether congestion was encountered.
405    pub(super) fn detect_ecn(
406        &mut self,
407        newly_acked: u64,
408        ecn: frame::EcnCounts,
409    ) -> Result<bool, &'static str> {
410        let ect0_increase = ecn
411            .ect0
412            .checked_sub(self.ecn_feedback.ect0)
413            .ok_or("peer ECT(0) count regression")?;
414        let ect1_increase = ecn
415            .ect1
416            .checked_sub(self.ecn_feedback.ect1)
417            .ok_or("peer ECT(1) count regression")?;
418        let ce_increase = ecn
419            .ce
420            .checked_sub(self.ecn_feedback.ce)
421            .ok_or("peer CE count regression")?;
422        let total_increase = ect0_increase + ect1_increase + ce_increase;
423        if total_increase < newly_acked {
424            return Err("ECN bleaching");
425        }
426        if (ect0_increase + ce_increase) < newly_acked || ect1_increase != 0 {
427            return Err("ECN corruption");
428        }
429        // If total_increase > newly_acked (which happens when ACKs are lost), this is required by
430        // the draft so that long-term drift does not occur. If =, then the only question is whether
431        // to count CE packets as CE or ECT0. Recording them as CE is more consistent and keeps the
432        // congestion check obvious.
433        self.ecn_feedback = ecn;
434        Ok(ce_increase != 0)
435    }
436
437    /// Stop tracking sent packet `number`, and return what we knew about it
438    pub(super) fn take(&mut self, number: u64) -> Option<SentPacket> {
439        let packet = self.sent_packets.remove(number)?;
440        if !packet.ack_eliciting && number > self.largest_ack_eliciting_sent {
441            self.unacked_non_ack_eliciting_tail =
442                self.unacked_non_ack_eliciting_tail.checked_sub(1).unwrap();
443        }
444        Some(packet)
445    }
446
447    /// May return a packet that should be forgotten
448    pub(super) fn sent(&mut self, number: u64, packet: SentPacket) -> Option<SentPacket> {
449        // Retain state for at most this many non-ACK-eliciting packets sent after the most recently
450        // sent ACK-eliciting packet. We're never guaranteed to receive an ACK for those, and we
451        // can't judge them as lost without an ACK, so to limit memory in applications which receive
452        // packets but don't send ACK-eliciting data for long periods use we must eventually start
453        // forgetting about them, although it might also be reasonable to just kill the connection
454        // due to weird peer behavior.
455        const MAX_UNACKED_NON_ACK_ELICTING_TAIL: u64 = 1_000;
456
457        let mut forgotten = None;
458        if packet.ack_eliciting {
459            self.unacked_non_ack_eliciting_tail = 0;
460            self.largest_ack_eliciting_sent = number;
461        } else if self.unacked_non_ack_eliciting_tail > MAX_UNACKED_NON_ACK_ELICTING_TAIL {
462            let oldest_after_ack_eliciting = self
463                .sent_packets
464                .keys_range((
465                    Bound::Excluded(self.largest_ack_eliciting_sent),
466                    Bound::Unbounded,
467                ))
468                .next()
469                .unwrap();
470            // Per https://www.rfc-editor.org/rfc/rfc9000.html#name-frames-and-frame-types,
471            // non-ACK-eliciting packets must only contain PADDING, ACK, and CONNECTION_CLOSE
472            // frames, which require no special handling on ACK or loss beyond removal from
473            // in-flight counters if padded.
474            let packet = self
475                .sent_packets
476                .remove(oldest_after_ack_eliciting)
477                .unwrap();
478            debug_assert!(!packet.ack_eliciting);
479            forgotten = Some(packet);
480        } else {
481            self.unacked_non_ack_eliciting_tail += 1;
482        }
483
484        self.sent_packets.insert(number, packet);
485        forgotten
486    }
487
488    /// Whether any congestion-controlled packets in this space are not yet acknowledged or lost
489    pub(super) fn has_in_flight(&self) -> bool {
490        // The number of non-congestion-controlled (i.e. size == 0) packets in flight at a time
491        // should be small, since otherwise congestion control wouldn't be effective. Therefore,
492        // this shouldn't need to visit many packets before finishing one way or another.
493        self.sent_packets.values().any(|x| x.size != 0)
494    }
495}
496
497#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
498pub(super) enum OpenStatus {
499    /// The application has not yet been informed of this path.
500    #[default]
501    Pending,
502    /// The application has been informed of this path.
503    Informed,
504}
505
506/// Represents one or more packets subject to retransmission
507#[derive(Debug, Clone)]
508pub(super) struct SentPacket {
509    /// [`PathData::generation`](super::PathData::generation) of the path on which this packet was sent
510    pub(super) path_generation: u64,
511    /// The time the packet was sent.
512    pub(super) time_sent: Instant,
513    /// The number of bytes sent in the packet, not including UDP or IP overhead, but including QUIC
514    /// framing overhead. Zero if this packet is not counted towards congestion control, i.e. not an
515    /// "in flight" packet.
516    pub(super) size: u16,
517    /// Whether an acknowledgement is expected directly in response to this packet.
518    pub(super) ack_eliciting: bool,
519    /// The largest packet number acknowledged by this packet
520    pub(super) largest_acked: FxHashMap<PathId, u64>,
521    /// Data which needs to be retransmitted in case the packet is lost.
522    ///
523    /// These might be retransmitted over any available path in the same [`SpaceKind`].
524    pub(super) retransmits: ThinRetransmits,
525    /// Retransmittable data specific to a path generation.
526    pub(super) path_retransmits: PathRetransmits,
527    /// Metadata for stream frames in a packet
528    ///
529    /// The actual application data is stored with the stream state.
530    pub(super) stream_frames: frame::StreamMetaVec,
531}
532
533/// Represents one or more packets that are deemed lost.
534#[derive(Debug)]
535pub(super) struct LostPacket {
536    /// The time the packet was sent.
537    pub(super) time_sent: Instant,
538}
539
540/// Retransmittable data queue.
541///
542/// Data in this queue must be retransmittable over any path in the same [`SpaceKind`].
543#[allow(unreachable_pub)] // fuzzing only
544#[derive(Debug, Default, Clone)]
545pub struct Retransmits {
546    pub(super) max_data: bool,
547    pub(super) max_stream_id: [bool; 2],
548    pub(super) streams_blocked: [bool; 2],
549    pub(super) reset_stream: Vec<(StreamId, VarInt)>,
550    pub(super) stop_sending: Vec<frame::StopSending>,
551    pub(super) max_stream_data: FxHashSet<StreamId>,
552    pub(super) crypto: VecDeque<frame::Crypto>,
553    pub(super) new_cids: PendingNewCids,
554    pub(super) retire_cids: Vec<(PathId, u64)>,
555    pub(super) ack_frequency: bool,
556    pub(super) handshake_done: bool,
557    /// Whether we should inform the peer we will allow higher [`PathId`]s.
558    pub(super) max_path_id: bool,
559    /// Whether we should inform the peer that their max [`PathId`] is blocking our attempt to open
560    /// new paths.
561    ///
562    /// Stores the remote_max_path_id at the time this was generated.
563    /// This frame is entirely informational, so when it's retransmitted, the remote_max_path_id is
564    /// intentionally not updated to preserve the fact that this was the state of the client at some
565    /// point.
566    pub(super) paths_blocked: Option<PathId>,
567    /// For each enqueued NEW_TOKEN frame, a copy of the path's remote address
568    ///
569    /// There are 2 reasons this is unusual:
570    ///
571    /// - If the path changes, NEW_TOKEN frames bound for the old path are not retransmitted on the
572    ///   new path. That is why this field stores the remote address: so that ones for old paths
573    ///   can be filtered out.
574    /// - If a token is lost, a new randomly generated token is re-transmitted, rather than the
575    ///   original. This is so that if both transmissions are received, the client won't risk
576    ///   sending the same token twice. That is why this field does _not_ store any actual token.
577    ///
578    /// It is true that a QUIC endpoint will only want to effectively have NEW_TOKEN frames
579    /// enqueued for its current path at a given point in time. Based on that, we could conceivably
580    /// change this from a vector to an `Option<(FourTuple, usize)>` or just a `usize` or
581    /// something. However, due to the architecture of noq, it is considerably simpler to not do
582    /// that; consider what such a change would mean for implementing `BitOrAssign` on Self.
583    pub(super) new_tokens: Vec<FourTuple>,
584    /// Paths which need to be abandoned
585    pub(super) path_abandon: BTreeMap<PathId, TransportErrorCode>,
586    /// If a [`frame::PathStatusAvailable`] and [`frame::PathStatusBackup`] need to be sent for a path
587    pub(super) path_status: BTreeSet<PathId>,
588    /// Whether a PATH_CIDS_BLOCKED frame needs to be sent for a path.
589    ///
590    /// Stores the next_seq number for the blocked path. This number can be "outdated" at the time of
591    /// sending when this is a retransmission. This is intentional, as this frame is purely
592    /// informational, and this would preserve this information.
593    pub(super) path_cids_blocked: BTreeMap<PathId, VarInt>,
594
595    // Nat traversal data
596    /// Addresses to report in `ADD_ADDRESS` frames
597    pub(super) add_address: BTreeSet<AddAddress>,
598    /// Address IDs to remove in `REMOVE_ADDRESS` frames
599    pub(super) remove_address: BTreeSet<RemoveAddress>,
600    /// Round and local addresses to advertise in `REACH_OUT` frames
601    pub(super) reach_out: PendingReachOutFrames,
602}
603
604impl Retransmits {
605    pub(super) fn is_empty(&self, streams: &StreamsState) -> bool {
606        let Self {
607            max_data,
608            max_stream_id,
609            streams_blocked,
610            reset_stream,
611            stop_sending,
612            max_stream_data,
613            crypto,
614            new_cids,
615            retire_cids,
616            ack_frequency,
617            handshake_done,
618            max_path_id,
619            paths_blocked,
620            new_tokens,
621            path_abandon,
622            path_status,
623            path_cids_blocked,
624            add_address,
625            remove_address,
626            reach_out,
627        } = &self;
628        !max_data
629            && !max_stream_id.iter().any(|x| *x)
630            && !streams_blocked.iter().any(|x| *x)
631            && reset_stream.is_empty()
632            && stop_sending.is_empty()
633            && max_stream_data
634                .iter()
635                .all(|&id| !streams.can_send_flow_control(id))
636            && crypto.is_empty()
637            && new_cids.is_empty()
638            && retire_cids.is_empty()
639            && !ack_frequency
640            && !handshake_done
641            && !max_path_id
642            && paths_blocked.is_none()
643            && new_tokens.is_empty()
644            && path_abandon.is_empty()
645            && path_status.is_empty()
646            && path_cids_blocked.is_empty()
647            && add_address.is_empty()
648            && remove_address.is_empty()
649            && reach_out.is_empty()
650    }
651}
652
653impl ::std::ops::BitOrAssign for Retransmits {
654    fn bitor_assign(&mut self, rhs: Self) {
655        let Self {
656            max_data,
657            max_stream_id,
658            streams_blocked,
659            reset_stream,
660            stop_sending,
661            max_stream_data,
662            crypto,
663            new_cids,
664            retire_cids,
665            ack_frequency,
666            handshake_done,
667            max_path_id,
668            paths_blocked,
669            new_tokens,
670            mut path_abandon,
671            mut path_status,
672            mut path_cids_blocked,
673            add_address,
674            remove_address,
675            mut reach_out,
676        } = rhs;
677
678        // We reduce in-stream head-of-line blocking by queueing retransmits before other data for
679        // STREAM and CRYPTO frames.
680        self.max_data |= max_data;
681        for dir in Dir::iter() {
682            self.max_stream_id[dir as usize] |= max_stream_id[dir as usize];
683            self.streams_blocked[dir as usize] |= streams_blocked[dir as usize];
684        }
685        self.reset_stream.extend_from_slice(&reset_stream);
686        self.stop_sending.extend_from_slice(&stop_sending);
687        self.max_stream_data.extend(&max_stream_data);
688        for crypto in crypto.into_iter().rev() {
689            self.crypto.push_front(crypto);
690        }
691        self.new_cids.extend(&new_cids);
692        self.retire_cids.extend(retire_cids);
693        self.ack_frequency |= ack_frequency;
694        self.handshake_done |= handshake_done;
695        self.max_path_id |= max_path_id;
696        self.paths_blocked = cmp::max(self.paths_blocked, paths_blocked);
697        self.new_tokens.extend_from_slice(&new_tokens);
698        self.path_abandon.append(&mut path_abandon);
699        self.path_status.append(&mut path_status);
700        self.path_cids_blocked.append(&mut path_cids_blocked);
701        self.add_address.extend(add_address.iter().copied());
702        self.remove_address.extend(remove_address.iter().copied());
703        self.reach_out.append(&mut reach_out);
704    }
705}
706
707impl ::std::ops::BitOrAssign<ThinRetransmits> for Retransmits {
708    fn bitor_assign(&mut self, rhs: ThinRetransmits) {
709        let ThinRetransmits { retransmits } = rhs;
710        if let Some(retransmits) = retransmits {
711            self.bitor_assign(*retransmits)
712        }
713    }
714}
715
716impl ::std::iter::FromIterator<Self> for Retransmits {
717    fn from_iter<T>(iter: T) -> Self
718    where
719        T: IntoIterator<Item = Self>,
720    {
721        let mut result = Self::default();
722        for packet in iter {
723            result |= packet;
724        }
725        result
726    }
727}
728
729/// The queue of new CIDs to be transmitted to the peer.
730///
731/// This queue is always sorted, so that popping off the last item is always the lowest
732/// sequence number of the lowest path ID. Which is the CID you want to be issued next.
733///
734/// This is but a newtype over a `Vec` to enforce the sorted invariant.
735#[derive(Clone, Debug, Default)]
736pub(super) struct PendingNewCids {
737    /// The CIDs themselves.
738    cids: Vec<IssuedCid>,
739    /// Whether [`Self::cids`] is sorted or not.
740    sorted: bool,
741}
742
743impl PendingNewCids {
744    /// Inserts an issued CID into the queue.
745    pub(super) fn push(&mut self, cid: IssuedCid) {
746        self.cids.push(cid);
747        self.sorted = false;
748    }
749
750    /// Pops the next issued CID to transmit from the queue.
751    pub(super) fn pop(&mut self) -> Option<IssuedCid> {
752        if !mem::replace(&mut self.sorted, true) {
753            self.cids
754                .sort_by_key(|cid| cmp::Reverse((cid.path_id, cid.sequence)));
755        }
756        self.cids.pop()
757    }
758
759    pub(super) fn is_empty(&self) -> bool {
760        self.cids.is_empty()
761    }
762
763    pub(super) fn extend(&mut self, other: &Self) {
764        self.cids.extend(&other.cids);
765        self.sorted = false;
766    }
767
768    pub(super) fn retain<F>(&mut self, f: F)
769    where
770        F: FnMut(&IssuedCid) -> bool,
771    {
772        self.cids.retain(f);
773    }
774}
775
776/// Logically a Vec of REACH_OUT frames queued for transmit.
777///
778/// This keeps track of the highest round ID and automatically drops frames with a lower
779/// round ID.
780///
781/// The API is directly modelled on [`Vec`].
782#[derive(Debug, Default, Clone)]
783pub(crate) struct PendingReachOutFrames {
784    /// The round ID of the REACH_OUT frames currently pending.
785    round: VarInt,
786    /// The REACH_OUT frames, always all having the same round ID.
787    frames: Vec<frame::ReachOut>,
788}
789
790impl PendingReachOutFrames {
791    pub(crate) fn len(&self) -> usize {
792        self.frames.len()
793    }
794
795    pub(crate) fn is_empty(&self) -> bool {
796        self.frames.is_empty()
797    }
798
799    pub(crate) fn push(&mut self, frame: frame::ReachOut) {
800        if frame.round < self.round {
801            return;
802        } else if frame.round > self.round {
803            self.round = frame.round;
804            self.frames.clear();
805        }
806        self.frames.push(frame);
807    }
808
809    pub(crate) fn append(&mut self, other: &mut Self) {
810        if other.round < self.round {
811            other.frames.clear();
812            return;
813        } else if other.round > self.round {
814            self.round = other.round;
815            self.frames.clear();
816        }
817        self.frames.append(&mut other.frames);
818    }
819
820    pub(crate) fn pop_if(
821        &mut self,
822        predicate: impl FnOnce(&mut frame::ReachOut) -> bool,
823    ) -> Option<frame::ReachOut> {
824        self.frames.pop_if(predicate)
825    }
826}
827
828impl FromIterator<frame::ReachOut> for PendingReachOutFrames {
829    fn from_iter<T: IntoIterator<Item = frame::ReachOut>>(iter: T) -> Self {
830        let iter = iter.into_iter();
831        let size_hint = iter.size_hint();
832        let mut this = Self {
833            round: Default::default(),
834            frames: Vec::with_capacity(size_hint.1.unwrap_or(size_hint.0)),
835        };
836        for frame in iter {
837            this.push(frame);
838        }
839        this
840    }
841}
842
843/// A variant of `Retransmits` which only allocates storage when required
844#[derive(Debug, Default, Clone)]
845pub(super) struct ThinRetransmits {
846    retransmits: Option<Box<Retransmits>>,
847}
848
849impl ThinRetransmits {
850    /// Returns `true` if no retransmits are necessary
851    pub(super) fn is_empty(&self, streams: &StreamsState) -> bool {
852        match &self.retransmits {
853            Some(retransmits) => retransmits.is_empty(streams),
854            None => true,
855        }
856    }
857
858    /// Returns a reference to the retransmits stored in this box
859    pub(super) fn get(&self) -> Option<&Retransmits> {
860        self.retransmits.as_deref()
861    }
862
863    /// Returns a mutable reference to the retransmits stored in this box
864    pub(super) fn get_mut(&mut self) -> Option<&mut Retransmits> {
865        self.retransmits.as_deref_mut()
866    }
867
868    /// Returns a mutable reference to the stored retransmits
869    ///
870    /// This function will allocate a backing storage if required.
871    pub(super) fn get_or_create(&mut self) -> &mut Retransmits {
872        if self.retransmits.is_none() {
873            self.retransmits = Some(Box::default());
874        }
875        self.retransmits.as_deref_mut().unwrap()
876    }
877}
878
879/// RFC4303-style sliding window packet number deduplicator.
880///
881/// A contiguous bitfield, where each bit corresponds to a packet number and the rightmost bit is
882/// always set. A set bit represents a packet that has been successfully authenticated. Bits left of
883/// the window are assumed to be set.
884///
885/// ```text
886/// ...xxxxxxxxx 1 0
887///     ^        ^ ^
888/// window highest next
889/// ```
890#[derive(Debug, Default)]
891pub(super) struct Dedup {
892    window: Window,
893    /// Lowest packet number higher than all yet authenticated.
894    next: u64,
895}
896
897impl Dedup {
898    /// Construct an empty window positioned at the start.
899    #[cfg(test)]
900    pub(super) fn new() -> Self {
901        Self { window: 0, next: 0 }
902    }
903
904    /// Highest packet number authenticated.
905    fn highest(&self) -> u64 {
906        self.next - 1
907    }
908
909    /// Record a newly authenticated packet number.
910    ///
911    /// Returns whether the packet might be a duplicate.
912    pub(super) fn insert(&mut self, packet: u64) -> bool {
913        if let Some(diff) = packet.checked_sub(self.next) {
914            // Right of window
915            self.window = ((self.window << 1) | 1)
916                .checked_shl(cmp::min(diff, u64::from(u32::MAX)) as u32)
917                .unwrap_or(0);
918            self.next = packet + 1;
919            false
920        } else if self.highest() - packet < WINDOW_SIZE {
921            // Within window
922            if let Some(bit) = (self.highest() - packet).checked_sub(1) {
923                // < highest
924                let mask = 1 << bit;
925                let duplicate = self.window & mask != 0;
926                self.window |= mask;
927                duplicate
928            } else {
929                // == highest
930                true
931            }
932        } else {
933            // Left of window
934            true
935        }
936    }
937
938    /// Returns the packet number of the smallest packet missing between the provided interval
939    ///
940    /// If there are no missing packets, returns `None`
941    fn smallest_missing_in_interval(&self, lower_bound: u64, upper_bound: u64) -> Option<u64> {
942        debug_assert!(lower_bound <= upper_bound);
943        debug_assert!(upper_bound <= self.highest());
944        const BITFIELD_SIZE: u64 = Window::BITS as u64;
945
946        // Since we already know the packets at the boundaries have been received, we only need to
947        // check those in between them (this removes the necessity of extra logic to deal with the
948        // highest packet, which is stored outside the bitfield)
949        let lower_bound = lower_bound + 1;
950        let upper_bound = upper_bound.saturating_sub(1);
951
952        // Note: the offsets are counted from the right
953        // The highest packet is not included in the bitfield, so we subtract 1 to account for that
954        let start_offset = (self.highest() - upper_bound).max(1) - 1;
955        if start_offset >= BITFIELD_SIZE {
956            // The start offset is outside of the window. All packets outside of the window are
957            // considered to be received.
958            return None;
959        }
960
961        let end_offset_exclusive = self.highest().saturating_sub(lower_bound);
962
963        // The range is clamped at the edge of the window, because any earlier packets are
964        // considered to be received
965        let range_len = end_offset_exclusive
966            .saturating_sub(start_offset)
967            .min(BITFIELD_SIZE);
968        if range_len == 0 {
969            return None;
970        }
971
972        // Ensure the shift is within bounds (we already know start_offset < BITFIELD_SIZE,
973        // because of the early return)
974        let mask = if range_len == BITFIELD_SIZE {
975            u128::MAX
976        } else {
977            ((1u128 << range_len) - 1) << start_offset
978        };
979        let gaps = !self.window & mask;
980
981        let smallest_missing_offset = 128 - gaps.leading_zeros() as u64;
982        let smallest_missing_packet = self.highest() - smallest_missing_offset;
983
984        if smallest_missing_packet <= upper_bound {
985            Some(smallest_missing_packet)
986        } else {
987            None
988        }
989    }
990
991    /// Returns true if there are any missing packets between the provided interval
992    ///
993    /// The provided packet numbers must have been received before calling this function
994    fn missing_in_interval(&self, lower_bound: u64, upper_bound: u64) -> bool {
995        self.smallest_missing_in_interval(lower_bound, upper_bound)
996            .is_some()
997    }
998}
999
1000/// Inner bitfield type.
1001///
1002/// Because QUIC never reuses packet numbers, this only needs to be large enough to deal with
1003/// packets that are reordered but still delivered in a timely manner.
1004type Window = u128;
1005
1006/// Number of packets tracked by `Dedup`.
1007const WINDOW_SIZE: u64 = 1 + size_of::<Window>() as u64 * 8;
1008/// Indicates which data is available for sending
1009///
1010/// This applies to a particular space ID that was queried and all refers to on-path data.
1011#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1012pub(super) struct SendableFrames {
1013    /// Whether there are ACK frames to send, these are not ack-eliciting.
1014    pub(super) acks: bool,
1015    /// Whether there is a CONNECTION_CLOSE to send, this is not ack-eliciting.
1016    pub(super) close: bool,
1017    /// Whether there are any frames that must be sent on this specific space.
1018    ///
1019    /// A space here in the sense of a QUIC Multipath packet number space: `Initial`,
1020    /// `Handshake` and all `Data(PathId)` spaces.
1021    ///
1022    /// These are ack-eliciting. Some frames are scheduled per path, e.g. PING,
1023    /// IMMEDIATE_ACK, PATH_CHALLENGE or PATH_RESPONSE.
1024    pub(super) space_specific: bool,
1025    /// Whether there are any other frames to send, these are ack-eliciting.
1026    pub(super) other: bool,
1027}
1028
1029impl SendableFrames {
1030    /// Returns that no data is available for sending
1031    pub(super) fn empty() -> Self {
1032        Self {
1033            acks: false,
1034            close: false,
1035            space_specific: false,
1036            other: false,
1037        }
1038    }
1039
1040    /// Whether an ack-eliciting packet will be sent.
1041    pub(super) fn is_ack_eliciting(&self) -> bool {
1042        let Self {
1043            acks: _,
1044            close,
1045            space_specific,
1046            other,
1047        } = *self;
1048        if close {
1049            // No ack-eliciting frames are included with a CONNECTION_CLOSE, only acks.
1050            return false;
1051        }
1052        space_specific || other
1053    }
1054
1055    /// Whether no data is sendable.
1056    pub(super) fn is_empty(&self) -> bool {
1057        let Self {
1058            acks,
1059            close,
1060            space_specific,
1061            other,
1062        } = *self;
1063        !acks && !close && !space_specific && !other
1064    }
1065}
1066
1067impl ::std::ops::BitOrAssign for SendableFrames {
1068    fn bitor_assign(&mut self, rhs: Self) {
1069        let Self {
1070            acks,
1071            close,
1072            space_specific,
1073            other,
1074        } = rhs;
1075
1076        self.acks |= acks;
1077        self.close |= close;
1078        self.space_specific |= space_specific;
1079        self.other |= other;
1080    }
1081}
1082
1083#[derive(Debug)]
1084pub(super) struct PendingAcks {
1085    /// Whether we should send an ACK immediately, even if that means sending an ACK-only packet
1086    ///
1087    /// When `immediate_ack_required` is false, the normal behavior is to send ACK frames only when
1088    /// there is other data to send, or when the `MaxAckDelay` timer expires.
1089    immediate_ack_required: bool,
1090    /// The number of ack-eliciting packets received since the last ACK frame was sent
1091    ///
1092    /// Once the count _exceeds_ `ack_eliciting_threshold`, an immediate ACK is required
1093    ack_eliciting_since_last_ack_sent: u64,
1094    non_ack_eliciting_since_last_ack_sent: u64,
1095    ack_eliciting_threshold: u64,
1096    /// The reordering threshold, controlling how we respond to out-of-order ack-eliciting packets
1097    ///
1098    /// Different values enable different behavior:
1099    ///
1100    /// * `0`: no special action is taken
1101    /// * `1`: an ACK is immediately sent if it is out-of-order according to RFC 9000
1102    /// * `>1`: an ACK is immediately sent if it is out-of-order according to the ACK frequency draft
1103    reordering_threshold: u64,
1104    /// The earliest ack-eliciting packet since the last ACK was sent, used to calculate the moment
1105    /// upon which `max_ack_delay` elapses
1106    earliest_ack_eliciting_since_last_ack_sent: Option<Instant>,
1107    /// Packet number ranges for which to still send acknowledgements.
1108    ///
1109    /// These are packet number ranges of ack-eliciting packets the peer has sent and which
1110    /// need to be acknowledged.  Packet numbers are only removed from here once the peer has
1111    /// acknowledged the ACKs for them.
1112    ranges: ArrayRangeSet,
1113    /// The largest packet number received and the time it was received
1114    ///
1115    /// Used to calculate ACK delay in [`PendingAcks::ack_delay`].
1116    largest_packet: Option<(u64, Instant)>,
1117    /// The ack-eliciting packet we have received with the largest packet number
1118    largest_ack_eliciting_packet: Option<u64>,
1119    /// The largest acknowledged packet number sent in an ACK frame
1120    largest_acked: Option<u64>,
1121}
1122
1123impl PendingAcks {
1124    fn new() -> Self {
1125        Self {
1126            immediate_ack_required: false,
1127            ack_eliciting_since_last_ack_sent: 0,
1128            non_ack_eliciting_since_last_ack_sent: 0,
1129            ack_eliciting_threshold: 1,
1130            reordering_threshold: 1,
1131            earliest_ack_eliciting_since_last_ack_sent: None,
1132            ranges: Default::default(),
1133            largest_packet: Default::default(),
1134            largest_ack_eliciting_packet: Default::default(),
1135            largest_acked: Default::default(),
1136        }
1137    }
1138
1139    pub(super) fn set_ack_frequency_params(&mut self, frame: &frame::AckFrequency) {
1140        self.ack_eliciting_threshold = frame.ack_eliciting_threshold.into_inner();
1141        self.reordering_threshold = frame.reordering_threshold.into_inner();
1142    }
1143
1144    pub(super) fn set_immediate_ack_required(&mut self) {
1145        self.immediate_ack_required = true;
1146    }
1147
1148    pub(super) fn on_max_ack_delay_timeout(&mut self) {
1149        self.immediate_ack_required = self.ack_eliciting_since_last_ack_sent > 0;
1150    }
1151
1152    pub(super) fn max_ack_delay_timeout(&self, max_ack_delay: Duration) -> Option<Instant> {
1153        self.earliest_ack_eliciting_since_last_ack_sent
1154            .map(|earliest_unacked| earliest_unacked + max_ack_delay)
1155    }
1156
1157    /// Whether any ACK frames SHOULD be sent
1158    ///
1159    /// This is used in the top-level [`Connection::space_can_send`], so determines if a
1160    /// packet will be built. It is often possible to construct new ACK ranges to send
1161    /// before this returns `true`. This results in more ACK frames being sent, and
1162    /// processing those at the receiver costs CPU for very little improvements.
1163    ///
1164    /// [`Connection::space_can_send`]: super::Connection::space_can_send
1165    pub(super) fn can_send(&self) -> bool {
1166        self.immediate_ack_required && !self.ranges.is_empty()
1167    }
1168
1169    /// Returns the delay since the packet with the largest packet number was received
1170    pub(super) fn ack_delay(&self, now: Instant) -> Duration {
1171        self.largest_packet
1172            .map_or_else(Duration::default, |(_, received)| now - received)
1173    }
1174
1175    /// Handle receipt of a new packet
1176    ///
1177    /// Returns true if the max ack delay timer should be armed
1178    pub(super) fn packet_received(
1179        &mut self,
1180        now: Instant,
1181        packet_number: u64,
1182        ack_eliciting: bool,
1183        dedup: &Dedup,
1184    ) -> bool {
1185        if !ack_eliciting {
1186            self.non_ack_eliciting_since_last_ack_sent += 1;
1187            return false;
1188        }
1189
1190        let prev_largest_ack_eliciting = self.largest_ack_eliciting_packet.unwrap_or(0);
1191
1192        // Track largest ack-eliciting packet
1193        self.largest_ack_eliciting_packet = self
1194            .largest_ack_eliciting_packet
1195            .map(|pn| pn.max(packet_number))
1196            .or(Some(packet_number));
1197
1198        // Handle ack_eliciting_threshold
1199        self.ack_eliciting_since_last_ack_sent += 1;
1200        self.immediate_ack_required |=
1201            self.ack_eliciting_since_last_ack_sent > self.ack_eliciting_threshold;
1202
1203        // Handle out-of-order packets
1204        self.immediate_ack_required |=
1205            self.is_out_of_order(packet_number, prev_largest_ack_eliciting, dedup);
1206
1207        // Arm max_ack_delay timer if necessary
1208        if self.earliest_ack_eliciting_since_last_ack_sent.is_none() && !self.can_send() {
1209            self.earliest_ack_eliciting_since_last_ack_sent = Some(now);
1210            return true;
1211        }
1212
1213        false
1214    }
1215
1216    fn is_out_of_order(
1217        &self,
1218        packet_number: u64,
1219        prev_largest_ack_eliciting: u64,
1220        dedup: &Dedup,
1221    ) -> bool {
1222        match self.reordering_threshold {
1223            0 => false,
1224            1 => {
1225                // From https://www.rfc-editor.org/rfc/rfc9000#section-13.2.1-7
1226                packet_number < prev_largest_ack_eliciting
1227                    || dedup.missing_in_interval(prev_largest_ack_eliciting, packet_number)
1228            }
1229            _ => {
1230                // From acknowledgement frequency draft, section 6.1: send an ACK immediately if
1231                // doing so would cause the sender to detect a new packet loss
1232                let Some((largest_acked, largest_unacked)) =
1233                    self.largest_acked.zip(self.largest_ack_eliciting_packet)
1234                else {
1235                    return false;
1236                };
1237                if self.reordering_threshold > largest_acked {
1238                    return false;
1239                }
1240                // The largest packet number that could be declared lost without a new ACK being
1241                // sent
1242                let largest_reported = largest_acked - self.reordering_threshold + 1;
1243                let Some(smallest_missing_unreported) =
1244                    dedup.smallest_missing_in_interval(largest_reported, largest_unacked)
1245                else {
1246                    return false;
1247                };
1248                largest_unacked - smallest_missing_unreported >= self.reordering_threshold
1249            }
1250        }
1251    }
1252
1253    /// Should be called whenever ACKs have been sent
1254    ///
1255    /// This will suppress sending further ACKs until additional ACK eliciting frames arrive
1256    pub(super) fn acks_sent(&mut self) {
1257        // It is possible (though unlikely) that the ACKs we just sent do not cover all the
1258        // ACK-eliciting packets we have received (e.g. if there is not enough room in the packet to
1259        // fit all the ranges). To keep things simple, however, we assume they do. If there are
1260        // indeed some ACKs that weren't covered, the packets might be ACKed later anyway, because
1261        // they are still contained in `self.ranges`. If we somehow fail to send the ACKs at a later
1262        // moment, the peer will assume the packets got lost and will retransmit their frames in a
1263        // new packet, which is suboptimal, because we already received them. Our assumption here is
1264        // that simplicity results in code that is more performant, even in the presence of
1265        // occasional redundant retransmits.
1266        self.immediate_ack_required = false;
1267        self.ack_eliciting_since_last_ack_sent = 0;
1268        self.non_ack_eliciting_since_last_ack_sent = 0;
1269        self.earliest_ack_eliciting_since_last_ack_sent = None;
1270        self.largest_acked = self.largest_ack_eliciting_packet;
1271    }
1272
1273    /// Insert one packet that needs to be acknowledged
1274    pub(super) fn insert_one(&mut self, packet: u64, now: Instant) {
1275        self.ranges.insert_one(packet);
1276
1277        if self.largest_packet.is_none_or(|(pn, _)| packet > pn) {
1278            self.largest_packet = Some((packet, now));
1279        }
1280
1281        if self.ranges.range_count() > MAX_ACK_BLOCKS {
1282            self.ranges.pop_min();
1283        }
1284    }
1285
1286    /// Remove ACKs of packets numbered at or below `max` from the set of pending ACKs
1287    pub(super) fn subtract_below(&mut self, max: u64) {
1288        self.ranges.remove(0..(max + 1));
1289    }
1290
1291    /// Returns the set of currently pending ACK ranges
1292    pub(super) fn ranges(&self) -> &ArrayRangeSet {
1293        &self.ranges
1294    }
1295
1296    /// Queue an ACK if a significant number of non-ACK-eliciting packets have not yet been
1297    /// acknowledged
1298    ///
1299    /// Should be called immediately before a non-probing packet is composed, when we've already
1300    /// committed to sending a packet regardless.
1301    pub(super) fn maybe_ack_non_eliciting(&mut self) {
1302        // If we're going to send a packet anyway, and we've received a significant number of
1303        // non-ACK-eliciting packets, then include an ACK to help the peer perform timely loss
1304        // detection even if they're not sending any ACK-eliciting packets themselves. Exact
1305        // threshold chosen somewhat arbitrarily.
1306        const LAZY_ACK_THRESHOLD: u64 = 10;
1307        if self.non_ack_eliciting_since_last_ack_sent > LAZY_ACK_THRESHOLD {
1308            self.immediate_ack_required = true;
1309        }
1310    }
1311}
1312
1313/// Helper for mitigating [optimistic ACK attacks]
1314///
1315/// A malicious peer could prompt the local application to begin a large data transfer, and then
1316/// send ACKs without first waiting for data to be received. This could defeat congestion control,
1317/// allowing the connection to consume disproportionate resources. We therefore occasionally skip
1318/// packet numbers, and classify any ACK referencing a skipped packet number as a transport error.
1319///
1320/// Skipped packet numbers occur only in the application data space (where costly transfers might
1321/// take place) and are distributed exponentially to reflect the reduced likelihood and impact of
1322/// bad behavior from a peer that has been well-behaved for an extended period.
1323///
1324/// ACKs for packet numbers that have not yet been allocated are also a transport error, but an
1325/// attacker with knowledge of the congestion control algorithm in use could time falsified ACKs to
1326/// arrive after the packets they reference are sent.
1327///
1328/// [optimistic ACK attacks]: https://www.rfc-editor.org/rfc/rfc9000.html#name-optimistic-ack-attack
1329pub(super) struct PacketNumberFilter {
1330    /// Next outgoing packet number to skip
1331    next_skipped_packet_number: u64,
1332    /// Most recently skipped packet number
1333    prev_skipped_packet_number: Option<u64>,
1334    /// Next packet number to skip is randomly selected from 2^n..2^n+1
1335    exponent: u32,
1336}
1337
1338impl PacketNumberFilter {
1339    pub(super) fn new(rng: &mut (impl CryptoRng + ?Sized)) -> Self {
1340        // First skipped PN is in 0..64
1341        let exponent = 6;
1342        Self {
1343            next_skipped_packet_number: rng.random_range(0..2u64.saturating_pow(exponent)),
1344            prev_skipped_packet_number: None,
1345            exponent,
1346        }
1347    }
1348
1349    #[cfg(test)]
1350    pub(super) fn disabled() -> Self {
1351        Self {
1352            next_skipped_packet_number: u64::MAX,
1353            prev_skipped_packet_number: None,
1354            exponent: u32::MAX,
1355        }
1356    }
1357
1358    /// Whether to use the provided packet number (false) or to skip it (true)
1359    pub(super) fn skip_pn(&mut self, n: u64, rng: &mut (impl CryptoRng + ?Sized)) -> bool {
1360        if n != self.next_skipped_packet_number {
1361            return false;
1362        }
1363
1364        trace!("skipping pn {n}");
1365        // Skip this packet number, and choose the next one to skip
1366        self.prev_skipped_packet_number = Some(self.next_skipped_packet_number);
1367        let next_exponent = self.exponent.saturating_add(1);
1368        self.next_skipped_packet_number = rng
1369            .random_range(2u64.saturating_pow(self.exponent)..2u64.saturating_pow(next_exponent));
1370        self.exponent = next_exponent;
1371        true
1372    }
1373}
1374
1375/// Ensures we can always fit all our ACKs in a single minimum-MTU packet with room to spare
1376const MAX_ACK_BLOCKS: usize = 64;
1377
1378#[cfg(test)]
1379mod test {
1380    use rand::Rng;
1381    use rand::seq::SliceRandom;
1382
1383    use crate::token::ResetToken;
1384    use crate::{ConnectionIdGenerator, RandomConnectionIdGenerator};
1385
1386    use super::*;
1387
1388    #[test]
1389    fn sanity() {
1390        let mut dedup = Dedup::new();
1391        assert!(!dedup.insert(0));
1392        assert_eq!(dedup.next, 1);
1393        assert_eq!(dedup.window, 0b1);
1394        assert!(dedup.insert(0));
1395        assert_eq!(dedup.next, 1);
1396        assert_eq!(dedup.window, 0b1);
1397        assert!(!dedup.insert(1));
1398        assert_eq!(dedup.next, 2);
1399        assert_eq!(dedup.window, 0b11);
1400        assert!(!dedup.insert(2));
1401        assert_eq!(dedup.next, 3);
1402        assert_eq!(dedup.window, 0b111);
1403        assert!(!dedup.insert(4));
1404        assert_eq!(dedup.next, 5);
1405        assert_eq!(dedup.window, 0b11110);
1406        assert!(!dedup.insert(7));
1407        assert_eq!(dedup.next, 8);
1408        assert_eq!(dedup.window, 0b1111_0100);
1409        assert!(dedup.insert(4));
1410        assert!(!dedup.insert(3));
1411        assert_eq!(dedup.next, 8);
1412        assert_eq!(dedup.window, 0b1111_1100);
1413        assert!(!dedup.insert(6));
1414        assert_eq!(dedup.next, 8);
1415        assert_eq!(dedup.window, 0b1111_1101);
1416        assert!(!dedup.insert(5));
1417        assert_eq!(dedup.next, 8);
1418        assert_eq!(dedup.window, 0b1111_1111);
1419    }
1420
1421    #[test]
1422    fn happypath() {
1423        let mut dedup = Dedup::new();
1424        for i in 0..(2 * WINDOW_SIZE) {
1425            assert!(!dedup.insert(i));
1426            for j in 0..=i {
1427                assert!(dedup.insert(j));
1428            }
1429        }
1430    }
1431
1432    #[test]
1433    fn jump() {
1434        let mut dedup = Dedup::new();
1435        dedup.insert(2 * WINDOW_SIZE);
1436        assert!(dedup.insert(WINDOW_SIZE));
1437        assert_eq!(dedup.next, 2 * WINDOW_SIZE + 1);
1438        assert_eq!(dedup.window, 0);
1439        assert!(!dedup.insert(WINDOW_SIZE + 1));
1440        assert_eq!(dedup.next, 2 * WINDOW_SIZE + 1);
1441        assert_eq!(dedup.window, 1 << (WINDOW_SIZE - 2));
1442    }
1443
1444    #[test]
1445    fn dedup_has_missing() {
1446        let mut dedup = Dedup::new();
1447
1448        dedup.insert(0);
1449        assert!(!dedup.missing_in_interval(0, 0));
1450
1451        dedup.insert(1);
1452        assert!(!dedup.missing_in_interval(0, 1));
1453
1454        dedup.insert(3);
1455        assert!(dedup.missing_in_interval(1, 3));
1456
1457        dedup.insert(4);
1458        assert!(!dedup.missing_in_interval(3, 4));
1459        assert!(dedup.missing_in_interval(0, 4));
1460
1461        dedup.insert(2);
1462        assert!(!dedup.missing_in_interval(0, 4));
1463    }
1464
1465    #[test]
1466    fn dedup_outside_of_window_has_missing() {
1467        let mut dedup = Dedup::new();
1468
1469        for i in 0..140 {
1470            dedup.insert(i);
1471        }
1472
1473        // 0 and 4 are outside of the window
1474        assert!(!dedup.missing_in_interval(0, 4));
1475        dedup.insert(160);
1476        assert!(!dedup.missing_in_interval(0, 4));
1477        assert!(!dedup.missing_in_interval(0, 140));
1478        assert!(dedup.missing_in_interval(0, 160));
1479    }
1480
1481    #[test]
1482    fn dedup_smallest_missing() {
1483        let mut dedup = Dedup::new();
1484
1485        dedup.insert(0);
1486        assert_eq!(dedup.smallest_missing_in_interval(0, 0), None);
1487
1488        dedup.insert(1);
1489        assert_eq!(dedup.smallest_missing_in_interval(0, 1), None);
1490
1491        dedup.insert(5);
1492        dedup.insert(7);
1493        assert_eq!(dedup.smallest_missing_in_interval(0, 7), Some(2));
1494        assert_eq!(dedup.smallest_missing_in_interval(5, 7), Some(6));
1495
1496        dedup.insert(2);
1497        assert_eq!(dedup.smallest_missing_in_interval(1, 7), Some(3));
1498
1499        dedup.insert(170);
1500        dedup.insert(172);
1501        dedup.insert(300);
1502        assert_eq!(dedup.smallest_missing_in_interval(170, 172), None);
1503
1504        dedup.insert(500);
1505        assert_eq!(dedup.smallest_missing_in_interval(0, 500), Some(372));
1506        assert_eq!(dedup.smallest_missing_in_interval(0, 373), Some(372));
1507        assert_eq!(dedup.smallest_missing_in_interval(0, 372), None);
1508    }
1509
1510    #[test]
1511    fn pending_acks_first_packet_is_not_considered_reordered() {
1512        let mut acks = PendingAcks::new();
1513        let mut dedup = Dedup::new();
1514        dedup.insert(0);
1515        acks.packet_received(Instant::now(), 0, true, &dedup);
1516        assert!(!acks.immediate_ack_required);
1517    }
1518
1519    #[test]
1520    fn pending_acks_after_immediate_ack_set() {
1521        let mut acks = PendingAcks::new();
1522        let mut dedup = Dedup::new();
1523
1524        // Receive ack-eliciting packet
1525        dedup.insert(0);
1526        let now = Instant::now();
1527        acks.insert_one(0, now);
1528        acks.packet_received(now, 0, true, &dedup);
1529
1530        // Sanity check
1531        assert!(!acks.ranges.is_empty());
1532        assert!(!acks.can_send());
1533
1534        // Can send ACK after max_ack_delay exceeded
1535        acks.set_immediate_ack_required();
1536        assert!(acks.can_send());
1537    }
1538
1539    #[test]
1540    fn pending_acks_ack_delay() {
1541        let mut acks = PendingAcks::new();
1542        let mut dedup = Dedup::new();
1543
1544        let t1 = Instant::now();
1545        let t2 = t1 + Duration::from_millis(2);
1546        let t3 = t2 + Duration::from_millis(5);
1547        assert_eq!(acks.ack_delay(t1), Duration::from_millis(0));
1548        assert_eq!(acks.ack_delay(t2), Duration::from_millis(0));
1549        assert_eq!(acks.ack_delay(t3), Duration::from_millis(0));
1550
1551        // In-order packet
1552        dedup.insert(0);
1553        acks.insert_one(0, t1);
1554        acks.packet_received(t1, 0, true, &dedup);
1555        assert_eq!(acks.ack_delay(t1), Duration::from_millis(0));
1556        assert_eq!(acks.ack_delay(t2), Duration::from_millis(2));
1557        assert_eq!(acks.ack_delay(t3), Duration::from_millis(7));
1558
1559        // Out of order (higher than expected)
1560        dedup.insert(3);
1561        acks.insert_one(3, t2);
1562        acks.packet_received(t2, 3, true, &dedup);
1563        assert_eq!(acks.ack_delay(t2), Duration::from_millis(0));
1564        assert_eq!(acks.ack_delay(t3), Duration::from_millis(5));
1565
1566        // Out of order (lower than expected, so previous instant is kept)
1567        dedup.insert(2);
1568        acks.insert_one(2, t3);
1569        acks.packet_received(t3, 2, true, &dedup);
1570        assert_eq!(acks.ack_delay(t3), Duration::from_millis(5));
1571    }
1572
1573    #[test]
1574    fn sent_packet_size() {
1575        // The tracking state of sent packets should be minimal, and not grow
1576        // over time.
1577        assert!(size_of::<SentPacket>() <= 128);
1578    }
1579
1580    #[test]
1581    fn pending_new_cids() {
1582        #[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))]
1583        use aws_lc_rs::hmac;
1584        #[cfg(feature = "ring")]
1585        use ring::hmac;
1586
1587        let mut cid_generator = RandomConnectionIdGenerator::new(8);
1588        let mut reset_key = [0; 64];
1589        rand::rng().fill_bytes(&mut reset_key);
1590        let hmac = hmac::Key::new(hmac::HMAC_SHA256, &reset_key);
1591
1592        let cid_a = cid_generator.generate_cid();
1593        let a = IssuedCid {
1594            path_id: PathId::ZERO,
1595            sequence: 1,
1596            id: cid_a,
1597            reset_token: ResetToken::new(&hmac, cid_a),
1598        };
1599        let cid_b = cid_generator.generate_cid();
1600        let b = IssuedCid {
1601            path_id: PathId::ZERO,
1602            sequence: 2,
1603            id: cid_b,
1604            reset_token: ResetToken::new(&hmac, cid_b),
1605        };
1606        let cid_c = cid_generator.generate_cid();
1607        let c = IssuedCid {
1608            path_id: PathId(1),
1609            sequence: 1,
1610            id: cid_c,
1611            reset_token: ResetToken::new(&hmac, cid_c),
1612        };
1613
1614        let mut pending_cids = PendingNewCids::default();
1615
1616        for _ in 0..9 {
1617            // Push CIDs in a random order
1618            let mut input = vec![a, b, c];
1619            input.shuffle(&mut rand::rng());
1620            for cid in input {
1621                pending_cids.push(cid);
1622            }
1623
1624            // Pop order is always the same
1625            assert_eq!(pending_cids.pop().map(|i| i.id), Some(a.id));
1626            assert_eq!(pending_cids.pop().map(|i| i.id), Some(b.id));
1627            assert_eq!(pending_cids.pop().map(|i| i.id), Some(c.id));
1628            assert!(pending_cids.pop().is_none());
1629        }
1630    }
1631}