Newer
Older
#[derive(Debug, PartialEq, Eq, Clone)]
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
pub struct Route {
pub max_hops: u8,
path: ArrayVec<u8, 254>,
has_future: bool,
}
impl Route {
pub fn new(max_hops: u8) -> Self {
let path = ArrayVec::new();
Self {
max_hops,
path,
has_future: false,
}
}
/// Returns `None` if there isn't enough space for the callsign
/// Returns `None` if attempting to pushed is_used=true after an existing is_used=false
/// is_future=false when this callsign has digipeated
/// is_future=true when this callsign is expected to be part of the route, but isn't yet
/// see the specs for more information
pub fn push_callsign(&mut self, callsign: &str, ssid: u8, is_future: bool) -> Option<()> {
let len = callsign.as_bytes().len() + 2;
let free_space = self.path.capacity() - self.path.len();
if len > free_space {
return None;
}
self.has_future = self.has_future || is_future;
if self.has_future && !is_future {
return None;
}
// safe to unwrap since we already did a length check
self.path
.try_extend_from_slice(callsign.as_bytes())
.unwrap();
self.path.push(if is_future { 0xFD } else { 0xFF });
self.path.push(ssid);
Some(())
}
/// Returns `None` if there isn't enough space
pub fn push_internet(&mut self) -> Option<()> {
let free_space = self.path.capacity() - self.path.len();
if free_space < 1 {
return None;
}
self.path.push(0xFE);
Some(())
}
pub fn iter(&'_ self) -> RouteIter<'_> {
RouteIter::new(self)
}
pub fn encode<'a>(&self, buf: &'a mut [u8]) -> Option<&'a [u8]> {
let packet_len = self.path.len() + 1;
let buf = buf.get_mut(0..(packet_len + 1))?;
buf[0] = packet_len.try_into().unwrap();
buf[1] = self.max_hops;
buf[2..(packet_len + 1)].copy_from_slice(&self.path);
Some(buf)
}
pub fn decode(data: &[u8]) -> Option<Self> {
let len: usize = (*data.first()?).into();
let data = data.get(1..(len + 1))?;
let mut path = ArrayVec::new();
path.try_extend_from_slice(&data[1..]).unwrap();
let has_future = data[1..].iter().any(|x| *x == 0xFD);

Stephen D
committed
let s = Self {

Stephen D
committed
};
if UntrustedRouteIter::new(&s).any(|v| v.is_none()) {
return None;
}
Some(s)
}
}
#[derive(Debug, Eq, PartialEq)]
pub enum RouteNode<'a> {
Internet,
Identity(&'a str, u8, bool),
}

Stephen D
committed
enum UntrustedRoute<'a> {
Some(RouteNode<'a>),
None,
Invalid,
}

Stephen D
committed
struct UntrustedRouteIter<'a> {

Stephen D
committed
seen_future: bool,
dead: bool,

Stephen D
committed
impl<'a> UntrustedRouteIter<'a> {

Stephen D
committed
Self {
route,
i: 0,
seen_future: false,
dead: false,
}

Stephen D
committed
fn maybe_next(&mut self) -> UntrustedRoute<'a> {

Stephen D
committed
return UntrustedRoute::None;
}
let i_start = self.i;
self.i += 1;
if self.route.path[i_start] == 0xFE {

Stephen D
committed
return UntrustedRoute::Some(RouteNode::Internet);
}
while self.route.path[self.i] != 0xFD && self.route.path[self.i] != 0xFF {
self.i += 1;
}

Stephen D
committed
let callsign = match core::str::from_utf8(&self.route.path[i_start..self.i]) {
Ok(x) => x,
Err(_) => return UntrustedRoute::Invalid,
};
let is_future = self.route.path[self.i] == 0xFD;

Stephen D
committed
if self.seen_future && !is_future {
// past after future - not allowed
return UntrustedRoute::Invalid;
}
self.seen_future |= is_future;
self.i += 1;
let ssid = self.route.path[self.i];
self.i += 1;

Stephen D
committed
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
UntrustedRoute::Some(RouteNode::Identity(callsign, ssid, is_future))
}
}
impl<'a> Iterator for UntrustedRouteIter<'a> {
type Item = Option<RouteNode<'a>>;
fn next(&mut self) -> Option<Self::Item> {
if self.dead {
return None;
}
match self.maybe_next() {
UntrustedRoute::Some(v) => Some(Some(v)),
UntrustedRoute::None => None,
UntrustedRoute::Invalid => Some(None),
}
}
}
pub struct RouteIter<'a> {
iter: UntrustedRouteIter<'a>,
}
impl<'a> RouteIter<'a> {
fn new(route: &'a Route) -> Self {
Self {
iter: UntrustedRouteIter::new(route),
}
}
}
impl<'a> Iterator for RouteIter<'a> {
type Item = RouteNode<'a>;
fn next(&mut self) -> Option<Self::Item> {
Some(self.iter.next()?.unwrap())