xref: /webrtc/sctp/src/util.rs (revision 5d8fe953)
1 use bytes::Bytes;
2 use crc::{Crc, CRC_32_ISCSI};
3 
4 pub(crate) const PADDING_MULTIPLE: usize = 4;
5 
get_padding_size(len: usize) -> usize6 pub(crate) fn get_padding_size(len: usize) -> usize {
7     (PADDING_MULTIPLE - (len % PADDING_MULTIPLE)) % PADDING_MULTIPLE
8 }
9 
10 /// Allocate and zero this data once.
11 /// We need to use it for the checksum and don't want to allocate/clear each time.
12 pub(crate) static FOUR_ZEROES: Bytes = Bytes::from_static(&[0, 0, 0, 0]);
13 
14 pub(crate) const ISCSI_CRC: Crc<u32> = Crc::<u32>::new(&CRC_32_ISCSI);
15 
16 /// Fastest way to do a crc32 without allocating.
generate_packet_checksum(raw: &Bytes) -> u3217 pub(crate) fn generate_packet_checksum(raw: &Bytes) -> u32 {
18     let mut digest = ISCSI_CRC.digest();
19     digest.update(&raw[0..8]);
20     digest.update(&FOUR_ZEROES[..]);
21     digest.update(&raw[12..]);
22     digest.finalize()
23 }
24 
25 /// Serial Number Arithmetic (RFC 1982)
26 #[inline]
sna32lt(i1: u32, i2: u32) -> bool27 pub(crate) fn sna32lt(i1: u32, i2: u32) -> bool {
28     (i1 < i2 && i2 - i1 < 1 << 31) || (i1 > i2 && i1 - i2 > 1 << 31)
29 }
30 
31 #[inline]
sna32lte(i1: u32, i2: u32) -> bool32 pub(crate) fn sna32lte(i1: u32, i2: u32) -> bool {
33     i1 == i2 || sna32lt(i1, i2)
34 }
35 
36 #[inline]
sna32gt(i1: u32, i2: u32) -> bool37 pub(crate) fn sna32gt(i1: u32, i2: u32) -> bool {
38     (i1 < i2 && (i2 - i1) >= 1 << 31) || (i1 > i2 && (i1 - i2) <= 1 << 31)
39 }
40 
41 #[inline]
sna32gte(i1: u32, i2: u32) -> bool42 pub(crate) fn sna32gte(i1: u32, i2: u32) -> bool {
43     i1 == i2 || sna32gt(i1, i2)
44 }
45 
46 #[inline]
sna32eq(i1: u32, i2: u32) -> bool47 pub(crate) fn sna32eq(i1: u32, i2: u32) -> bool {
48     i1 == i2
49 }
50 
51 #[inline]
sna16lt(i1: u16, i2: u16) -> bool52 pub(crate) fn sna16lt(i1: u16, i2: u16) -> bool {
53     (i1 < i2 && (i2 - i1) < 1 << 15) || (i1 > i2 && (i1 - i2) > 1 << 15)
54 }
55 
56 #[inline]
sna16lte(i1: u16, i2: u16) -> bool57 pub(crate) fn sna16lte(i1: u16, i2: u16) -> bool {
58     i1 == i2 || sna16lt(i1, i2)
59 }
60 
61 #[inline]
sna16gt(i1: u16, i2: u16) -> bool62 pub(crate) fn sna16gt(i1: u16, i2: u16) -> bool {
63     (i1 < i2 && (i2 - i1) >= 1 << 15) || (i1 > i2 && (i1 - i2) <= 1 << 15)
64 }
65 
66 #[inline]
sna16gte(i1: u16, i2: u16) -> bool67 pub(crate) fn sna16gte(i1: u16, i2: u16) -> bool {
68     i1 == i2 || sna16gt(i1, i2)
69 }
70 
71 #[inline]
sna16eq(i1: u16, i2: u16) -> bool72 pub(crate) fn sna16eq(i1: u16, i2: u16) -> bool {
73     i1 == i2
74 }
75 
76 #[cfg(test)]
77 mod test {
78     use crate::error::Result;
79 
80     use super::*;
81 
82     const DIV: isize = 16;
83 
84     #[test]
test_serial_number_arithmetic32bit() -> Result<()>85     fn test_serial_number_arithmetic32bit() -> Result<()> {
86         const SERIAL_BITS: u32 = 32;
87         const INTERVAL: u32 = ((1u64 << (SERIAL_BITS as u64)) / (DIV as u64)) as u32;
88         const MAX_FORWARD_DISTANCE: u32 = 1 << ((SERIAL_BITS - 1) - 1);
89         const MAX_BACKWARD_DISTANCE: u32 = 1 << (SERIAL_BITS - 1);
90 
91         for i in 0..DIV as u32 {
92             let s1 = i * INTERVAL;
93             let s2f = s1.checked_add(MAX_FORWARD_DISTANCE);
94             let s2b = s1.checked_add(MAX_BACKWARD_DISTANCE);
95 
96             if let (Some(s2f), Some(s2b)) = (s2f, s2b) {
97                 assert!(sna32lt(s1, s2f), "s1 < s2 should be true: s1={s1} s2={s2f}");
98                 assert!(
99                     !sna32lt(s1, s2b),
100                     "s1 < s2 should be false: s1={s1} s2={s2b}"
101                 );
102 
103                 assert!(
104                     !sna32gt(s1, s2f),
105                     "s1 > s2 should be false: s1={s1} s2={s2f}"
106                 );
107                 assert!(sna32gt(s1, s2b), "s1 > s2 should be true: s1={s1} s2={s2b}");
108 
109                 assert!(
110                     sna32lte(s1, s2f),
111                     "s1 <= s2 should be true: s1={s1} s2={s2f}"
112                 );
113                 assert!(
114                     !sna32lte(s1, s2b),
115                     "s1 <= s2 should be false: s1={s1} s2={s2b}"
116                 );
117 
118                 assert!(
119                     !sna32gte(s1, s2f),
120                     "s1 >= s2 should be fales: s1={s1} s2={s2f}"
121                 );
122                 assert!(
123                     sna32gte(s1, s2b),
124                     "s1 >= s2 should be true: s1={s1} s2={s2b}"
125                 );
126 
127                 assert!(
128                     sna32eq(s2b, s2b),
129                     "s2 == s2 should be true: s2={s2b} s2={s2b}"
130                 );
131                 assert!(
132                     sna32lte(s2b, s2b),
133                     "s2 == s2 should be true: s2={s2b} s2={s2b}"
134                 );
135                 assert!(
136                     sna32gte(s2b, s2b),
137                     "s2 == s2 should be true: s2={s2b} s2={s2b}"
138                 );
139             }
140 
141             if let Some(s1add1) = s1.checked_add(1) {
142                 assert!(
143                     !sna32eq(s1, s1add1),
144                     "s1 == s1+1 should be false: s1={s1} s1+1={s1add1}"
145                 );
146             }
147 
148             if let Some(s1sub1) = s1.checked_sub(1) {
149                 assert!(
150                     !sna32eq(s1, s1sub1),
151                     "s1 == s1-1 hould be false: s1={s1} s1-1={s1sub1}"
152                 );
153             }
154 
155             assert!(sna32eq(s1, s1), "s1 == s1 should be true: s1={s1} s2={s1}");
156             assert!(sna32lte(s1, s1), "s1 == s1 should be true: s1={s1} s2={s1}");
157 
158             assert!(sna32gte(s1, s1), "s1 == s1 should be true: s1={s1} s2={s1}");
159         }
160 
161         Ok(())
162     }
163 
164     #[test]
test_serial_number_arithmetic16bit() -> Result<()>165     fn test_serial_number_arithmetic16bit() -> Result<()> {
166         const SERIAL_BITS: u16 = 16;
167         const INTERVAL: u16 = ((1u64 << (SERIAL_BITS as u64)) / (DIV as u64)) as u16;
168         const MAX_FORWARD_DISTANCE: u16 = 1 << ((SERIAL_BITS - 1) - 1);
169         const MAX_BACKWARD_DISTANCE: u16 = 1 << (SERIAL_BITS - 1);
170 
171         for i in 0..DIV as u16 {
172             let s1 = i * INTERVAL;
173             let s2f = s1.checked_add(MAX_FORWARD_DISTANCE);
174             let s2b = s1.checked_add(MAX_BACKWARD_DISTANCE);
175 
176             if let (Some(s2f), Some(s2b)) = (s2f, s2b) {
177                 assert!(sna16lt(s1, s2f), "s1 < s2 should be true: s1={s1} s2={s2f}");
178                 assert!(
179                     !sna16lt(s1, s2b),
180                     "s1 < s2 should be false: s1={s1} s2={s2b}"
181                 );
182 
183                 assert!(
184                     !sna16gt(s1, s2f),
185                     "s1 > s2 should be fales: s1={s1} s2={s2f}"
186                 );
187                 assert!(sna16gt(s1, s2b), "s1 > s2 should be true: s1={s1} s2={s2b}");
188 
189                 assert!(
190                     sna16lte(s1, s2f),
191                     "s1 <= s2 should be true: s1={s1} s2={s2f}"
192                 );
193                 assert!(
194                     !sna16lte(s1, s2b),
195                     "s1 <= s2 should be false: s1={s1} s2={s2b}"
196                 );
197 
198                 assert!(
199                     !sna16gte(s1, s2f),
200                     "s1 >= s2 should be fales: s1={s1} s2={s2f}"
201                 );
202                 assert!(
203                     sna16gte(s1, s2b),
204                     "s1 >= s2 should be true: s1={s1} s2={s2b}"
205                 );
206 
207                 assert!(
208                     sna16eq(s2b, s2b),
209                     "s2 == s2 should be true: s2={s2b} s2={s2b}"
210                 );
211                 assert!(
212                     sna16lte(s2b, s2b),
213                     "s2 == s2 should be true: s2={s2b} s2={s2b}"
214                 );
215                 assert!(
216                     sna16gte(s2b, s2b),
217                     "s2 == s2 should be true: s2={s2b} s2={s2b}"
218                 );
219             }
220 
221             assert!(sna16eq(s1, s1), "s1 == s1 should be true: s1={s1} s2={s1}");
222 
223             if let Some(s1add1) = s1.checked_add(1) {
224                 assert!(
225                     !sna16eq(s1, s1add1),
226                     "s1 == s1+1 should be false: s1={s1} s1+1={s1add1}"
227                 );
228             }
229             if let Some(s1sub1) = s1.checked_sub(1) {
230                 assert!(
231                     !sna16eq(s1, s1sub1),
232                     "s1 == s1-1 hould be false: s1={s1} s1-1={s1sub1}"
233                 );
234             }
235 
236             assert!(sna16lte(s1, s1), "s1 == s1 should be true: s1={s1} s2={s1}");
237             assert!(sna16gte(s1, s1), "s1 == s1 should be true: s1={s1} s2={s1}");
238         }
239 
240         Ok(())
241     }
242 }
243