1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Copyright 2024 Saorsa Labs Ltd.
//
// This Saorsa Network Software is licensed under the General Public License (GPL), version 3.
// Please see the file LICENSE-GPL, or visit <http://www.gnu.org/licenses/> for the full text.
//
// Full details available at https://saorsalabs.com/licenses
use crate::Instant;
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub(crate) enum Timer {
/// When to send an ack-eliciting probe packet or declare unacked packets lost
LossDetection = 0,
/// When to close the connection after no activity
Idle = 1,
/// When the close timer expires, the connection has been gracefully terminated.
Close = 2,
/// When keys are discarded because they should not be needed anymore
KeyDiscard = 3,
/// When to give up on validating a new path to the peer
PathValidation = 4,
/// When to send a `PING` frame to keep the connection alive
KeepAlive = 5,
/// When pacing will allow us to send a packet
Pacing = 6,
/// When to invalidate old CID and proactively push new one via NEW_CONNECTION_ID frame
PushNewCid = 7,
/// When to send an immediate ACK if there are unacked ack-eliciting packets of the peer
MaxAckDelay = 8,
/// When to perform NAT traversal operations (coordination, validation retries)
NatTraversal = 9,
}
impl Timer {
pub(crate) const VALUES: [Self; 10] = [
Self::LossDetection,
Self::Idle,
Self::Close,
Self::KeyDiscard,
Self::PathValidation,
Self::KeepAlive,
Self::Pacing,
Self::PushNewCid,
Self::MaxAckDelay,
Self::NatTraversal,
];
}
/// A table of data associated with each distinct kind of `Timer`
#[derive(Debug, Copy, Clone, Default)]
pub(crate) struct TimerTable {
data: [Option<Instant>; 10],
}
impl TimerTable {
pub(super) fn set(&mut self, timer: Timer, time: Instant) {
self.data[timer as usize] = Some(time);
}
pub(super) fn get(&self, timer: Timer) -> Option<Instant> {
self.data[timer as usize]
}
pub(super) fn stop(&mut self, timer: Timer) {
self.data[timer as usize] = None;
}
pub(super) fn next_timeout(&self) -> Option<Instant> {
self.data.iter().filter_map(|&x| x).min()
}
pub(super) fn is_expired(&self, timer: Timer, after: Instant) -> bool {
self.data[timer as usize].is_some_and(|x| x <= after)
}
}