1use proto::{Protocol, QoS};
2
3bitflags! {
4 pub struct ConnectFlags: u8 {
5 const USERNAME = 0b10000000;
6 const PASSWORD = 0b01000000;
7 const WILL_RETAIN = 0b00100000;
8 const WILL_QOS = 0b00011000;
9 const WILL = 0b00000100;
10 const CLEAN_SESSION = 0b00000010;
11 }
12}
13
14pub const WILL_QOS_SHIFT: u8 = 3;
15
16bitflags! {
17 pub struct ConnectAckFlags: u8 {
18 const SESSION_PRESENT = 0b00000001;
19 }
20}
21
22#[repr(u8)]
23#[derive(Debug, Eq, PartialEq, Copy, Clone)]
24pub enum ConnectReturnCode {
26 ConnectionAccepted = 0,
28 UnacceptableProtocolVersion = 1,
30 IdentifierRejected = 2,
32 ServiceUnavailable = 3,
34 BadUserNameOrPassword = 4,
36 NotAuthorized = 5,
38 Reserved = 6,
40}
41
42const_enum!(ConnectReturnCode: u8);
43
44impl ConnectReturnCode {
45 pub fn reason(&self) -> &'static str {
46 match *self {
47 ConnectReturnCode::ConnectionAccepted => "Connection Accepted",
48 ConnectReturnCode::UnacceptableProtocolVersion => {
49 "Connection Refused, unacceptable protocol version"
50 }
51 ConnectReturnCode::IdentifierRejected => "Connection Refused, identifier rejected",
52 ConnectReturnCode::ServiceUnavailable => "Connection Refused, Server unavailable",
53 ConnectReturnCode::BadUserNameOrPassword => {
54 "Connection Refused, bad user name or password"
55 }
56 ConnectReturnCode::NotAuthorized => "Connection Refused, not authorized",
57 _ => "Connection Refused",
58 }
59 }
60}
61
62#[derive(Debug, PartialEq, Clone)]
63pub struct FixedHeader {
64 pub packet_type: u8,
66 pub packet_flags: u8,
68 pub remaining_length: usize,
71}
72
73#[derive(Debug, PartialEq, Clone)]
74pub struct LastWill<'a> {
76 pub qos: QoS,
78 pub retain: bool,
80 pub topic: &'a str,
82 pub message: &'a [u8],
84}
85
86#[derive(Debug, PartialEq, Copy, Clone)]
87pub enum SubscribeReturnCode {
89 Success(QoS),
90 Failure,
91}
92
93#[derive(Debug, PartialEq, Clone)]
94pub enum Packet<'a> {
96 Connect {
98 protocol: Protocol,
99 clean_session: bool,
101 keep_alive: u16,
103 last_will: Option<LastWill<'a>>,
105 client_id: &'a str,
107 username: Option<&'a str>,
109 password: Option<&'a [u8]>,
111 },
112 ConnectAck {
114 session_present: bool,
117 return_code: ConnectReturnCode,
118 },
119 Publish {
121 dup: bool,
123 retain: bool,
124 qos: QoS,
126 topic: &'a str,
128 packet_id: Option<u16>,
130 payload: &'a [u8],
132 },
133 PublishAck {
135 packet_id: u16,
137 },
138 PublishReceived {
140 packet_id: u16,
142 },
143 PublishRelease {
145 packet_id: u16,
147 },
148 PublishComplete {
150 packet_id: u16,
152 },
153 Subscribe {
155 packet_id: u16,
157 topic_filters: Vec<(&'a str, QoS)>,
159 },
160 SubscribeAck {
162 packet_id: u16,
163 status: Vec<SubscribeReturnCode>,
165 },
166 Unsubscribe {
168 packet_id: u16,
170 topic_filters: Vec<&'a str>,
172 },
173 UnsubscribeAck {
175 packet_id: u16,
177 },
178 PingRequest,
180 PingResponse,
182 Disconnect,
184}
185
186impl<'a> Packet<'a> {
187 #[inline]
188 pub fn packet_type(&self) -> u8 {
190 match *self {
191 Packet::Connect { .. } => CONNECT,
192 Packet::ConnectAck { .. } => CONNACK,
193 Packet::Publish { .. } => PUBLISH,
194 Packet::PublishAck { .. } => PUBACK,
195 Packet::PublishReceived { .. } => PUBREC,
196 Packet::PublishRelease { .. } => PUBREL,
197 Packet::PublishComplete { .. } => PUBCOMP,
198 Packet::Subscribe { .. } => SUBSCRIBE,
199 Packet::SubscribeAck { .. } => SUBACK,
200 Packet::Unsubscribe { .. } => UNSUBSCRIBE,
201 Packet::UnsubscribeAck { .. } => UNSUBACK,
202 Packet::PingRequest => PINGREQ,
203 Packet::PingResponse => PINGRESP,
204 Packet::Disconnect => DISCONNECT,
205 }
206 }
207
208 pub fn packet_flags(&self) -> u8 {
210 match *self {
211 Packet::Publish { dup, qos, retain, .. } => {
212 let mut b = qos.into();
213
214 b <<= 1;
215
216 if dup {
217 b |= 0b1000;
218 }
219
220 if retain {
221 b |= 0b0001;
222 }
223
224 b
225 }
226 Packet::PublishRelease { .. } |
227 Packet::Subscribe { .. } |
228 Packet::Unsubscribe { .. } => 0b0010,
229 _ => 0,
230 }
231 }
232}
233
234pub const CONNECT: u8 = 1;
235pub const CONNACK: u8 = 2;
236pub const PUBLISH: u8 = 3;
237pub const PUBACK: u8 = 4;
238pub const PUBREC: u8 = 5;
239pub const PUBREL: u8 = 6;
240pub const PUBCOMP: u8 = 7;
241pub const SUBSCRIBE: u8 = 8;
242pub const SUBACK: u8 = 9;
243pub const UNSUBSCRIBE: u8 = 10;
244pub const UNSUBACK: u8 = 11;
245pub const PINGREQ: u8 = 12;
246pub const PINGRESP: u8 = 13;
247pub const DISCONNECT: u8 = 14;