hdds_micro/transport/mesh/
header.rs1use crate::error::{Error, Result};
7
8pub const MESH_HEADER_SIZE: usize = 7;
10
11const MESH_MAGIC: u8 = 0x4D; #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
16pub struct MeshFlags(u8);
17
18impl MeshFlags {
19 pub const fn empty() -> Self {
21 Self(0)
22 }
23
24 pub const ACK_REQUIRED: Self = Self(0x01);
26
27 pub const IS_ACK: Self = Self(0x02);
29
30 pub const ROUTE_REQUEST: Self = Self(0x04);
32
33 pub const ROUTE_REPLY: Self = Self(0x08);
35
36 pub const BEACON: Self = Self(0x10);
38
39 pub fn contains(&self, flag: Self) -> bool {
41 (self.0 & flag.0) != 0
42 }
43
44 pub fn set(&mut self, flag: Self) {
46 self.0 |= flag.0;
47 }
48
49 pub fn clear(&mut self, flag: Self) {
51 self.0 &= !flag.0;
52 }
53
54 pub fn bits(&self) -> u8 {
56 self.0
57 }
58
59 pub fn from_bits(bits: u8) -> Self {
61 Self(bits)
62 }
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub struct MeshHeader {
76 pub src: u8,
78 pub dst: u8,
80 pub seq: u16,
82 pub ttl: u8,
84 pub flags: MeshFlags,
86 pub hop_count: u8,
88}
89
90impl MeshHeader {
91 pub fn new(src: u8, dst: u8, seq: u16, ttl: u8) -> Self {
93 Self {
94 src,
95 dst,
96 seq,
97 ttl,
98 flags: MeshFlags::empty(),
99 hop_count: 0,
100 }
101 }
102
103 pub fn broadcast(src: u8, seq: u16, ttl: u8) -> Self {
105 Self::new(src, 0xFF, seq, ttl)
106 }
107
108 pub fn is_broadcast(&self) -> bool {
110 self.dst == 0xFF
111 }
112
113 pub fn for_relay(&self) -> Option<Self> {
115 if self.ttl == 0 {
116 return None;
117 }
118
119 Some(Self {
120 src: self.src,
121 dst: self.dst,
122 seq: self.seq,
123 ttl: self.ttl - 1,
124 flags: self.flags,
125 hop_count: self.hop_count.saturating_add(1),
126 })
127 }
128
129 pub fn encode(&self, buf: &mut [u8]) -> Result<usize> {
131 if buf.len() < MESH_HEADER_SIZE {
132 return Err(Error::BufferTooSmall);
133 }
134
135 buf[0] = MESH_MAGIC;
136 buf[1] = self.src;
137 buf[2] = self.dst;
138 buf[3] = (self.seq >> 8) as u8;
139 buf[4] = (self.seq & 0xFF) as u8;
140 buf[5] = (self.ttl & 0x0F) | ((self.hop_count & 0x0F) << 4);
142 buf[6] = self.flags.bits();
143
144 Ok(MESH_HEADER_SIZE)
145 }
146
147 pub fn decode(buf: &[u8]) -> Result<Self> {
149 if buf.len() < MESH_HEADER_SIZE {
150 return Err(Error::BufferTooSmall);
151 }
152
153 if buf[0] != MESH_MAGIC {
154 return Err(Error::InvalidData);
155 }
156
157 let src = buf[1];
158 let dst = buf[2];
159 let seq = ((buf[3] as u16) << 8) | (buf[4] as u16);
160 let ttl = buf[5] & 0x0F;
161 let hop_count = (buf[5] >> 4) & 0x0F;
162 let flags = MeshFlags::from_bits(buf[6]);
163
164 Ok(Self {
165 src,
166 dst,
167 seq,
168 ttl,
169 flags,
170 hop_count,
171 })
172 }
173
174 pub fn message_id(&self) -> u32 {
176 ((self.src as u32) << 16) | (self.seq as u32)
177 }
178}
179
180#[cfg(test)]
181mod tests {
182 use super::*;
183
184 #[test]
185 fn test_header_encode_decode() {
186 let header = MeshHeader {
187 src: 1,
188 dst: 2,
189 seq: 0x1234,
190 ttl: 5,
191 flags: MeshFlags::empty(),
192 hop_count: 2,
193 };
194
195 let mut buf = [0u8; 16];
196 let len = header.encode(&mut buf).unwrap();
197 assert_eq!(len, MESH_HEADER_SIZE);
198
199 let decoded = MeshHeader::decode(&buf).unwrap();
200 assert_eq!(decoded.src, 1);
201 assert_eq!(decoded.dst, 2);
202 assert_eq!(decoded.seq, 0x1234);
203 assert_eq!(decoded.ttl, 5);
204 assert_eq!(decoded.hop_count, 2);
205 }
206
207 #[test]
208 fn test_header_broadcast() {
209 let header = MeshHeader::broadcast(5, 100, 3);
210 assert!(header.is_broadcast());
211 assert_eq!(header.dst, 0xFF);
212 assert_eq!(header.src, 5);
213 assert_eq!(header.seq, 100);
214 assert_eq!(header.ttl, 3);
215 }
216
217 #[test]
218 fn test_header_for_relay() {
219 let header = MeshHeader::new(1, 2, 100, 3);
220 assert_eq!(header.hop_count, 0);
221
222 let relayed = header.for_relay().unwrap();
223 assert_eq!(relayed.ttl, 2);
224 assert_eq!(relayed.hop_count, 1);
225
226 let last_hop = MeshHeader::new(1, 2, 100, 0);
228 assert!(last_hop.for_relay().is_none());
229 }
230
231 #[test]
232 fn test_header_buffer_too_small() {
233 let header = MeshHeader::new(1, 2, 100, 3);
234 let mut buf = [0u8; 4];
235 assert!(header.encode(&mut buf).is_err());
236 }
237
238 #[test]
239 fn test_header_invalid_magic() {
240 let buf = [0x00, 1, 2, 0, 100, 3, 0];
241 assert!(MeshHeader::decode(&buf).is_err());
242 }
243
244 #[test]
245 fn test_flags() {
246 let mut flags = MeshFlags::empty();
247 assert!(!flags.contains(MeshFlags::ACK_REQUIRED));
248
249 flags.set(MeshFlags::ACK_REQUIRED);
250 assert!(flags.contains(MeshFlags::ACK_REQUIRED));
251
252 flags.set(MeshFlags::BEACON);
253 assert!(flags.contains(MeshFlags::ACK_REQUIRED));
254 assert!(flags.contains(MeshFlags::BEACON));
255
256 flags.clear(MeshFlags::ACK_REQUIRED);
257 assert!(!flags.contains(MeshFlags::ACK_REQUIRED));
258 assert!(flags.contains(MeshFlags::BEACON));
259 }
260
261 #[test]
262 fn test_message_id() {
263 let h1 = MeshHeader::new(1, 2, 100, 3);
264 let h2 = MeshHeader::new(1, 2, 100, 3);
265 let h3 = MeshHeader::new(1, 2, 101, 3);
266 let h4 = MeshHeader::new(2, 2, 100, 3);
267
268 assert_eq!(h1.message_id(), h2.message_id());
269 assert_ne!(h1.message_id(), h3.message_id());
270 assert_ne!(h1.message_id(), h4.message_id());
271 }
272}