1use log::{error, trace};
2use tokio::sync::broadcast::Sender;
3
4pub const PUBLISH: u8 = 0x02;
6pub const SUBSCRIBE: u8 = 0x03;
8pub const UNSUBSCRIBE: u8 = 0x04;
10pub const QUERY: u8 = 0x05;
12pub const PUBLISHACK: u8 = 0x0B;
14pub const SUBSCRIBEACK: u8 = 0x0C;
16pub const UNSUBSCRIBEACK: u8 = 0x0D;
18pub const QUERYRESP: u8 = 0x0E;
20
21#[derive(Debug, Clone, PartialEq)]
23pub enum PktType {
24 PUBLISH,
26 SUBSCRIBE,
28 UNSUBSCRIBE,
30 QUERY,
32 PUBLISHACK,
34 SUBSCRIBEACK,
36 UNSUBSCRIBEACK,
38 QUERYRESP,
40}
41impl PktType {
42 pub fn to_byte(&self) -> u8 {
44 match self {
45 PktType::PUBLISH => PUBLISH,
46 PktType::SUBSCRIBE => SUBSCRIBE,
47 PktType::UNSUBSCRIBE => UNSUBSCRIBE,
48 PktType::QUERY => QUERY,
49 PktType::PUBLISHACK => PUBLISHACK,
50 PktType::SUBSCRIBEACK => SUBSCRIBEACK,
51 PktType::UNSUBSCRIBEACK => UNSUBSCRIBEACK,
52 PktType::QUERYRESP => QUERYRESP,
53 }
54 }
55}
56impl ToString for PktType {
57 fn to_string(&self) -> String {
59 match self {
60 PktType::PUBLISH => "PUBLISH".to_string(),
61 PktType::SUBSCRIBE => "SUBSCRIBE".to_string(),
62 PktType::UNSUBSCRIBE => "UNSUBSCRIBE".to_string(),
63 PktType::QUERY => "QUERY".to_string(),
64 PktType::PUBLISHACK => "PUBLISH_ACK".to_string(),
65 PktType::SUBSCRIBEACK => "SUBSCRIBE_ACK".to_string(),
66 PktType::UNSUBSCRIBEACK => "UNSUBSCRIBE_ACK".to_string(),
67 PktType::QUERYRESP => "QUERY_RESP".to_string(),
68 }
69 }
70}
71
72pub const SUPPORTED_VERSIONS: [[u8; 2]; 1] = [[0x00, 0x01]];
74
75pub const DEFAULT_VERSION: [u8; 2] = [0x00, 0x01];
77
78#[derive(Debug, Clone)]
80pub enum HeaderError {
81 InvalidHeaderBufferLength,
83 InvalidHeadOrTail,
85 UnsupportedVersion,
87 InvalidMessageType,
89 InvalidTopicLength,
91 InvalidMessageLength,
93 InvalidResuestResponseType,
95}
96
97#[derive(Debug, Clone)]
100pub struct Header {
101 pub header: u8,
103 pub version: [u8; 2],
105 pub pkt_type: PktType,
107 pub topic_length: u8,
109 pub message_length: u16,
111 pub padding: u8,
113}
114
115#[derive(Debug, Clone)]
117pub struct Msg {
118 pub header: Header,
120 pub topic: String,
122 pub message: Vec<u8>,
124 pub channel: Option<Sender<Msg>>,
126 pub client_id: Option<String>,
128}
129
130impl Msg {
131 pub fn new(pkt_type: PktType, topic: String, message: Option<Vec<u8>>) -> Msg {
133 let msg: Vec<u8> = match message {
134 Some(m) => m,
135 None => vec![],
136 };
137
138 Msg {
139 header: Header::new(pkt_type, topic.len() as u8, msg.len() as u16),
140 topic,
141 message: msg,
142 channel: None,
143 client_id: None,
144 }
145 }
146
147 pub fn channel(&mut self, chan: Sender<Msg>) {
149 self.channel = Some(chan);
150 }
151
152 pub fn client_id(&mut self, client_id: String) {
154 self.client_id = Some(client_id);
155 }
156
157 pub fn response_msg(&self, _message: Vec<u8>) -> Result<Msg, String> {
159 let mut header: Header = match self.header.response_header() {
160 Ok(h) => h,
161 Err(e) => {
162 error!("unable to generate the response header: {:?}", e);
163 return Err("unable to generate response header".to_string());
164 }
165 };
166 header.message_length = _message.len() as u16;
167 Ok(Msg {
168 header,
169 topic: self.topic.clone(),
170 message: _message,
171 channel: None,
172 client_id: None,
173 })
174 }
175
176 pub fn bytes(&self) -> Vec<u8> {
178 let mut buffer: Vec<u8> = self.header.bytes();
179 buffer.extend(self.topic.as_bytes().to_vec());
180 buffer.extend(self.message.clone());
181 trace!("the generated buffer is: {:?}", buffer);
182 buffer
183 }
184}
185
186impl Header {
187 pub fn new(pkt_type: PktType, topic_len: u8, message_len: u16) -> Header {
189 Header {
190 header: 0x0F,
191 version: DEFAULT_VERSION,
192 pkt_type,
193 topic_length: topic_len,
194 message_length: message_len,
195 padding: 0x00,
196 }
197 }
198
199 pub fn response_header(&self) -> Result<Header, HeaderError> {
201 let resp_type: PktType = match self.pkt_type {
202 PktType::SUBSCRIBE => PktType::SUBSCRIBEACK,
203 PktType::PUBLISH => PktType::PUBLISHACK,
204 PktType::UNSUBSCRIBE => PktType::UNSUBSCRIBEACK,
205 PktType::QUERY => PktType::QUERYRESP,
206 _ => {
207 error!("invalid request/response type");
208 return Err(HeaderError::InvalidResuestResponseType);
209 }
210 };
211 Ok(Header {
212 header: 0x0F,
213 version: self.version,
214 pkt_type: resp_type,
215 topic_length: self.topic_length,
216 message_length: self.message_length,
217 padding: 0x00,
218 })
219 }
220
221 pub fn bytes(&self) -> Vec<u8> {
223 let bytes_ = self.message_length.to_be_bytes();
224 vec![
225 self.header,
226 self.version[0],
227 self.version[1],
228 self.pkt_type.to_byte(),
229 self.topic_length,
230 bytes_[0],
231 bytes_[1],
232 self.padding,
233 ]
234 }
235
236 pub fn from_vec(bytes: Vec<u8>) -> Result<Header, HeaderError> {
238 if !bytes.len() == 8 {
239 error!("invalid header buffer length, aborting");
240 return Err(HeaderError::InvalidHeaderBufferLength);
241 }
242
243 if !(bytes[0] == 0x0F && bytes[7] == 0x00) {
244 error!("invalid header value, aborting");
245 return Err(HeaderError::InvalidHeadOrTail);
246 }
247
248 if !SUPPORTED_VERSIONS.contains(&[bytes[1], bytes[2]]) {
249 error!("unsupported packet version, aborting");
250 return Err(HeaderError::UnsupportedVersion);
251 }
252
253 let pkt_type: PktType = match bytes[3] {
254 PUBLISH => PktType::PUBLISH,
255 SUBSCRIBE => PktType::SUBSCRIBE,
256 UNSUBSCRIBE => PktType::UNSUBSCRIBE,
257 QUERY => PktType::QUERY,
258 PUBLISHACK => PktType::PUBLISHACK,
259 SUBSCRIBEACK => PktType::SUBSCRIBEACK,
260 QUERYRESP => PktType::QUERYRESP,
261 _ => {
262 error!("invalid message type, aborting");
263 return Err(HeaderError::InvalidMessageType);
264 }
265 };
266
267 if bytes[4] == 0 {
268 match pkt_type {
269 PktType::PUBLISH => {
270 error!("invalid topic length, aborting");
271 return Err(HeaderError::InvalidTopicLength);
272 }
273 PktType::SUBSCRIBE => {
274 error!("invalid topic length, aborting");
275 return Err(HeaderError::InvalidTopicLength);
276 }
277 PktType::UNSUBSCRIBE => {
278 error!("invalid topic length, aborting");
279 return Err(HeaderError::InvalidTopicLength);
280 }
281 PktType::QUERY => {
282 error!("invalid topic length, aborting");
283 return Err(HeaderError::InvalidTopicLength);
284 }
285 _ => {}
286 };
287 }
288
289 let message_length = ((bytes[5] as u16) << 8) | bytes[6] as u16;
290
291 if message_length == 0 {
292 match pkt_type {
293 PktType::PUBLISH => {
294 error!("invalid message length, aborting");
295 return Err(HeaderError::InvalidMessageLength);
296 }
297 PktType::QUERY => {
298 error!("invalid message length, aborting");
299 return Err(HeaderError::InvalidMessageLength);
300 }
301 _ => {}
302 };
303 }
304 Ok(Header {
305 header: 0x0F,
306 version: [bytes[1], bytes[2]],
307 pkt_type,
308 topic_length: bytes[4],
309 message_length,
310 padding: 0x00,
311 })
312 }
313}
314
315pub fn get_msg_response(msg: Msg) -> Result<Vec<u8>, String> {
317 let mut resp: Vec<u8> = match msg.response_msg(msg.message.clone()) {
318 Ok(m) => m.header.bytes(),
319 Err(e) => {
320 error!(
321 "error occurred while generating the response message: {}",
322 e
323 );
324 return Err(e);
325 }
326 };
327 resp.extend(msg.topic.bytes());
328 Ok(resp)
329}