diff options
Diffstat (limited to 'crates/windlass/src/transport/rtt.rs')
-rw-r--r-- | crates/windlass/src/transport/rtt.rs | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/crates/windlass/src/transport/rtt.rs b/crates/windlass/src/transport/rtt.rs new file mode 100644 index 0000000..69841f6 --- /dev/null +++ b/crates/windlass/src/transport/rtt.rs @@ -0,0 +1,48 @@ +use std::time::Duration; + +const MIN_RTO: f32 = 0.025; +const MAX_RTO: f32 = 5.000; + +/// State for estimating the round trip time of the connection +#[derive(Debug)] +pub struct RttState { + srtt: f32, + rttvar: f32, + rto: f32, +} + +impl Default for RttState { + fn default() -> Self { + Self { + srtt: 0.0, + rttvar: 0.0, + rto: MIN_RTO, + } + } +} + +impl RttState { + /// Get the current recommended retransmission timeout + pub fn rto(&self) -> Duration { + Duration::from_secs_f32(self.rto) + } + + /// Update the RTT estimation given a new observation + pub fn update(&mut self, rtt: Duration) { + let r = rtt.as_secs_f32(); + if self.srtt == 0.0 { + self.rttvar = r / 2.0; + self.srtt = r * 10.0; // Klipper uses this, we'll copy it + } else { + self.rttvar = (3.0 * self.rttvar + (self.srtt - r).abs()) / 4.0; + self.srtt = (7.0 * self.srtt + r) / 8.0; + } + let rttvar4 = (self.rttvar * 4.0).max(0.001); + self.rto = (self.srtt + rttvar4).clamp(MIN_RTO, MAX_RTO); + } + + /// Double the RTO estimation + pub fn double(&mut self) { + self.rto = (self.rto * 2.0).clamp(MIN_RTO, MAX_RTO); + } +} |