rtc_shared/replay_detector/
mod.rs1mod fixed_big_int;
2#[cfg(test)]
3mod replay_detector_test;
4
5use fixed_big_int::*;
6
7pub trait ReplayDetector: Send + Sync {
13 fn check(&mut self, seq: u64) -> bool;
17 fn accept(&mut self);
22}
23
24pub struct SlidingWindowDetector {
29 accepted: bool,
30 seq: u64,
31 latest_seq: u64,
32 max_seq: u64,
33 window_size: usize,
34 mask: FixedBigInt,
35}
36
37impl SlidingWindowDetector {
38 pub fn new(window_size: usize, max_seq: u64) -> Self {
44 SlidingWindowDetector {
45 accepted: false,
46 seq: 0,
47 latest_seq: 0,
48 max_seq,
49 window_size,
50 mask: FixedBigInt::new(window_size),
51 }
52 }
53}
54
55impl ReplayDetector for SlidingWindowDetector {
56 fn check(&mut self, seq: u64) -> bool {
57 self.accepted = false;
58
59 if seq > self.max_seq {
60 return false;
62 }
63
64 if seq <= self.latest_seq {
65 if self.latest_seq >= self.window_size as u64 + seq {
66 return false;
67 }
68 if self.mask.bit((self.latest_seq - seq) as usize) != 0 {
69 return false;
71 }
72 }
73
74 self.accepted = true;
75 self.seq = seq;
76 true
77 }
78
79 fn accept(&mut self) {
80 if !self.accepted {
81 return;
82 }
83
84 if self.seq > self.latest_seq {
85 self.mask.lsh((self.seq - self.latest_seq) as usize);
87 self.latest_seq = self.seq;
88 }
89 let diff = (self.latest_seq - self.seq) % self.max_seq;
90 self.mask.set_bit(diff as usize);
91 }
92}
93
94pub struct WrappedSlidingWindowDetector {
99 accepted: bool,
100 seq: u64,
101 latest_seq: u64,
102 max_seq: u64,
103 window_size: usize,
104 mask: FixedBigInt,
105 init: bool,
106}
107
108impl WrappedSlidingWindowDetector {
109 pub fn new(window_size: usize, max_seq: u64) -> Self {
114 WrappedSlidingWindowDetector {
115 accepted: false,
116 seq: 0,
117 latest_seq: 0,
118 max_seq,
119 window_size,
120 mask: FixedBigInt::new(window_size),
121 init: false,
122 }
123 }
124}
125
126impl ReplayDetector for WrappedSlidingWindowDetector {
127 fn check(&mut self, seq: u64) -> bool {
128 self.accepted = false;
129
130 if seq > self.max_seq {
131 return false;
133 }
134 if !self.init {
135 if seq != 0 {
136 self.latest_seq = seq - 1;
137 } else {
138 self.latest_seq = self.max_seq;
139 }
140 self.init = true;
141 }
142
143 let mut diff = self.latest_seq as i64 - seq as i64;
144 if diff > self.max_seq as i64 / 2 {
146 diff -= (self.max_seq + 1) as i64;
147 } else if diff <= -(self.max_seq as i64 / 2) {
148 diff += (self.max_seq + 1) as i64;
149 }
150
151 if diff >= self.window_size as i64 {
152 return false;
154 }
155 if diff >= 0 && self.mask.bit(diff as usize) != 0 {
156 return false;
158 }
159
160 self.accepted = true;
161 self.seq = seq;
162 true
163 }
164
165 fn accept(&mut self) {
166 if !self.accepted {
167 return;
168 }
169
170 let mut diff = self.latest_seq as i64 - self.seq as i64;
171 if diff > self.max_seq as i64 / 2 {
173 diff -= (self.max_seq + 1) as i64;
174 } else if diff <= -(self.max_seq as i64 / 2) {
175 diff += (self.max_seq + 1) as i64;
176 }
177
178 assert!(diff < self.window_size as i64);
179
180 if diff < 0 {
181 self.mask.lsh((-diff) as usize);
183 self.latest_seq = self.seq;
184 self.mask.set_bit(0);
185 } else {
186 self.mask.set_bit(diff as usize);
187 }
188 }
189}
190
191#[derive(Default)]
192pub struct NoOpReplayDetector;
196
197impl ReplayDetector for NoOpReplayDetector {
198 fn check(&mut self, _: u64) -> bool {
199 true
200 }
201 fn accept(&mut self) {}
202}