walle_mqtt_protocol/v4/
conn_ack.rs

1use bytes::{Buf, BufMut, Bytes, BytesMut};
2
3use crate::error::ProtoError;
4use crate::QoS;
5
6use super::{
7    decoder,
8    fixed_header::{FixedHeader, FixedHeaderBuilder},
9    Decoder, Encoder, VariableDecoder,
10};
11
12/// 链接回执报文
13/**
14
15 | Bit  | 7  | 6 | 5  | 4 | 3 | 2 | 1 | 0 |
16 | -----| ---| ---|---|---|---|---|---|---|
17 | byte1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
18 | byte2 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
19 | byte3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |sp |
20 | byte4 | 连 |接 |返 |回 | 码 | C | R | C |
21*/
22#[derive(Debug, PartialOrd, Clone, PartialEq)]
23pub struct ConnAck {
24    fixed_header: FixedHeader,
25    variable_header: ConnAckVariableHeader,
26}
27
28impl ConnAck {
29    pub fn new(conn_ack_type: ConnAckType) -> Result<ConnAck, ProtoError> {
30        let fixed_header = FixedHeaderBuilder::new().conn_ack().build();
31        match fixed_header {
32            Ok(f_header) => Ok(Self {
33                fixed_header: f_header,
34                variable_header: ConnAckVariableHeader::new(conn_ack_type),
35            }),
36            Err(e) => Err(e),
37        }
38    }
39    /// 返回CONNACK的返回类型
40    pub fn conn_ack_type(&self) -> ConnAckType {
41        self.variable_header.conn_ack_type.clone()
42    }
43}
44
45#[derive(PartialOrd, Debug, Clone, PartialEq)]
46pub enum ConnAckType {
47    // 连接成功
48    Success,
49    // 版本错误
50    ProtoVersionError,
51    // 不符合规定的client_id
52    IdentifierRejected,
53    // 服务不可用
54    ServiceUnavailable,
55    // 账号或者密码错误
56    BadUsernameOrPassword,
57    // 未授权
58    NotAuthentication,
59}
60//////////////////////////////////////////////////////////
61/// 为ConnAck实现Encoder trait
62/////////////////////////////////////////////////////////
63impl Encoder for ConnAck {
64    fn encode(&self, buffer: &mut BytesMut) -> Result<usize, ProtoError> {
65        let count = self.fixed_header.encode(buffer);
66        match count {
67            Ok(count) => {
68                if let Ok(v) = self.variable_header.encode(buffer) {
69                    return Ok(count + v);
70                }
71                Err(ProtoError::EncodeVariableHeaderError)
72            }
73            Err(e) => Err(e),
74        }
75    }
76}
77//////////////////////////////////////////////////////////
78/// 为ConnAck实现Decoder trait
79/////////////////////////////////////////////////////////
80impl Decoder for ConnAck {
81    type Item = ConnAck;
82    type Error = ProtoError;
83    fn decode(mut bytes: Bytes) -> Result<Self::Item, ProtoError> {
84        let resp = decoder::read_fixed_header(&mut bytes);
85        match resp {
86            Ok(fixed_header) => {
87                let qos = fixed_header.qos();
88                let variable_header_index = fixed_header.len();
89                bytes.advance(variable_header_index);
90                // 读取variable_header
91                let resp = ConnAckVariableHeader::decode(&mut bytes, qos);
92                match resp {
93                    Ok(variable_header) => Ok(ConnAck {
94                        fixed_header,
95                        variable_header,
96                    }),
97                    Err(e) => return Err(e),
98                }
99            }
100            Err(e) => Err(e),
101        }
102    }
103}
104
105#[derive(Debug, PartialOrd, Clone, PartialEq)]
106pub struct ConnAckVariableHeader {
107    session_present: bool,
108    conn_ack_type: ConnAckType,
109}
110
111impl ConnAckVariableHeader {
112    pub fn new(conn_ack_type: ConnAckType) -> Self {
113        Self {
114            session_present: false,
115            conn_ack_type,
116        }
117    }
118}
119
120//////////////////////////////////////////////////////////
121/// 为ConnAckVariableHeader实现Encoder trait
122/////////////////////////////////////////////////////////
123impl Encoder for ConnAckVariableHeader {
124    fn encode(&self, buffer: &mut BytesMut) -> Result<usize, ProtoError> {
125        buffer.put_u8(0b0000_0000);
126        match &self.conn_ack_type {
127            ConnAckType::Success => {
128                buffer.put_u8(0b0000_0000);
129                Ok(2)
130            }
131            ConnAckType::ProtoVersionError => {
132                buffer.put_u8(0b0000_0001);
133                Ok(2)
134            }
135            ConnAckType::IdentifierRejected => {
136                buffer.put_u8(0b0000_0010);
137                Ok(2)
138            }
139            ConnAckType::ServiceUnavailable => {
140                buffer.put_u8(0b0000_0011);
141                Ok(2)
142            }
143            ConnAckType::BadUsernameOrPassword => {
144                buffer.put_u8(0b0000_0100);
145                Ok(2)
146            }
147            ConnAckType::NotAuthentication => {
148                buffer.put_u8(0b0000_0101);
149                Ok(2)
150            }
151        }
152    }
153}
154
155//////////////////////////////////////////////////////////
156/// 为 ConnAckVariableHeader 实现 VariableDecoder trait
157/////////////////////////////////////////////////////////
158impl VariableDecoder for ConnAckVariableHeader {
159    type Item = ConnAckVariableHeader;
160
161    fn decode(bytes: &mut Bytes, _qos: Option<QoS>) -> Result<Self::Item, ProtoError> {
162        let b1 = bytes.get_u8();
163        if b1 == 0 {
164            let b2 = bytes.get_u8();
165            let con_ack_type = match b2 {
166                0b0000_0000 => ConnAckType::Success,
167                0b0000_0001 => ConnAckType::ProtoVersionError,
168                0b0000_0010 => ConnAckType::IdentifierRejected,
169                0b0000_0011 => ConnAckType::ServiceUnavailable,
170                0b0000_0100 => ConnAckType::BadUsernameOrPassword,
171                0b0000_0101 => ConnAckType::NotAuthentication,
172                _ => {
173                    return Err(ProtoError::NotKnow);
174                }
175            };
176            Ok(ConnAckVariableHeader::new(con_ack_type))
177        } else {
178            Err(ProtoError::NotKnow)
179        }
180    }
181}
182
183#[cfg(test)]
184mod tests {
185    use bytes::BytesMut;
186
187    use crate::v4::{builder::MqttMessageBuilder, Decoder, Encoder};
188
189    use super::ConnAck;
190
191    #[test]
192    fn encode_and_decode_for_connack_should_be_work() {
193        let resp = MqttMessageBuilder::conn_ack()
194            .conn_ack_type(super::ConnAckType::NotAuthentication)
195            .build();
196        println!("conn_ack: {:?}", resp);
197        let mut buffer = BytesMut::new();
198        let _count = resp.encode(&mut buffer);
199        let conn_ack = ConnAck::decode(buffer.freeze()).unwrap();
200        println!("conn_ack: {:?}", conn_ack);
201    }
202}