1
2
3
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use super::*;
use std::convert::TryFrom;
use std::error::Error as stdError;
fn random_token(buffer: &[u8]) -> u16 {
(buffer[1] as u16) << 8 | buffer[2] as u16
}
pub fn gateway_mac(buffer: &[u8]) -> MacAddress {
MacAddress::new(array_ref![buffer, 0, 8])
}
pub trait Parser {
fn parse(buffer: &[u8], num_recv: usize) -> std::result::Result<Packet, Box<dyn stdError>>;
}
impl Parser for Packet {
fn parse(buffer: &[u8], num_recv: usize) -> std::result::Result<Packet, Box<dyn stdError>> {
if buffer[0] != PROTOCOL_VERSION {
Err(Error::InvalidProtocolVersion.into())
} else if let Ok(id) = Identifier::try_from(buffer[3]) {
let random_token = random_token(buffer);
Ok(match id {
Identifier::PullData => {
let gateway_mac = gateway_mac(&buffer[4..12]);
pull_data::Packet {
random_token,
gateway_mac,
}
.into()
}
Identifier::PushData => {
let gateway_mac = gateway_mac(&buffer[4..12]);
let json_str = std::str::from_utf8(&buffer[12..num_recv])?;
let data = serde_json::from_str(json_str)?;
push_data::Packet {
random_token,
gateway_mac,
data,
}
.into()
}
Identifier::TxAck => {
let gateway_mac = gateway_mac(&buffer[4..12]);
tx_ack::Packet {
random_token,
gateway_mac,
}
.into()
}
Identifier::PushAck => push_ack::Packet { random_token }.into(),
Identifier::PullAck => pull_ack::Packet { random_token }.into(),
Identifier::PullResp => {
let json_str = std::str::from_utf8(&buffer[4..num_recv])?;
let data = serde_json::from_str(json_str)?;
pull_resp::Packet { random_token, data }.into()
}
})
} else {
Err(Error::InvalidIdentifier.into())
}
}
}
use std::{fmt, str};
#[derive(Debug, Clone)]
pub enum Error {
InvalidProtocolVersion,
InvalidIdentifier,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::InvalidProtocolVersion => {
write!(f, "Invalid protocol version (byte 0 in UDP frame)")
}
Error::InvalidIdentifier => {
write!(f, "Invalid message identifier (byte 3 in UDP frame)")
}
}
}
}
impl stdError for Error {
fn description(&self) -> &str {
match self {
Error::InvalidProtocolVersion => "Invalid protocol version (byte 0 in UDP frame)",
Error::InvalidIdentifier => "Invalid message identifier (byte 3 in UDP frame)",
}
}
fn cause(&self) -> Option<&dyn stdError> {
None
}
}