twamp_rs/twamp_control/
server_start.rs1use super::accept::Accept;
2use crate::timestamp::timestamp::TimeStamp;
3use deku::prelude::*;
4use rand::random;
5use std::time::Duration;
6
7#[derive(Clone, Debug, PartialEq, DekuRead, DekuWrite)]
9#[deku(endian = "big")]
10pub struct ServerStart {
11 #[deku(assert_eq = "[0u8; 15]")]
13 mbz_start: [u8; 15],
14
15 accept: Accept,
17
18 server_iv: [u8; 16],
21
22 start_time: TimeStamp,
24
25 #[deku(assert_eq = "[0u8; 8]")]
27 mbz_end: [u8; 8],
28}
29
30impl ServerStart {
31 pub fn new(accept: Accept, start_time: Duration) -> Self {
33 ServerStart {
34 mbz_start: [0; 15],
35 accept,
36 server_iv: Vec::from([0; 16])
37 .iter()
38 .map(|_| random())
39 .collect::<Vec<u8>>()
40 .try_into()
41 .unwrap(),
42 start_time: TimeStamp::try_from(start_time)
43 .expect("should have converted duration to timestamp."),
44 mbz_end: [0; 8],
45 }
46 }
47
48 pub fn accept(&self) -> &Accept {
50 &self.accept
51 }
52
53 pub fn start_time(&self) -> &TimeStamp {
55 &self.start_time
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use std::collections::HashSet;
63
64 const SERVER_START_LENGTH_IN_BYTES: usize = 48;
65 const TIME: Duration = Duration::new(1713023152, 123456789);
66
67 #[test]
68 fn create_server_start_with_accept_ok() {
69 let accept = Accept::Ok;
70 let server_start = ServerStart::new(accept, TIME);
71 let server_start_accept: u8 = server_start.accept.into();
72 assert_eq!(server_start_accept, accept.into());
73 }
74
75 #[test]
76 fn create_server_start_with_accept_failure() {
77 let accept = Accept::Failure;
78 let server_start = ServerStart::new(accept, TIME);
79 let server_start_accept: u8 = server_start.accept.into();
80 assert_eq!(server_start_accept, accept.into());
81 }
82
83 #[test]
84 fn create_server_start_with_accept_internal_error() {
85 let accept = Accept::InternalError;
86 let server_start = ServerStart::new(accept, TIME);
87 let server_start_accept: u8 = server_start.accept.into();
88 assert_eq!(server_start_accept, accept.into());
89 }
90
91 #[test]
92 fn create_server_start_with_accept_not_supported() {
93 let accept = Accept::NotSupported;
94 let server_start = ServerStart::new(accept, TIME);
95 let server_start_accept: u8 = server_start.accept.into();
96 assert_eq!(server_start_accept, accept.into());
97 }
98
99 #[test]
100 fn create_server_start_with_accept_permanent_resource_limitation() {
101 let accept = Accept::PermanentResourceLimitation;
102 let server_start = ServerStart::new(accept, TIME);
103 let server_start_accept: u8 = server_start.accept.into();
104 assert_eq!(server_start_accept, accept.into());
105 }
106
107 #[test]
108 fn create_server_start_with_accept_temporary_resource_limitation() {
109 let accept = Accept::TemporaryResourceLimitation;
110 let server_start = ServerStart::new(accept, TIME);
111 let server_start_accept: u8 = server_start.accept.into();
112 assert_eq!(server_start_accept, accept.into());
113 }
114
115 #[test]
116 fn first_mbz_are_zeros() {
117 let server_start = ServerStart::new(Accept::Ok, TIME);
118 assert!(server_start.mbz_start == [0; 15]);
119 }
120
121 #[test]
122 fn last_mbz_are_zeros() {
123 let server_start = ServerStart::new(Accept::Ok, TIME);
124 assert!(server_start.mbz_end == [0; 8]);
125 }
126
127 #[test]
128 fn server_iv_is_random() {
129 let server_start = ServerStart::new(Accept::Ok, TIME);
130 let server_iv_bytes_unique = server_start.server_iv.iter().collect::<HashSet<_>>();
131 assert!(server_iv_bytes_unique.len() > 1);
132 }
133
134 #[test]
135 fn should_serialize_to_correct_bytes() {
136 let server_start = ServerStart::new(Accept::Ok, TIME);
137 let encoded = server_start.to_bytes().unwrap();
138 assert_eq!(encoded.len(), SERVER_START_LENGTH_IN_BYTES);
139 }
140
141 #[test]
142 fn should_deserialize_to_correct_struct() {
143 let server_start = ServerStart::new(Accept::Ok, TIME);
144 let encoded = server_start.to_bytes().unwrap();
145 let (_rest, val) = ServerStart::from_bytes((&encoded, 0)).unwrap();
146 assert_eq!(val, server_start);
147 }
148}