summaryrefslogtreecommitdiff
path: root/crates/windlass/src/transport/rtt.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/windlass/src/transport/rtt.rs')
-rw-r--r--crates/windlass/src/transport/rtt.rs48
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);
+ }
+}