Repository navigation
feat(proto): add a handshake idle timeout #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
91b5887
9f30274
e6b21af
231c30d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3633,11 +3633,18 @@ impl Connection { | |
| let path = self.path(path_id)?; | ||
| let pto_count = path.pto_count; | ||
|
|
||
| // The idle timeout the probes have to beat, as `reset_idle_timeout` arms it. | ||
| let idle = if self.state.is_handshake() { | ||
| Some(self.config.handshake_idle_timeout) | ||
| } else { | ||
| path.idle_timeout.or(self.idle_timeout) | ||
| }; | ||
|
|
||
| // Cap the maximum interval between two tail-loss probes. | ||
| let max_interval = if path.rtt.get() > SLOW_RTT_THRESHOLD { | ||
| // For slow links we want to increase the interval beyond 2s. | ||
| (path.rtt.get() * 3) / 2 | ||
| } else if let Some(idle) = path.idle_timeout.or(self.idle_timeout) | ||
| } else if let Some(idle) = idle | ||
| && idle <= MIN_IDLE_FOR_FAST_PTO | ||
| { | ||
| // If the idle timeout is relatively low, cap at 1s so we get plenty of retries | ||
|
|
@@ -3913,18 +3920,28 @@ impl Connection { | |
| /// enabled there is an additional per-path idle timeout. | ||
| fn reset_idle_timeout(&mut self, now: Instant, space: SpaceKind, path_id: PathId) { | ||
| // First reset the global idle timeout. | ||
| if let Some(timeout) = self.idle_timeout { | ||
| if self.state.is_closed() { | ||
| self.timers | ||
| .stop(Timer::Conn(ConnTimer::Idle), self.qlog.with_time(now)); | ||
| } else { | ||
| let dt = cmp::max(timeout, 3 * self.max_pto_for_space(space)); | ||
| let timeout = if self.state.is_closed() { | ||
| None | ||
| } else if self.state.is_handshake() { | ||
| Some(self.config.handshake_idle_timeout) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Useful? React with 👍 / 👎.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in e6b21af: (Written by Claude Opus 5.5) |
||
| } else { | ||
| self.idle_timeout | ||
| }; | ||
| // A deadline too far out to represent never fires. | ||
| let deadline = timeout.and_then(|timeout| { | ||
| now.checked_add(cmp::max(timeout, 3 * self.max_pto_for_space(space))) | ||
| }); | ||
| match deadline { | ||
| Some(deadline) => { | ||
| self.timers.set( | ||
| Timer::Conn(ConnTimer::Idle), | ||
| now + dt, | ||
| deadline, | ||
| self.qlog.with_time(now), | ||
| ); | ||
| } | ||
| None => self | ||
| .timers | ||
| .stop(Timer::Conn(ConnTimer::Idle), self.qlog.with_time(now)), | ||
| } | ||
|
|
||
| // Now handle the per-path state. | ||
|
|
@@ -4800,6 +4817,8 @@ impl Connection { | |
|
|
||
| self.events.push_back(Event::Connected); | ||
| self.state.move_to_established(); | ||
| // Swap the handshake idle timeout for the negotiated one. | ||
| self.reset_idle_timeout(now, SpaceKind::Data, path_id); | ||
| trace!("established"); | ||
|
|
||
| // Multipath can only be enabled after the state has reached Established. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When server code delays calling
Incoming::accept, this timeout does not govern that portion of the handshake:Endpoint::acceptstill rejects stale Initial packets usingserver_config.transport.max_idle_timeout. For example, with the defaults an Initial can remain queued for 20 seconds despite the new 10-second handshake timeout, and withmax_idle_timeout(None)it can remain queued indefinitely; acceptance then creates a connection and starts a fresh handshake timer. Usehandshake_idle_timeoutfor the stale-Initial check so the configured limit covers the handshake from receipt of the Initial.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 9f30274:
Endpoint::acceptnow drops an Initial as stale oncehandshake_idle_timeouthas passed since it arrived, instead ofmax_idle_timeout, so the limit covers the wait foracceptand an unset idle timeout no longer lets an Initial wait forever. Test:stale_initial_uses_handshake_idle_timeout(accept 11s after the Initial times out; it was accepted before the change).(Written by Claude Opus 5.5)