Skip to content

Commit

Permalink
make expiry return longer timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
KershawChang committed May 8, 2024
1 parent bb88aab commit 2b037cc
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 13 deletions.
26 changes: 15 additions & 11 deletions neqo-transport/src/connection/idle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,14 @@ impl IdleTimeout {
self.timeout = min(self.timeout, peer_timeout);
}

pub fn expiry(&self, now: Instant, pto: Duration, keep_alive: bool) -> Instant {
pub fn expiry(&self, now: Instant, pto: Duration) -> Instant {
let start = match self.state {
IdleTimeoutState::Init => now,
IdleTimeoutState::PacketReceived(t) | IdleTimeoutState::AckElicitingPacketSent(t) => t,
};
let delay = if keep_alive && !self.keep_alive_outstanding {
// For a keep-alive timer, wait for half the timeout interval, but be sure
// not to wait too little or we will send many unnecessary probes.
max(self.timeout / 2, pto)
} else {
max(self.timeout, pto * 3)
};
let delay = max(self.timeout, pto * 3);
qtrace!(
"IdleTimeout::expiry@{now:?} pto={pto:?}, ka={keep_alive} => {t:?}",
"IdleTimeout::expiry@{now:?} pto={pto:?} => {t:?}",
t = start + delay
);
start + delay
Expand Down Expand Up @@ -92,7 +86,17 @@ impl IdleTimeout {
}

pub fn expired(&self, now: Instant, pto: Duration) -> bool {
now >= self.expiry(now, pto, false)
now >= self.expiry(now, pto)
}

fn keep_alive_timeout(&self, now: Instant, pto: Duration) -> Instant {
let start = match self.state {
IdleTimeoutState::Init => now,
IdleTimeoutState::PacketReceived(t) | IdleTimeoutState::AckElicitingPacketSent(t) => t,
};
// For a keep-alive timer, wait for half the timeout interval, but be sure
// not to wait too little or we will send many unnecessary probes.
start + max(self.timeout / 2, pto)
}

pub fn send_keep_alive(
Expand All @@ -101,7 +105,7 @@ impl IdleTimeout {
pto: Duration,
tokens: &mut Vec<RecoveryToken>,
) -> bool {
if !self.keep_alive_outstanding && now >= self.expiry(now, pto, true) {
if !self.keep_alive_outstanding && now >= self.keep_alive_timeout(now, pto) {
self.keep_alive_outstanding = true;
tokens.push(RecoveryToken::KeepAlive);
true
Expand Down
3 changes: 1 addition & 2 deletions neqo-transport/src/connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1029,8 +1029,7 @@ impl Connection {
let rtt = path.rtt();
let pto = rtt.pto(PacketNumberSpace::ApplicationData);

let keep_alive = self.streams.need_keep_alive();
let idle_time = self.idle_timeout.expiry(now, pto, keep_alive);
let idle_time = self.idle_timeout.expiry(now, pto);
qtrace!([self], "Idle/keepalive timer {:?}", idle_time);
delays.push(idle_time);

Expand Down
22 changes: 22 additions & 0 deletions neqo-transport/src/connection/tests/idle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -742,3 +742,25 @@ fn keep_alive_with_ack_eliciting_packet_lost() {
assert!(matches!(out, Output::None));
assert!(matches!(client.state(), State::Closed(_)));
}

#[test]
fn keep_alive_with_unresponsive_server() {
let mut client = default_client();
let mut server = default_server();
connect(&mut client, &mut server);

let mut now = now();
let client_stream = client.stream_create(StreamType::BiDi).unwrap();
client.stream_keep_alive(client_stream, true).unwrap();

for _ in 0..100 {
if client.stream_send(client_stream, &[0x0; 500]).is_err() {
break;
}
if let Output::Callback(t) = client.process_output(now) {
now += t;
}
}
// Connection should be closed due to idle timeout.
assert!(matches!(client.state(), State::Closed(_)));
}

0 comments on commit 2b037cc

Please sign in to comment.