mirror of
https://github.com/n0-computer/noq.git
synced 2026-10-03 12:40:46 +00:00
fix(proto): re-arm PathIdle timer when idle timeout is changed (#544)
## Description Immediately re-arm or stop the PathIdle timer when `set_path_max_idle_timeout` is called, accounting for already-elapsed idle time. Previously the running timer continued with the old deadline, so extending the timeout during a network change had no effect until the next received packet. Setting `None` now stops the timer. Split from #525. Relates to #376 --------- Co-authored-by: Philipp Krüger <philipp.krueger1@gmail.com>
This commit is contained in:
committed by
GitHub
parent
2622b67748
commit
cdde4e92f3
@@ -843,13 +843,17 @@ impl Connection {
|
||||
self.path(path_id).and_then(|path| path.remote_status())
|
||||
}
|
||||
|
||||
/// Sets the max_idle_timeout for a specific path
|
||||
/// Sets the max_idle_timeout for a specific path.
|
||||
///
|
||||
/// The PathIdle timer is immediately re-armed accounting for already-elapsed
|
||||
/// idle time. Setting `None` disables the timeout and stops the timer.
|
||||
///
|
||||
/// See [`TransportConfig::default_path_max_idle_timeout`] for details.
|
||||
///
|
||||
/// Returns the previous value of the setting.
|
||||
pub fn set_path_max_idle_timeout(
|
||||
&mut self,
|
||||
now: Instant,
|
||||
path_id: PathId,
|
||||
timeout: Option<Duration>,
|
||||
) -> Result<Option<Duration>, ClosedPath> {
|
||||
@@ -857,7 +861,29 @@ impl Connection {
|
||||
.paths
|
||||
.get_mut(&path_id)
|
||||
.ok_or(ClosedPath { _private: () })?;
|
||||
Ok(std::mem::replace(&mut path.data.idle_timeout, timeout))
|
||||
let prev = std::mem::replace(&mut path.data.idle_timeout, timeout);
|
||||
|
||||
// Adjust the PathIdle timer, accounting for already-elapsed idle time.
|
||||
if !self.state.is_closed() {
|
||||
if let Some(new_timeout) = timeout {
|
||||
let timer = Timer::PerPath(path_id, PathTimer::PathIdle);
|
||||
let deadline = match (prev, self.timers.get(timer)) {
|
||||
(Some(old_timeout), Some(old_deadline)) => {
|
||||
let last_activity = old_deadline.checked_sub(old_timeout).unwrap_or(now);
|
||||
last_activity + new_timeout
|
||||
}
|
||||
_ => now + new_timeout,
|
||||
};
|
||||
self.timers.set(timer, deadline, self.qlog.with_time(now));
|
||||
} else {
|
||||
self.timers.stop(
|
||||
Timer::PerPath(path_id, PathTimer::PathIdle),
|
||||
self.qlog.with_time(now),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(prev)
|
||||
}
|
||||
|
||||
/// Sets the keep_alive_interval for a specific path
|
||||
|
||||
@@ -155,7 +155,6 @@ where
|
||||
self.heap.as_mut().and_then(|h| h.remove(key))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn get(&self, key: &K) -> Option<&V> {
|
||||
for (k, v) in self.stack.iter().filter_map(|v| v.as_ref()) {
|
||||
if k == key {
|
||||
@@ -240,6 +239,10 @@ impl PathTimerTable {
|
||||
self.timers[timer as usize] = Some(time);
|
||||
}
|
||||
|
||||
fn get(&self, timer: PathTimer) -> Option<Instant> {
|
||||
self.timers[timer as usize]
|
||||
}
|
||||
|
||||
fn stop(&mut self, timer: PathTimer) {
|
||||
self.timers[timer as usize] = None;
|
||||
}
|
||||
@@ -281,6 +284,13 @@ impl TimerTable {
|
||||
qlog.emit_timer_set(timer, time);
|
||||
}
|
||||
|
||||
pub(super) fn get(&self, timer: Timer) -> Option<Instant> {
|
||||
match timer {
|
||||
Timer::Conn(timer) => self.generic[timer as usize],
|
||||
Timer::PerPath(path_id, timer) => self.path_timers.get(&path_id)?.get(timer),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn set_or_stop(
|
||||
&mut self,
|
||||
timer: Timer,
|
||||
|
||||
@@ -564,8 +564,9 @@ impl ConnPair {
|
||||
path_id: PathId,
|
||||
timeout: Option<Duration>,
|
||||
) -> Result<Option<Duration>, ClosedPath> {
|
||||
let now = self.pair.time;
|
||||
self.conn_mut(side)
|
||||
.set_path_max_idle_timeout(path_id, timeout)
|
||||
.set_path_max_idle_timeout(now, path_id, timeout)
|
||||
}
|
||||
|
||||
pub(super) fn set_path_keep_alive_interval(
|
||||
|
||||
+2
-1
@@ -241,7 +241,8 @@ impl Path {
|
||||
timeout: Option<Duration>,
|
||||
) -> Result<Option<Duration>, ClosedPath> {
|
||||
let mut state = self.conn.state.lock("path_set_max_idle_timeout");
|
||||
state.inner.set_path_max_idle_timeout(self.id, timeout)
|
||||
let now = state.runtime.now();
|
||||
state.inner.set_path_max_idle_timeout(now, self.id, timeout)
|
||||
}
|
||||
|
||||
/// Sets the keep_alive_interval for a specific path
|
||||
|
||||
Reference in New Issue
Block a user