srt_protocol/protocol/time/
timer.rs

1use core::u32;
2use std::cmp::max;
3use std::time::{Duration, Instant};
4
5//4. Timers
6//
7//   UDT uses four timers to trigger different periodical events. Each
8//   event has its own period and they are all independent. They use the
9//   system time as origins and should process wrapping if the system time
10//   wraps.
11//
12//   For a certain periodical event E in UDT, suppose the time variable is
13//   ET and its period is p. If E is set or reset at system time t0 (ET =
14//   t0), then at any time t1, (t1 - ET >= p) is the condition to check if
15//   E should be triggered.
16//
17//   The four timers are ACK, NAK, EXP and SND. SND is used in the sender
18//   only for rate-based packet sending (see Section 6.1), whereas the
19//   other three are used in the receiver only.
20//
21//   ACK is used to trigger an acknowledgement (ACK). Its period is set by
22//   the congestion control module. However, UDT will send an ACK no
23//   longer than every 0.01 second, even though the congestion control
24//   does not need timer-based ACK. Here, 0.01 second is defined as the
25//   SYN time, or synchronization time, and it affects many of the other
26//   timers used in UDT.
27//
28//   NAK is used to trigger a negative acknowledgement (NAK). Its period
29//   is dynamically updated to 4 * RTT_+ RTTVar + SYN, where RTTVar is the
30//   variance of RTT samples.
31//
32//   EXP is used to trigger data packets retransmission and maintain
33//   connection status. Its period is dynamically updated to 4 * RTT +
34//   RTTVar + SYN.
35//
36//   The recommended granularity of their periods is microseconds. The
37//   system time is queried after each time bounded UDP receiving (there
38//   will be additional necessary data processing time if a UDP packet is
39//   received) to check if any of the ACK, NAK, or EXP event should be
40//   triggered. The timeout value of UDP receiving should be at least SYN.
41//
42//   In the rest of this document, a name of a time variable will be used
43//   to represent the associated event, the variable itself, or the value
44//   of its period, depending on the context. For example, ACK can mean
45//   either the ACK event or the value of ACK period.
46#[derive(Debug)]
47pub struct Timer {
48    period: Duration,
49    last: Instant,
50}
51
52impl Timer {
53    const MIN_PERIOD: Duration = Duration::from_micros(1);
54
55    pub fn new(now: Instant, period: Duration) -> Timer {
56        Timer {
57            period: max(period, Self::MIN_PERIOD),
58            last: now,
59        }
60    }
61
62    pub fn period(&mut self) -> Duration {
63        self.period
64    }
65
66    pub fn next_instant(&self) -> Instant {
67        self.last + self.period
68    }
69
70    pub fn reset(&mut self, now: Instant) {
71        self.last = now;
72    }
73
74    pub fn set_period(&mut self, period: Duration) {
75        self.period = period;
76    }
77
78    pub fn check_expired(&mut self, now: Instant) -> Option<u32> {
79        if self.period.as_nanos() == 0 {
80            return Some(1);
81        }
82        if now >= self.next_instant() {
83            let elapsed = now - self.last;
84            let elapsed_periods = (elapsed.as_nanos() / self.period.as_nanos()) as u32;
85            self.last += self.period * elapsed_periods;
86            Some(elapsed_periods)
87        } else {
88            None
89        }
90    }
91}