Skip to content

Commit fd322b8

Browse files
committed
Make path_congestion_check functionally pure
1 parent 7034b27 commit fd322b8

2 files changed

Lines changed: 35 additions & 11 deletions

File tree

noq-proto/src/connection/mod.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,8 +1492,16 @@ impl Connection {
14921492
// we need them in `path_congestion_check`.
14931493
self.path_data_mut(path_id).update_pacer(now);
14941494
let congestion_blocked =
1495-
self.path_congestion_check(space_id, path_id, transmit, &can_send, now);
1495+
self.path_congestion_check(space_id, path_id, transmit, &can_send);
14961496
if congestion_blocked != PathBlocked::No {
1497+
if let PathBlocked::Pacing(delay) = congestion_blocked {
1498+
let resume_time = now + delay;
1499+
self.timers.set_if_earlier(
1500+
Timer::PerPath(path_id, PathTimer::Pacing),
1501+
resume_time,
1502+
self.qlog.with_time(now),
1503+
);
1504+
}
14971505
// Previous iterations of this loop may have built packets already.
14981506
return match last_packet_number {
14991507
Some(pn) => PollPathSpaceStatus::WrotePacket {
@@ -1882,14 +1890,22 @@ impl Connection {
18821890
false
18831891
}
18841892

1885-
/// Checks if creating a new datagram would be blocked by congestion control
1893+
/// Checks if creating a new datagram would be blocked by congestion control or pacing.
1894+
///
1895+
/// This is a pure function - it doesn't modify state, so neither does it update the pacer
1896+
/// nor does it set the pacing timer. Callers need to handle that:
1897+
///
1898+
/// - To make new pacing tokens available, the pacer needs to be update before a call to
1899+
/// this function using [`PathData::update_pacer`].
1900+
/// - When this function returns [`PathBlocked::Pacing`], and you decide to actually send
1901+
/// the given packet, call [`TimerTable::set_if_earlier`] with [`PathTimer::Pacing`]
1902+
/// and given delay relative to the time used for `update_pacer`.
18861903
fn path_congestion_check(
18871904
&mut self,
18881905
space_id: SpaceId,
18891906
path_id: PathId,
18901907
transmit: &TransmitBuf<'_>,
18911908
can_send: &SendableFrames,
1892-
now: Instant,
18931909
) -> PathBlocked {
18941910
// Anti-amplification is only based on `total_sent`, which gets updated after
18951911
// the transmit is sent. Therefore we pass the amount of bytes for datagrams
@@ -1926,16 +1942,10 @@ impl Connection {
19261942

19271943
// Pacing check.
19281944
if let Some(delay) = self.path_data(path_id).pacing_delay(bytes_to_send) {
1929-
let resume_time = now + delay;
1930-
self.timers.set(
1931-
Timer::PerPath(path_id, PathTimer::Pacing),
1932-
resume_time,
1933-
self.qlog.with_time(now),
1934-
);
19351945
// Loss probes and CONNECTION_CLOSE should be subject to pacing, even though
19361946
// they are not congestion controlled.
19371947
trace!(?space_id, %path_id, ?delay, "blocked by pacing");
1938-
return PathBlocked::Pacing;
1948+
return PathBlocked::Pacing(delay);
19391949
}
19401950

19411951
PathBlocked::No
@@ -7243,7 +7253,7 @@ enum PathBlocked {
72437253
No,
72447254
AntiAmplification,
72457255
Congestion,
7246-
Pacing,
7256+
Pacing(Duration),
72477257
}
72487258

72497259
/// Fields of `Connection` specific to it being client-side or server-side

noq-proto/src/connection/timer.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,20 @@ impl TimerTable {
292292
qlog.emit_timer_set(timer, time);
293293
}
294294

295+
/// Sets the timer, but only if the timer was unset or was set to a later value before.
296+
pub(super) fn set_if_earlier(
297+
&mut self,
298+
timer: Timer,
299+
time: Instant,
300+
qlog: QlogSinkWithTime<'_>,
301+
) {
302+
match self.get(timer) {
303+
Some(already_set) if already_set <= time => {}
304+
None => {}
305+
Some(_) => self.set(timer, time, qlog),
306+
}
307+
}
308+
295309
pub(super) fn get(&self, timer: Timer) -> Option<Instant> {
296310
match timer {
297311
Timer::Conn(timer) => self.generic[timer as usize],

0 commit comments

Comments
 (0)