srt_protocol/protocol/time/
mod.rs1mod base;
2mod rtt;
3mod timer;
4
5pub use base::*;
6pub use rtt::*;
7pub use timer::*;
8
9use std::{
10 cmp::{max, min},
11 time::{Duration, Instant},
12};
13
14#[derive(Debug)]
20pub struct Timers {
21 snd: Timer,
22
23 full_ack: Timer,
30
31 nak: Timer,
35
36 exp: Timer,
40 exp_count: u32,
41 peer_idle: Timer,
42
43 statistics: Timer,
44}
45
46impl Timers {
47 pub const SYN: Duration = Duration::from_millis(10);
48 const EXP_MAX: u32 = 16;
49
50 pub fn new(now: Instant, statistics_interval: Duration, peer_idle_timeout: Duration) -> Self {
51 let (ack, nak, exp) = Self::calculate_periods(1, &Rtt::default());
52 Self {
53 snd: Timer::new(now, Duration::from_millis(1)),
54 full_ack: Timer::new(now, ack),
55 nak: Timer::new(now, nak),
56 exp: Timer::new(now, exp),
57 exp_count: 1,
58 peer_idle: Timer::new(now, peer_idle_timeout),
59 statistics: Timer::new(now, statistics_interval),
62 }
63 }
64
65 pub fn next_timer(
66 &self,
67 now: Instant,
68 has_packets_to_send: bool,
69 next_message: Option<Instant>,
70 unacked_packets: u32,
71 ) -> Instant {
72 let timer = min(self.exp.next_instant(), self.nak.next_instant());
73 let timer = next_message.map_or(timer, |message| min(timer, message));
74 let timer = if unacked_packets > 0 {
75 min(self.full_ack.next_instant(), timer)
76 } else {
77 timer
78 };
79 let timer = if has_packets_to_send {
80 min(self.snd.next_instant(), timer)
81 } else {
82 timer
83 };
84
85 max(now, timer)
86 }
87
88 pub fn check_snd(&mut self, now: Instant) -> Option<u32> {
89 self.snd.check_expired(now)
90 }
91
92 pub fn check_full_ack(&mut self, now: Instant) -> Option<u32> {
93 self.full_ack.check_expired(now)
94 }
95
96 pub fn check_nak(&mut self, now: Instant) -> Option<u32> {
97 self.nak.check_expired(now)
98 }
99
100 pub fn check_peer_idle_timeout(&mut self, now: Instant) -> Option<u32> {
101 let _ = self.exp.check_expired(now)?;
102
103 self.peer_idle
104 .check_expired(now)
105 .filter(|_| self.exp_count > Self::EXP_MAX)
106 .or_else(|| {
107 self.exp_count += 1;
108 None
109 })
110 }
111
112 pub fn check_statistics(&mut self, now: Instant) -> Option<u32> {
113 self.statistics.check_expired(now)
114 }
115
116 pub fn update_snd_period(&mut self, period: Duration) {
117 self.snd.set_period(period)
118 }
119
120 pub fn update_rtt(&mut self, rtt: &Rtt) {
121 let (ack, nak, exp) = Self::calculate_periods(self.exp_count, rtt);
122 self.full_ack.set_period(ack);
123 self.nak.set_period(nak);
124 self.exp.set_period(exp);
125 }
126
127 pub fn reset_exp(&mut self, now: Instant) {
128 self.exp_count = 1;
129 self.peer_idle.reset(now)
130 }
131
132 fn calculate_periods(exp_count: u32, rtt: &Rtt) -> (Duration, Duration, Duration) {
133 let ms = Duration::from_millis;
134
135 let nak_rtt_period = (rtt.mean_as_duration() + 4 * rtt.variance_as_duration()) / 2;
137 let nak_period = max(nak_rtt_period, ms(20));
138
139 let exp_rtt_period = 4 * rtt.mean_as_duration() + rtt.variance_as_duration() + Self::SYN;
142 let exp_period = max(exp_count * exp_rtt_period, exp_count * ms(300));
143
144 (ms(10), nak_period, exp_period)
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use proptest::prelude::*;
152
153 use super::*;
154
155 use crate::packet::TimeSpan;
156
157 proptest! {
158 #[test]
159 fn nak(simulated_rtt in 0i32..500_000) {
160 prop_assume!(simulated_rtt >= 0);
161 let mut rtt = Rtt::default();
162 for _ in 0..1000 {
163 rtt.update(TimeSpan::from_micros(simulated_rtt));
164 }
165
166 let ms = Duration::from_millis;
167 let rtt_mean = rtt.mean_as_duration();
168 let rtt_variance = rtt.variance_as_duration();
169
170 prop_assume!((rtt_mean + 4 * rtt_variance) / 2 > ms(20));
172
173 let start = Instant::now();
174 let mut timers = Timers::new(start, ms(10_000), ms(5_000));
175
176 timers.update_rtt(&rtt);
177
178 assert_eq!(timers.nak.next_instant() - start, (rtt_mean + 4 * rtt_variance) / 2);
180
181 assert_eq!(timers.full_ack.next_instant() - start, ms(10));
183 }
184
185 #[test]
186 fn exp(simulated_rtt in 0i32..500_000) {
187 prop_assume!(simulated_rtt >= 0);
188 let mut rtt = Rtt::default();
189 for _ in 0..1000 {
190 rtt.update(TimeSpan::from_micros(simulated_rtt));
191 }
192
193 let ms = Duration::from_millis;
194 let syn = ms(10);
195 let rtt_mean = rtt.mean_as_duration();
196 let rtt_variance = rtt.variance_as_duration();
197
198 prop_assume!(4 * rtt_mean + rtt_variance + syn > ms(300));
200
201 let start = Instant::now();
202 let mut timers = Timers::new(start, ms(10_000), ms(5_000));
203
204 timers.update_rtt(&rtt);
205
206 assert_eq!(timers.exp.next_instant() - start, 4 * rtt_mean + rtt_variance + syn);
208
209 assert_eq!(timers.full_ack.next_instant() - start, ms(10));
211
212 assert_eq!(timers.full_ack.next_instant() - start, ms(10));
214 }
215
216 #[test]
217 fn nak_lower_bound(simulated_rtt in 0i32..100_000) {
218 prop_assume!(simulated_rtt >= 10_000);
219 let mut rtt = Rtt::default();
220 for _ in 0..1000 {
221 rtt.update(TimeSpan::from_micros(simulated_rtt));
222 }
223
224 let ms = Duration::from_millis;
225 let rtt_mean = rtt.mean_as_duration();
226 let rtt_variance = rtt.variance_as_duration();
227
228 prop_assume!((rtt_mean + 4 * rtt_variance) / 2 <= ms(20));
230
231 let start = Instant::now();
232 let mut timers = Timers::new(start, ms(10_000), ms(5_000));
233
234 timers.update_rtt(&rtt);
235
236 assert_eq!(timers.nak.next_instant() - start, ms(20));
238
239 assert_eq!(timers.full_ack.next_instant() - start, ms(10));
241 }
242
243 #[test]
244 fn exp_lower_bound(simulated_rtt in 0i32..100_000) {
245 prop_assume!(simulated_rtt >= 0);
246 let mut rtt = Rtt::default();
247 for _ in 0..1000 {
248 rtt.update(TimeSpan::from_micros(simulated_rtt));
249 }
250
251 let ms = Duration::from_millis;
252 let syn = ms(10);
253 let rtt_mean = rtt.mean_as_duration();
254 let rtt_variance = rtt.variance_as_duration();
255
256 prop_assume!(4 * rtt_mean + rtt_variance + syn <= ms(300));
258
259 let start = Instant::now();
260 let mut timers = Timers::new(start, ms(10_000), ms(5_000));
261
262 timers.update_rtt(&rtt);
263
264 assert_eq!(timers.exp.next_instant() - start, ms(300));
266
267 assert_eq!(timers.full_ack.next_instant() - start, ms(10));
269 }
270 }
271
272 #[test]
273 fn next_timer() {
274 let ms = TimeSpan::from_millis;
275 let start = Instant::now();
276 let mut timers = Timers::new(start, Duration::MAX, Duration::from_millis(5_000));
277
278 let now = start;
280 let actual_timer = timers.next_timer(now, false, None, 1);
281 assert_eq!(TimeSpan::from_interval(now, actual_timer), ms(10));
282
283 let actual_timer = timers.next_timer(now, false, None, 0);
285 assert!(TimeSpan::from_interval(now, actual_timer) > ms(10));
286
287 let now = start + ms(15);
289 assert!(timers.check_full_ack(now).is_some());
291 assert!(timers.check_nak(now).is_none());
292 assert!(timers.check_peer_idle_timeout(now).is_none());
293
294 let nak = ms(20);
296 let actual_timer = timers.next_timer(now, false, Some(start + ms(10_000)), 1);
297 assert_eq!(TimeSpan::from_interval(start, actual_timer), nak);
298
299 assert!(timers.check_full_ack(actual_timer).is_some());
301 assert!(timers.check_nak(actual_timer).is_some());
302 assert!(timers.check_peer_idle_timeout(actual_timer).is_none());
303
304 let exp_lower_bound = ms(300);
306 let now = start + exp_lower_bound;
307
308 assert!(timers.check_full_ack(now).is_some());
310 assert!(timers.check_nak(now).is_some());
311
312 let actual_timer = timers.next_timer(now, false, Some(start + ms(10_000)), 1);
314 assert_eq!(
315 TimeSpan::from_interval(start, actual_timer),
316 exp_lower_bound
317 );
318
319 assert!(timers.check_full_ack(actual_timer).is_none());
321 assert!(timers.check_nak(actual_timer).is_none());
322 let last_input = start;
323 timers.reset_exp(last_input);
324 for exp_count in 1..=16 {
325 assert!(timers
326 .check_peer_idle_timeout(last_input + exp_count * exp_lower_bound)
327 .is_none());
328 }
329 assert!(timers
330 .check_peer_idle_timeout(last_input + 17 * exp_lower_bound)
331 .is_some());
332 }
333}