Skip to content
File

Blob: firmware/vendor/str0m/src/util/mod.rs

rust88 lines
1use std::time::{Duration, Instant};
2 
3mod bit_pattern;
4 
5pub(crate) use bit_pattern::BitPattern;
6 
7pub(crate) mod value_history;
8 
9mod time_tricks;
10pub(crate) use time_tricks::{InstantExt, SystemTimeExt, not_happening};
11pub(crate) use time_tricks::{already_happened, epoch_to_beginning};
12 
13mod average;
14pub(crate) use average::MovingAverage;
15 
16pub(crate) trait Soonest {
17 fn soonest(self, other: Self) -> Self;
18}
19 
20impl<T: Default> Soonest for (Option<Instant>, T) {
21 fn soonest(self, other: Self) -> Self {
22 match (self, other) {
23 ((Some(v1), s1), (Some(v2), s2)) => {
24 if v1 < v2 {
25 (Some(v1), s1)
26 } else {
27 (Some(v2), s2)
28 }
29 }
30 ((None, _), (None, _)) => (None, T::default()),
31 ((None, _), (v, s)) => (v, s),
32 ((v, s), (None, _)) => (v, s),
33 }
34 }
35}
36 
37/// Calculate the round trip time for a given peer as described in
38/// [RFC3550 6.4.1](https://datatracker.ietf.org/doc/html/rfc3550#section-6.4.1).
39///
40/// ## Params
41/// - `ntp_time` the offset since 1900-01-01.
42/// - `delay` the delay(`DLSR`) since last sender report expressed as fractions of a second in 32 bits.
43/// - `last_report` the middle 32 bits of an NTP timestamp for the most recent sender report(LSR)
44/// or Receiver Report(LRR).
45pub(crate) fn calculate_rtt(ntp_time: Duration, delay: u32, last_report: u32) -> Option<Duration> {
46 // [10 Nov 1995 11:33:25.125 UTC] [10 Nov 1995 11:33:36.5 UTC]
47 // n SR(n) A=b710:8000 (46864.500 s)
48 // ---------------------------------------------------------------->
49 // v ^
50 // ntp_sec =0xb44db705 v ^ dlsr=0x0005:4000 ( 5.250s)
51 // ntp_frac=0x20000000 v ^ lsr =0xb705:2000 (46853.125s)
52 // (3024992005.125 s) v ^
53 // r v ^ RR(n)
54 // ---------------------------------------------------------------->
55 // |<-DLSR->|
56 // (5.250 s)
57 //
58 // A 0xb710:8000 (46864.500 s)
59 // DLSR -0x0005:4000 ( 5.250 s)
60 // LSR -0xb705:2000 (46853.125 s)
61 // -------------------------------
62 // delay 0x0006:2000 ( 6.125 s)
63 
64 // - we want the current middle 32 bits of an NTP timestamp for the current time.
65 // We treat the seconds separately to the fractions.
66 // [32 bit seconds].[32 bit fractions]
67 // [16 bit].[16 bit]
68 
69 // As per RFC delay is 0 in case no SR packet has been received yet.
70 if delay == 0 {
71 return None;
72 }
73 
74 let now_secs = ntp_time.as_secs();
75 let now_fract_ns = ntp_time.subsec_nanos() as u64;
76 let now_fract = ((now_fract_ns * u32::MAX as u64) / 1_000_000_000) as u32;
77 
78 // Combine the final 2x16 bits together.
79 let now = (now_secs as u32) << 16 | (now_fract >> 16);
80 
81 let rtt = now.checked_sub(delay)?.checked_sub(last_report)?;
82 let rtt_seconds = rtt >> 16;
83 let rtt_fraction = (rtt & (u16::MAX as u32)) as f32 / (u16::MAX as u32) as f32;
84 
85 let nanos = (rtt_fraction * 1_000_000_000.0) as u32;
86 Some(Duration::new(rtt_seconds as u64, nanos))
87}