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
102
use super::*;
use crate::*;
use bytes::{Buf, BufMut, Bytes, BytesMut};
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(u8)]
pub enum ConnectReturnCode {
Accepted = 0,
RefusedProtocolVersion,
BadClientId,
ServiceUnavailable,
BadUsernamePassword,
NotAuthorized,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ConnAck {
pub session_present: bool,
pub code: ConnectReturnCode,
}
impl ConnAck {
pub fn new(code: ConnectReturnCode, session_present: bool) -> ConnAck {
ConnAck {
code,
session_present,
}
}
pub(crate) fn assemble(fixed_header: FixedHeader, mut bytes: Bytes) -> Result<Self, Error> {
let variable_header_index = fixed_header.fixed_len;
bytes.advance(variable_header_index);
if fixed_header.remaining_len != 2 {
return Err(Error::PayloadSizeIncorrect);
}
let flags = bytes.get_u8();
let return_code = bytes.get_u8();
let session_present = (flags & 0x01) == 1;
let code = connect_return(return_code)?;
let connack = ConnAck {
session_present,
code,
};
Ok(connack)
}
fn len(&self) -> usize {
1 + 1
}
pub fn write(&self, buffer: &mut BytesMut) -> Result<usize, Error> {
let len = self.len();
buffer.reserve(len);
buffer.put_u8(0x20);
let count = write_remaining_length(buffer, len)?;
buffer.put_u8(self.session_present as u8);
buffer.put_u8(self.code as u8);
Ok(1 + count + len)
}
}
fn connect_return(num: u8) -> Result<ConnectReturnCode, Error> {
match num {
0 => Ok(ConnectReturnCode::Accepted),
1 => Ok(ConnectReturnCode::RefusedProtocolVersion),
2 => Ok(ConnectReturnCode::BadClientId),
3 => Ok(ConnectReturnCode::ServiceUnavailable),
4 => Ok(ConnectReturnCode::BadUsernamePassword),
5 => Ok(ConnectReturnCode::NotAuthorized),
num => Err(Error::InvalidConnectReturnCode(num)),
}
}
#[cfg(test)]
mod test {
use crate::{ConnAck, ConnectReturnCode};
use alloc::vec;
use bytes::BytesMut;
#[test]
fn write_packet_connack_works() {
let connack = ConnAck {
session_present: true,
code: ConnectReturnCode::Accepted,
};
let mut buf = BytesMut::new();
connack.write(&mut buf).unwrap();
assert_eq!(buf, vec![0b0010_0000, 0x02, 0x01, 0x00]);
}
}