hdds_micro/transport/mesh/
mod.rs1#![allow(dead_code)]
26
27mod header;
28mod neighbor;
29mod router;
30mod seen;
31
32pub use header::{MeshFlags, MeshHeader, MESH_HEADER_SIZE};
33pub use neighbor::{Neighbor, NeighborTable};
34pub use router::{MeshConfig, MeshRouter, RelayDecision};
35pub use seen::SeenCache;
36
37use crate::error::{Error, Result};
38use crate::transport::Transport;
39
40pub const MAX_TTL: u8 = 7;
42
43pub const DEFAULT_TTL: u8 = 3;
45
46pub struct MeshTransport<T: Transport, const NEIGHBORS: usize, const SEEN: usize> {
50 inner: T,
52 router: MeshRouter<NEIGHBORS, SEEN>,
54 node_id: u8,
56 seq: u16,
58 rx_buf: [u8; 256],
60}
61
62impl<T: Transport, const NEIGHBORS: usize, const SEEN: usize> MeshTransport<T, NEIGHBORS, SEEN> {
63 pub fn new(inner: T, node_id: u8, config: MeshConfig) -> Self {
65 Self {
66 inner,
67 router: MeshRouter::new(node_id, config),
68 node_id,
69 seq: 0,
70 rx_buf: [0u8; 256],
71 }
72 }
73
74 pub fn node_id(&self) -> u8 {
76 self.node_id
77 }
78
79 fn next_seq(&mut self) -> u16 {
81 let seq = self.seq;
82 self.seq = self.seq.wrapping_add(1);
83 seq
84 }
85
86 pub fn send_mesh(&mut self, payload: &[u8]) -> Result<()> {
88 if payload.len() > 255 - MESH_HEADER_SIZE {
89 return Err(Error::BufferTooSmall);
90 }
91
92 let header = MeshHeader {
93 src: self.node_id,
94 dst: 0xFF, seq: self.next_seq(),
96 ttl: self.router.config().default_ttl,
97 flags: MeshFlags::empty(),
98 hop_count: 0,
99 };
100
101 self.send_with_header(&header, payload)
102 }
103
104 pub fn send_to(&mut self, dest: u8, payload: &[u8]) -> Result<()> {
106 if payload.len() > 255 - MESH_HEADER_SIZE {
107 return Err(Error::BufferTooSmall);
108 }
109
110 let header = MeshHeader {
111 src: self.node_id,
112 dst: dest,
113 seq: self.next_seq(),
114 ttl: self.router.config().default_ttl,
115 flags: MeshFlags::empty(),
116 hop_count: 0,
117 };
118
119 self.send_with_header(&header, payload)
120 }
121
122 fn send_with_header(&mut self, header: &MeshHeader, payload: &[u8]) -> Result<()> {
124 let mut buf = [0u8; 256];
125 let header_len = header.encode(&mut buf)?;
126
127 let total_len = header_len + payload.len();
128 if total_len > buf.len() {
129 return Err(Error::BufferTooSmall);
130 }
131
132 buf[header_len..total_len].copy_from_slice(payload);
133
134 let locator = crate::rtps::Locator::udpv4([255, 255, 255, 255], 0);
136 self.inner.send(&buf[..total_len], &locator)?;
137 Ok(())
138 }
139
140 pub fn recv_mesh(&mut self, buf: &mut [u8]) -> Result<Option<(u8, usize)>> {
145 let (len, _locator) = match self.inner.try_recv(&mut self.rx_buf) {
147 Ok(result) => result,
148 Err(Error::ResourceExhausted) => return Ok(None),
149 Err(e) => return Err(e),
150 };
151
152 if len < MESH_HEADER_SIZE {
153 return Ok(None); }
155
156 let header = match MeshHeader::decode(&self.rx_buf[..len]) {
158 Ok(h) => h,
159 Err(_) => return Ok(None), };
161
162 let rssi = self.inner.last_rssi();
164
165 let decision = self.router.process_received(&header, rssi);
167
168 match decision {
169 RelayDecision::Deliver => {
170 let payload_start = MESH_HEADER_SIZE;
172 let payload_len = len - payload_start;
173
174 if payload_len > buf.len() {
175 return Err(Error::BufferTooSmall);
176 }
177
178 buf[..payload_len].copy_from_slice(&self.rx_buf[payload_start..len]);
179 Ok(Some((header.src, payload_len)))
180 }
181 RelayDecision::Relay(new_header) => {
182 let payload_start = MESH_HEADER_SIZE;
184 let payload_len = len - payload_start;
185
186 let is_for_us = header.dst == 0xFF || header.dst == self.node_id;
188 let should_deliver = is_for_us && payload_len <= buf.len();
189
190 if should_deliver {
191 buf[..payload_len].copy_from_slice(&self.rx_buf[payload_start..len]);
192 }
193
194 let mut relay_buf = [0u8; 256];
196 relay_buf[..payload_len].copy_from_slice(&self.rx_buf[payload_start..len]);
197
198 let _ = self.send_with_header(&new_header, &relay_buf[..payload_len]);
200
201 if should_deliver {
202 Ok(Some((header.src, payload_len)))
203 } else {
204 Ok(None)
205 }
206 }
207 RelayDecision::Drop => {
208 Ok(None)
210 }
211 }
212 }
213
214 pub fn neighbors(&self) -> &NeighborTable<NEIGHBORS> {
216 self.router.neighbors()
217 }
218
219 pub fn stats(&self) -> MeshStats {
221 self.router.stats()
222 }
223
224 pub fn inner_mut(&mut self) -> &mut T {
226 &mut self.inner
227 }
228
229 pub fn inner(&self) -> &T {
231 &self.inner
232 }
233}
234
235#[derive(Debug, Clone, Copy, Default)]
237pub struct MeshStats {
238 pub tx_originated: u32,
240 pub tx_relayed: u32,
242 pub rx_delivered: u32,
244 pub rx_duplicate: u32,
246 pub rx_ttl_expired: u32,
248}
249
250#[cfg(test)]
251mod tests {
252 use super::*;
253 use crate::transport::NullTransport;
254
255 #[test]
256 fn test_mesh_transport_creation() {
257 let inner = NullTransport::default();
258 let config = MeshConfig::default();
259 let mesh: MeshTransport<_, 8, 32> = MeshTransport::new(inner, 1, config);
260
261 assert_eq!(mesh.node_id(), 1);
262 }
263
264 #[test]
265 fn test_mesh_sequence_increment() {
266 let inner = NullTransport::default();
267 let config = MeshConfig::default();
268 let mut mesh: MeshTransport<_, 8, 32> = MeshTransport::new(inner, 1, config);
269
270 assert_eq!(mesh.next_seq(), 0);
271 assert_eq!(mesh.next_seq(), 1);
272 assert_eq!(mesh.next_seq(), 2);
273 }
274}