mqtt_codec/
packet.rs

1use bytes::Bytes;
2use bytestring::ByteString;
3
4use crate::proto::{Protocol, QoS};
5
6#[repr(u8)]
7#[derive(Debug, Eq, PartialEq, Copy, Clone)]
8/// Connect Return Code
9pub enum ConnectCode {
10    /// Connection accepted
11    ConnectionAccepted = 0,
12    /// Connection Refused, unacceptable protocol version
13    UnacceptableProtocolVersion = 1,
14    /// Connection Refused, identifier rejected
15    IdentifierRejected = 2,
16    /// Connection Refused, Server unavailable
17    ServiceUnavailable = 3,
18    /// Connection Refused, bad user name or password
19    BadUserNameOrPassword = 4,
20    /// Connection Refused, not authorized
21    NotAuthorized = 5,
22    /// Reserved
23    Reserved = 6,
24}
25
26const_enum!(ConnectCode: u8);
27
28impl ConnectCode {
29    pub fn reason(self) -> &'static str {
30        match self {
31            ConnectCode::ConnectionAccepted => "Connection Accepted",
32            ConnectCode::UnacceptableProtocolVersion => {
33                "Connection Refused, unacceptable protocol version"
34            }
35            ConnectCode::IdentifierRejected => "Connection Refused, identifier rejected",
36            ConnectCode::ServiceUnavailable => "Connection Refused, Server unavailable",
37            ConnectCode::BadUserNameOrPassword => {
38                "Connection Refused, bad user name or password"
39            }
40            ConnectCode::NotAuthorized => "Connection Refused, not authorized",
41            _ => "Connection Refused",
42        }
43    }
44}
45
46#[derive(Debug, PartialEq, Clone)]
47/// Connection Will
48pub struct LastWill {
49    /// the QoS level to be used when publishing the Will Message.
50    pub qos: QoS,
51    /// the Will Message is to be Retained when it is published.
52    pub retain: bool,
53    /// the Will Topic
54    pub topic: ByteString,
55    /// defines the Application Message that is to be published to the Will Topic
56    pub message: Bytes,
57}
58
59#[derive(Debug, PartialEq, Clone)]
60/// Connect packet content
61pub struct Connect {
62    /// mqtt protocol version
63    pub protocol: Protocol,
64    /// the handling of the Session state.
65    pub clean_session: bool,
66    /// a time interval measured in seconds.
67    pub keep_alive: u16,
68    /// Will Message be stored on the Server and associated with the Network Connection.
69    pub last_will: Option<LastWill>,
70    /// identifies the Client to the Server.
71    pub client_id: ByteString,
72    /// username can be used by the Server for authentication and authorization.
73    pub username: Option<ByteString>,
74    /// password can be used by the Server for authentication and authorization.
75    pub password: Option<Bytes>,
76}
77
78#[derive(Debug, PartialEq, Clone)]
79/// Publish message
80pub struct Publish {
81    /// this might be re-delivery of an earlier attempt to send the Packet.
82    pub dup: bool,
83    pub retain: bool,
84    /// the level of assurance for delivery of an Application Message.
85    pub qos: QoS,
86    /// the information channel to which payload data is published.
87    pub topic: ByteString,
88    /// only present in PUBLISH Packets where the QoS level is 1 or 2.
89    pub packet_id: Option<u16>,
90    /// the Application Message that is being published.
91    pub payload: Bytes,
92}
93
94#[derive(Debug, PartialEq, Copy, Clone)]
95/// Subscribe Return Code
96pub enum SubscribeReturnCode {
97    Success(QoS),
98    Failure,
99}
100
101#[derive(Debug, PartialEq, Clone)]
102/// MQTT Control Packets
103pub enum Packet {
104    /// Client request to connect to Server
105    Connect(Connect),
106
107    /// Connect acknowledgment
108    ConnectAck {
109        /// enables a Client to establish whether the Client and Server have a consistent view
110        /// about whether there is already stored Session state.
111        session_present: bool,
112        return_code: ConnectCode,
113    },
114
115    /// Publish message
116    Publish(Publish),
117
118    /// Publish acknowledgment
119    PublishAck {
120        /// Packet Identifier
121        packet_id: u16,
122    },
123    /// Publish received (assured delivery part 1)
124    PublishReceived {
125        /// Packet Identifier
126        packet_id: u16,
127    },
128    /// Publish release (assured delivery part 2)
129    PublishRelease {
130        /// Packet Identifier
131        packet_id: u16,
132    },
133    /// Publish complete (assured delivery part 3)
134    PublishComplete {
135        /// Packet Identifier
136        packet_id: u16,
137    },
138
139    /// Client subscribe request
140    Subscribe {
141        /// Packet Identifier
142        packet_id: u16,
143        /// the list of Topic Filters and QoS to which the Client wants to subscribe.
144        topic_filters: Vec<(ByteString, QoS)>,
145    },
146    /// Subscribe acknowledgment
147    SubscribeAck {
148        packet_id: u16,
149        /// corresponds to a Topic Filter in the SUBSCRIBE Packet being acknowledged.
150        status: Vec<SubscribeReturnCode>,
151    },
152
153    /// Unsubscribe request
154    Unsubscribe {
155        /// Packet Identifier
156        packet_id: u16,
157        /// the list of Topic Filters that the Client wishes to unsubscribe from.
158        topic_filters: Vec<ByteString>,
159    },
160    /// Unsubscribe acknowledgment
161    UnsubscribeAck {
162        /// Packet Identifier
163        packet_id: u16,
164    },
165
166    /// PING request
167    PingRequest,
168    /// PING response
169    PingResponse,
170
171    /// Client is disconnecting
172    Disconnect,
173}
174
175impl Packet {
176    #[inline]
177    /// MQTT Control Packet type
178    pub fn packet_type(&self) -> u8 {
179        match *self {
180            Packet::Connect { .. } => CONNECT,
181            Packet::ConnectAck { .. } => CONNACK,
182            Packet::Publish { .. } => PUBLISH,
183            Packet::PublishAck { .. } => PUBACK,
184            Packet::PublishReceived { .. } => PUBREC,
185            Packet::PublishRelease { .. } => PUBREL,
186            Packet::PublishComplete { .. } => PUBCOMP,
187            Packet::Subscribe { .. } => SUBSCRIBE,
188            Packet::SubscribeAck { .. } => SUBACK,
189            Packet::Unsubscribe { .. } => UNSUBSCRIBE,
190            Packet::UnsubscribeAck { .. } => UNSUBACK,
191            Packet::PingRequest => PINGREQ,
192            Packet::PingResponse => PINGRESP,
193            Packet::Disconnect => DISCONNECT,
194        }
195    }
196
197    /// Flags specific to each MQTT Control Packet type
198    pub fn packet_flags(&self) -> u8 {
199        match *self {
200            Packet::Publish(Publish {
201                dup, qos, retain, ..
202            }) => {
203                let mut b = qos.into();
204
205                b <<= 1;
206
207                if dup {
208                    b |= 0b1000;
209                }
210
211                if retain {
212                    b |= 0b0001;
213                }
214
215                b
216            }
217            Packet::PublishRelease { .. }
218            | Packet::Subscribe { .. }
219            | Packet::Unsubscribe { .. } => 0b0010,
220            _ => 0,
221        }
222    }
223}
224
225impl From<Connect> for Packet {
226    fn from(val: Connect) -> Packet {
227        Packet::Connect(val)
228    }
229}
230
231impl From<Publish> for Packet {
232    fn from(val: Publish) -> Packet {
233        Packet::Publish(val)
234    }
235}
236
237pub const CONNECT: u8 = 1;
238pub const CONNACK: u8 = 2;
239pub const PUBLISH: u8 = 3;
240pub const PUBACK: u8 = 4;
241pub const PUBREC: u8 = 5;
242pub const PUBREL: u8 = 6;
243pub const PUBCOMP: u8 = 7;
244pub const SUBSCRIBE: u8 = 8;
245pub const SUBACK: u8 = 9;
246pub const UNSUBSCRIBE: u8 = 10;
247pub const UNSUBACK: u8 = 11;
248pub const PINGREQ: u8 = 12;
249pub const PINGRESP: u8 = 13;
250pub const DISCONNECT: u8 = 14;