ntex_mqtt/v5/codec/packet/
auth.rs

1use 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/// AUTH message
8#[derive(Debug, PartialEq, Eq, Clone)]
9pub struct Auth {
10    pub reason_code: AuthReasonCode,
11    pub auth_method: Option<ByteString>,
12    pub auth_data: Option<Bytes>,
13    pub reason_string: Option<ByteString>,
14    pub user_properties: UserProperties,
15}
16
17prim_enum! {
18    /// AUTH reason codes
19    pub enum AuthReasonCode {
20        Success = 0,
21        ContinueAuth = 24,
22        ReAuth = 25
23    }
24}
25
26impl Auth {
27    pub(crate) fn decode(src: &mut Bytes) -> Result<Self, DecodeError> {
28        let auth = if src.has_remaining() {
29            let reason_code = src.get_u8().try_into()?;
30
31            if src.has_remaining() {
32                let mut auth_method = None;
33                let mut auth_data = None;
34                let mut reason_string = None;
35                let mut user_properties = Vec::new();
36
37                if reason_code != AuthReasonCode::Success || src.has_remaining() {
38                    let prop_src = &mut utils::take_properties(src)?;
39                    while prop_src.has_remaining() {
40                        match prop_src.get_u8() {
41                            pt::AUTH_METHOD => auth_method.read_value(prop_src)?,
42                            pt::AUTH_DATA => auth_data.read_value(prop_src)?,
43                            pt::REASON_STRING => reason_string.read_value(prop_src)?,
44                            pt::USER => user_properties.push(UserProperty::decode(prop_src)?),
45                            _ => return Err(DecodeError::MalformedPacket),
46                        }
47                    }
48                    ensure!(!src.has_remaining(), DecodeError::InvalidLength);
49                }
50
51                Self { reason_code, auth_method, auth_data, reason_string, user_properties }
52            } else {
53                Self { reason_code, ..Default::default() }
54            }
55        } else {
56            Self::default()
57        };
58        Ok(auth)
59    }
60}
61
62impl Default for Auth {
63    fn default() -> Self {
64        Self {
65            reason_code: AuthReasonCode::Success,
66            auth_method: None,
67            auth_data: None,
68            reason_string: None,
69            user_properties: Vec::new(),
70        }
71    }
72}
73
74impl EncodeLtd for Auth {
75    fn encoded_size(&self, limit: u32) -> usize {
76        const HEADER_LEN: usize = 1; // reason code
77
78        let mut prop_len =
79            encoded_property_size(&self.auth_method) + encoded_property_size(&self.auth_data);
80        let diag_len = encoded_size_opt_props(
81            &self.user_properties,
82            &self.reason_string,
83            reduce_limit(limit, prop_len + HEADER_LEN + 4),
84        ); // exclude other props and max of 4 bytes for property length value
85        prop_len += diag_len;
86        HEADER_LEN + var_int_len(prop_len) as usize + prop_len
87    }
88
89    fn encode(&self, buf: &mut BytesMut, size: u32) -> Result<(), EncodeError> {
90        let start_len = buf.len();
91        buf.put_u8(self.reason_code.into());
92
93        let prop_len = var_int_len_from_size(size - 1);
94        utils::write_variable_length(prop_len, buf);
95        encode_property(&self.auth_method, pt::AUTH_METHOD, buf)?;
96        encode_property(&self.auth_data, pt::AUTH_DATA, buf)?;
97        encode_opt_props(
98            &self.user_properties,
99            &self.reason_string,
100            buf,
101            size - (buf.len() - start_len) as u32,
102        )
103    }
104}