use std::{
cmp::{max, min},
time::{Duration, Instant},
};
use neqo_common::qtrace;
usecrate::recovery;
#[derive(Debug, Clone)] /// There's a little bit of different behavior for resetting idle timeout. See /// -transport 10.2 ("Idle Timeout"). enum IdleTimeoutState {
Init,
PacketReceived(Instant),
AckElicitingPacketSent(Instant),
}
#[derive(Debug, Clone)] /// There's a little bit of different behavior for resetting idle timeout. See /// -transport 10.1 ("Idle Timeout"). /// /// <https://datatracker.ietf.org/doc/html/rfc9000#section-10.1> pubstruct IdleTimeout {
timeout: Duration,
state: IdleTimeoutState,
keep_alive_outstanding: bool,
}
pubfn expiry(&self, now: Instant, pto: Duration) -> Instant { let delay = max(self.timeout, pto * 3); let t = self.start(now) + delay;
qtrace!("IdleTimeout::expiry@{now:?} pto={pto:?} => {t:?}");
t
}
pubconstfn on_packet_sent(&mutself, now: Instant) { // Only reset idle timeout if we've received a packet since the last // time we reset the timeout here. matchself.state { // > An endpoint also restarts its idle timer when sending an // > ack-eliciting packet if no other ack-eliciting packets have // > been sent since last receiving and processing a packet. // // <https://datatracker.ietf.org/doc/html/rfc9000#section-10.1> // // Conversely, given that a packet has been sent since last // receival, don't reset idle timer.
IdleTimeoutState::AckElicitingPacketSent(_) => {}
IdleTimeoutState::Init | IdleTimeoutState::PacketReceived(_) => { self.state = IdleTimeoutState::AckElicitingPacketSent(now);
}
}
}
pubfn on_packet_received(&mutself, now: Instant) { // Only update if this doesn't rewind the idle timeout. // We sometimes process packets after caching them, which uses // the time the packet was received. That could be in the past. let update = matchself.state {
IdleTimeoutState::Init => true,
IdleTimeoutState::AckElicitingPacketSent(t) | IdleTimeoutState::PacketReceived(t) => {
t <= now
}
}; if update { self.state = IdleTimeoutState::PacketReceived(now);
}
}
fn keep_alive_timeout(&self, now: Instant, pto: Duration) -> Instant { // 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. self.start(now) + max(self.timeout / 2, pto)
}
let timeout = self.keep_alive_timeout(now, pto); // Timer is in the past, i.e. we should have sent a keep alive, // but we were unable to, e.g. due to CC. if timeout <= now { return None;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.