renetcode/
replay_protection.rs1const NETCODE_REPLAY_BUFFER_SIZE: usize = 256;
2const EMPTY: u64 = u64::MAX;
3
4#[derive(Debug, Clone)]
5pub struct ReplayProtection {
6 most_recent_sequence: u64,
7 received_packet: [u64; NETCODE_REPLAY_BUFFER_SIZE],
8}
9
10impl Default for ReplayProtection {
11 fn default() -> Self {
12 Self::new()
13 }
14}
15
16impl ReplayProtection {
17 pub fn new() -> Self {
18 Self {
19 most_recent_sequence: 0,
20 received_packet: [EMPTY; NETCODE_REPLAY_BUFFER_SIZE],
21 }
22 }
23
24 pub fn already_received(&self, sequence: u64) -> bool {
25 if sequence + NETCODE_REPLAY_BUFFER_SIZE as u64 <= self.most_recent_sequence {
26 return true;
27 }
28
29 let index = sequence as usize % NETCODE_REPLAY_BUFFER_SIZE;
30 if self.received_packet[index] == EMPTY {
31 return false;
32 }
33
34 if self.received_packet[index] >= sequence {
35 return true;
36 }
37
38 false
39 }
40
41 pub fn advance_sequence(&mut self, sequence: u64) {
42 if sequence > self.most_recent_sequence {
43 self.most_recent_sequence = sequence;
44 }
45
46 let index = sequence as usize % NETCODE_REPLAY_BUFFER_SIZE;
47 self.received_packet[index] = sequence;
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn replay_protection() {
57 let mut replay_protection = ReplayProtection::new();
58 assert_eq!(replay_protection.most_recent_sequence, 0);
59
60 let max_sequence = (NETCODE_REPLAY_BUFFER_SIZE * 4) as u64;
62 for i in 0..max_sequence {
63 assert!(!replay_protection.already_received(i));
64 replay_protection.advance_sequence(i);
65 }
66
67 assert!(replay_protection.already_received(0));
69
70 for i in max_sequence - 10..max_sequence {
72 assert!(replay_protection.already_received(i));
73 }
74
75 assert!(!replay_protection.already_received(max_sequence + NETCODE_REPLAY_BUFFER_SIZE as u64));
77
78 for i in 0..max_sequence {
80 assert!(replay_protection.already_received(i));
81 }
82 }
83}