ntex_mqtt/v5/codec/packet/
disconnect.rs1use ntex_bytes::{Buf, BufMut, ByteString, Bytes, BytesMut};
2
3use crate::error::{DecodeError, EncodeError};
4use crate::utils::{self, Decode, Property};
5use crate::v5::codec::{UserProperties, UserProperty, encode::*, property_type as pt};
6
7#[derive(Debug, PartialEq, Eq, Clone)]
9pub struct Disconnect {
10 pub reason_code: DisconnectReasonCode,
11 pub session_expiry_interval_secs: Option<u32>,
12 pub server_reference: Option<ByteString>,
13 pub reason_string: Option<ByteString>,
14 pub user_properties: UserProperties,
15}
16
17prim_enum! {
18 pub enum DisconnectReasonCode {
20 NormalDisconnection = 0,
21 DisconnectWithWillMessage = 4,
22 UnspecifiedError = 128,
23 MalformedPacket = 129,
24 ProtocolError = 130,
25 ImplementationSpecificError = 131,
26 NotAuthorized = 135,
27 ServerBusy = 137,
28 ServerShuttingDown = 139,
29 BadAuthenticationMethod = 140,
30 KeepAliveTimeout = 141,
31 SessionTakenOver = 142,
32 TopicFilterInvalid = 143,
33 TopicNameInvalid = 144,
34 ReceiveMaximumExceeded = 147,
35 TopicAliasInvalid = 148,
36 PacketTooLarge = 149,
37 MessageRateTooHigh = 150,
38 QuotaExceeded = 151,
39 AdministrativeAction = 152,
40 PayloadFormatInvalid = 153,
41 RetainNotSupported = 154,
42 QosNotSupported = 155,
43 UseAnotherServer = 156,
44 ServerMoved = 157,
45 SharedSubscriptionNotSupported = 158,
46 ConnectionRateExceeded = 159,
47 MaximumConnectTime = 160,
48 SubscriptionIdentifiersNotSupported = 161,
49 WildcardSubscriptionsNotSupported = 162
50 }
51}
52
53impl Disconnect {
54 pub fn new(reason_code: DisconnectReasonCode) -> Self {
56 Self {
57 reason_code,
58 session_expiry_interval_secs: None,
59 server_reference: None,
60 reason_string: None,
61 user_properties: Vec::new(),
62 }
63 }
64
65 pub(crate) fn decode(src: &mut Bytes) -> Result<Self, DecodeError> {
66 let disconnect = if src.has_remaining() {
67 let reason_code = src.get_u8().try_into()?;
68
69 if src.has_remaining() {
70 let mut session_exp_secs = None;
71 let mut server_reference = None;
72 let mut reason_string = None;
73 let mut user_properties = Vec::new();
74
75 let prop_src = &mut utils::take_properties(src)?;
76 while prop_src.has_remaining() {
77 match prop_src.get_u8() {
78 pt::SESS_EXPIRY_INT => session_exp_secs.read_value(prop_src)?,
79 pt::REASON_STRING => reason_string.read_value(prop_src)?,
80 pt::USER => user_properties.push(UserProperty::decode(prop_src)?),
81 pt::SERVER_REF => server_reference.read_value(prop_src)?,
82 _ => return Err(DecodeError::MalformedPacket),
83 }
84 }
85 ensure!(!src.has_remaining(), DecodeError::InvalidLength);
86
87 Self {
88 reason_code,
89 session_expiry_interval_secs: session_exp_secs,
90 server_reference,
91 reason_string,
92 user_properties,
93 }
94 } else {
95 Self { reason_code, ..Default::default() }
96 }
97 } else {
98 Self::default()
99 };
100 Ok(disconnect)
101 }
102}
103
104impl Default for Disconnect {
105 fn default() -> Self {
106 Self {
107 reason_code: DisconnectReasonCode::NormalDisconnection,
108 session_expiry_interval_secs: None,
109 server_reference: None,
110 reason_string: None,
111 user_properties: Vec::new(),
112 }
113 }
114}
115
116impl EncodeLtd for Disconnect {
117 fn encoded_size(&self, limit: u32) -> usize {
118 const HEADER_LEN: usize = 1; let mut prop_len = encoded_property_size(&self.session_expiry_interval_secs)
121 + encoded_property_size(&self.server_reference);
122 let diag_len = encoded_size_opt_props(
123 &self.user_properties,
124 &self.reason_string,
125 reduce_limit(limit, prop_len + HEADER_LEN + 4),
126 ); prop_len += diag_len;
128 HEADER_LEN + var_int_len(prop_len) as usize + prop_len
129 }
130
131 fn encode(&self, buf: &mut BytesMut, size: u32) -> Result<(), EncodeError> {
132 let start_len = buf.len();
133 buf.put_u8(self.reason_code.into());
134
135 let prop_len = var_int_len_from_size(size - 1);
136 utils::write_variable_length(prop_len, buf);
137 encode_property(&self.session_expiry_interval_secs, pt::SESS_EXPIRY_INT, buf)?;
138 encode_property(&self.server_reference, pt::SERVER_REF, buf)?;
139 encode_opt_props(
140 &self.user_properties,
141 &self.reason_string,
142 buf,
143 size - (buf.len() - start_len) as u32,
144 )
145 }
146}