opcua_core/comms/
sequence_number.rs1use opcua_types::{Error, StatusCode};
4use tracing::trace;
5
6#[derive(Debug, Clone)]
7pub struct SequenceNumberHandle {
9 is_legacy: bool,
10 current_value: u32,
11}
12
13impl SequenceNumberHandle {
14 pub fn new(is_legacy: bool) -> Self {
18 Self {
19 is_legacy,
20 current_value: if is_legacy { 1 } else { 0 },
21 }
22 }
23
24 #[allow(unused)]
25 pub(crate) fn new_at(is_legacy: bool, value: u32) -> Self {
26 let max_value = if is_legacy { u32::MAX - 1024 } else { u32::MAX };
27 Self {
28 is_legacy,
29 current_value: value % max_value,
30 }
31 }
32
33 pub fn max_value(&self) -> u32 {
36 if self.is_legacy {
37 u32::MAX - 1024
38 } else {
39 u32::MAX
40 }
41 }
42
43 pub fn is_legacy(&self) -> bool {
45 self.is_legacy
46 }
47
48 pub(crate) fn set_is_legacy(&mut self, is_legacy: bool) {
49 self.is_legacy = is_legacy;
50 if self.current_value > self.max_value() {
51 self.current_value = self.min_value() + (self.current_value - self.max_value() - 1);
53 }
54 }
55
56 pub fn min_value(&self) -> u32 {
58 if self.is_legacy {
59 1
60 } else {
61 0
62 }
63 }
64
65 pub fn current(&self) -> u32 {
68 self.current_value
69 }
70
71 pub fn set(&mut self, value: u32) {
73 self.current_value = value;
74 }
75
76 pub fn increment(&mut self, value: u32) {
78 let remaining = self.max_value() - self.current_value;
79 if remaining < value {
80 self.current_value = self.min_value() + value - remaining - 1;
82 } else {
83 self.current_value += value;
85 }
86 }
87
88 pub fn validate_and_increment(&mut self, incoming_sequence_number: u32) -> Result<(), Error> {
90 let expected = self.current();
91 if incoming_sequence_number != expected {
92 if self.is_legacy() && expected == self.min_value() && incoming_sequence_number < 1024 {
97 self.set(incoming_sequence_number);
98 } else {
99 trace!(
100 "Expected sequence number {}, got {}",
101 expected,
102 incoming_sequence_number
103 );
104 return Err(Error::new(
105 StatusCode::BadSequenceNumberInvalid,
106 format!(
107 "Chunk sequence number of {incoming_sequence_number} is not the expected value of {expected}"
108 ),
109 ));
110 }
111 }
112 self.increment(1);
113
114 Ok(())
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::SequenceNumberHandle;
121
122 #[test]
123 fn test_sequence_numbers() {
124 let mut seq = SequenceNumberHandle::new(true);
125 assert_eq!(seq.current(), 1);
126 assert_eq!(seq.max_value(), u32::MAX - 1024);
127 assert_eq!(seq.min_value(), 1);
128 assert!(seq.is_legacy());
129 seq.increment(1);
130 assert_eq!(seq.current(), 2);
131
132 seq.increment(1022);
133 assert_eq!(seq.current(), 1024);
134 seq.increment(u32::MAX - 2048);
135 assert_eq!(seq.current(), u32::MAX - 1024);
136 seq.increment(1);
137 assert_eq!(seq.current(), 1);
138
139 seq.increment(u32::MAX - 1026);
140 assert_eq!(seq.current(), u32::MAX - 1025);
141 seq.increment(3);
142 assert_eq!(seq.current(), 2);
143 }
144
145 #[test]
146 fn test_sequence_numbers_non_legacy() {
147 let mut seq = SequenceNumberHandle::new(false);
148 assert_eq!(seq.current(), 0);
149 assert_eq!(seq.max_value(), u32::MAX);
150 assert_eq!(seq.min_value(), 0);
151 assert!(!seq.is_legacy());
152 seq.increment(1);
153 assert_eq!(seq.current(), 1);
154
155 seq.increment(u32::MAX - 1);
156 assert_eq!(seq.current(), u32::MAX);
157 seq.increment(1);
158 assert_eq!(seq.current(), 0);
159
160 seq.increment(u32::MAX - 1);
161 assert_eq!(seq.current(), u32::MAX - 1);
162 seq.increment(3);
163 assert_eq!(seq.current(), 1);
164 }
165
166 #[test]
167 fn test_sequence_numbers_validate() {
168 let mut seq = SequenceNumberHandle::new(true);
169 assert_eq!(seq.current(), 1);
170 assert!(seq.validate_and_increment(1).is_ok());
171 assert_eq!(seq.current(), 2);
172 assert!(seq.validate_and_increment(2).is_ok());
173 assert_eq!(seq.current(), 3);
174 assert!(seq.validate_and_increment(5).is_err());
175 assert_eq!(seq.current(), 3);
176
177 seq.set(1);
179 assert!(seq.validate_and_increment(50).is_ok());
180 assert_eq!(seq.current(), 51);
181 assert!(seq.validate_and_increment(50).is_err());
182 assert_eq!(seq.current(), 51);
183 assert!(seq.validate_and_increment(51).is_ok());
184 assert_eq!(seq.current(), 52);
185
186 seq.set(u32::MAX - 1024);
188 assert!(seq.validate_and_increment(u32::MAX - 1024).is_ok());
189 assert_eq!(seq.current(), 1);
190 assert!(seq.validate_and_increment(20).is_ok());
191 assert_eq!(seq.current(), 21);
192 }
193
194 #[test]
195 fn test_sequence_numbers_validate_non_legacy() {
196 let mut seq = SequenceNumberHandle::new(false);
197 assert_eq!(seq.current(), 0);
198 assert!(seq.validate_and_increment(0).is_ok());
199 assert_eq!(seq.current(), 1);
200 assert!(seq.validate_and_increment(1).is_ok());
201 assert_eq!(seq.current(), 2);
202 assert!(seq.validate_and_increment(5).is_err());
203 assert_eq!(seq.current(), 2);
204
205 seq.set(0);
207 assert!(seq.validate_and_increment(50).is_err());
209 assert_eq!(seq.current(), 0);
210 assert!(seq.validate_and_increment(0).is_ok());
211 assert_eq!(seq.current(), 1);
212
213 seq.set(u32::MAX);
215 assert!(seq.validate_and_increment(u32::MAX).is_ok());
216 assert_eq!(seq.current(), 0);
217 assert!(seq.validate_and_increment(0).is_ok());
218 assert_eq!(seq.current(), 1);
219 }
220}