# RustMqtt Mqtt encoder and decoder for pure rust. ## Notes 1) The byte order for `mqtt` packets is `Big-Endian`, means all the bytes will be arranged at `MSB` -> `LSB`. 2) Strings/Text values are `UTF-8`, the format is `2-byte`+`n-bytes`, where first `2-byte` are length of the string and another `n-bytes` is the actual textual data. Max length of text field is `65535` bytes. ## Control Packets All the `MQtt` control packets consists of 3 parts. 1) `Fixed header`, present in all MQTT Control Packets. 2) `Variable header`, present in some MQTT Control Packets. 3) `Payload`, present in some MQTT Control Packets. ### 1. Fixed Header 1) First byte in fixed header contains various settings as well as what type of packet this is. - `7th 6th 5th 4th`, these `4 bits` are the type of packet. - `3rd 2nd 1st 0th`, these `4 bits` are `packet specific`. mostly utilized for `publish` packet type. 2) Second on wards bytes contains the actual remaining length of the whole packet including variable header and payload if any. - The Remaining Length is encoded using a variable length encoding scheme which uses a single byte for values up to 127. Larger values are handled as follows. The least significant seven bits of each byte encode the data, and the most significant bit is used to indicate that there are following bytes in the representation. Thus each byte encodes 128 values and "continuation bit". The maximum number of bytes in the Remaining Length field is four. - ``` do encodedByte = X MOD 128 X = X DIV 128 // if there are more data to encode, set the top bit of this byte if ( X > 0 ) encodedByte = encodedByte OR 128 endif 'output' encodedByte while ( X > 0 ) ``` ### 2. Variable Header 1) Some types of MQTT Control Packets contain a variable header component. It resides between the fixed header and the payload. The content of the variable header varies depending on the Packet type. The Packet Identifier field of variable header is common in several packet types. 2) `Packet Identifier` - non-zero `2 bytes` longer. - These Control Packets are PUBLISH (where QoS > 0), PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK. ### 3. Payload 1) Some MQTT Control Packets contain a payload as the final part of the packet. 2) ``` Control Packet Payload CONNECT Required CONNACK None PUBLISH Optional PUBACK None PUBREC None PUBREL None PUBCOMP None SUBSCRIBE Required SUBACK Required UNSUBSCRIBE Required UNSUBACK None PINGREQ None PINGRESP None DISCONNECT None ``` ## MQTT Control Packets 1) CONNECT - `client` request for connection to `server`. - After network connection is established from client to server, the first packet to send from client side MUST be this. - `client` can only send 1 CONNECT packet per network connection. - `Fixed Header` - `7th 6th 5th 4th` -> `0 0 0 1` - `3rd 2nd 1st 0th` -> `0 0 0 0` - `Remaining Length` - `Variable Header` - `Protocol Name` - This is UTF-8 encoded string value. - Possible Values: `MQTT` for 3.1.1 - `Protocol Level` - `1 byte` containing the version of mqtt. - for latest, it is `4`. - `Connect Flags` - `1 byte` contains all the required connect flags. - `7th bit` -> `username` - `6th bit` -> `password` - `5th bit` -> `will retain` - `4th 3rd bits` -> `Will QoS` - `2nd bit` -> `Will Flag` - `1st bit` -> `Clean Session` - `0th bit` -> `Reserved` - `Keep alive` - `2 bytes` contains information about keep alive. - This is time value in `seconds`. - `Payload` - `Client ID` -> `UTF-8` encoded unique string. - `Will Topic` - if `will flag` is `1`. - UTF-8 encoded string. - `Will Message` - if `will flag` is `1`. - UTF-8 encoded string. - `Username` - if `username flag` is `1`. - UTF-8 encoded string. - `Password` - if `password flag` is `1`. - UTF-8 encoded string. 2) CONNACK - Acknowledge connection request - `Fixed Header` - is `0 0 1 0 0 0 0 0`. - `Remaining Length` - is `0 0 0 0 0 0 1 0`. - `Variable header` - `1st byte` is `0 0 0 0 0 0 0 SP`, where `SP` is `Session Present`. - `2nd byte` is `Return Code`. - ``` 0 0x00 Connection Accepted 1 0x01 Connection Refused, The Server does not support the level of the MQTT protocol requested by the Client 2 0x02 Connection Refused, identifier rejected The Client identifier is correct UTF-8 but not allowed by the Server 3 0x03 Connection Refused, Server unavailable 4 0x04 Connection Refused, bad user name or password 5 0x05 Connection Refused, not authorized 6 - 255 Reserved. ``` 3) PUBLISH - Packet is used when `client` wants to send data to `server`, or `server` wants to send data to `client`. - `Fixed Header 1st byte` - `7th 6th 5th 4th bits` -> `0 0 1 1`, This is the message type. - `3rd bit` -> `DUP Flag`, - if DUP = 0, this is first attempt to send message from client or server. if DUP = 1, then this might be re-attempt to send the message. - for QoS = 0, DUP will always be 0. - `2nd 1st buts` -> `Qos Level` - 0, 1, 2 values. - `1st bit` -> 'RETAIN Flag' - When this is 1, we will store this message and will publish to all new subscribers just after subscription is finished. - `Remaining Length 2nd.. bytes` - `Variable header` - `Topic Name` -> sort of key of the message that we are trying to publish, `UTF-8`. - `PacketID` -> `u16` packet id to id the message. - `Payload` - The type of data in payload is application specific. - If `Qos = 0` for `PUBLISH` packet, then there won't be any response from receiver to sender. 4) PUBACK - This packet is sent from receiver to sender when `Qos = 1` in `PUBLISH` packet. - `Fixed Header` - `0 1 0 0 0 0 0 0` - `Remaining Length` - `0 0 0 0 0 0 1 0` - `Variable Header` - `PacketId` -> 2 bytes - No Paylaod. 5) PUBREC - When `Qos=2` in `PUBLISH`, receiver will send `PUBREC` packet to sender. - `Fixed Header` - `0 1 0 1 0 0 0 0` - `Remaining Length` - `0 0 0 0 0 0 1 0` - `Variable header` - `PacketID` -> This is the packet id we received from publish packet. - no payload. 6) PUBREL - This is the response to `PUBREC` packet. sent from sender to receiver after sender receives `PUBREC` from receiver. - `Fixed Header` - `0 1 1 0 0 0 1 0` - `Remaing Length` - `0 0 0 0 0 0 1 0` - `Variable Header` - `PacketId` -> same packet id, which was received at the time of `PUBREC`. - no payload. 7) PUBCOMP - This is the response to `PUBREL` packet. sent from receiver to sender after receiver receives `PUBREL` from sender. - `Fixed Header` - `0 1 1 1 0 0 1 0` - `Remaing Length` - `0 0 0 0 0 0 1 0` - `Variable Header` - `PacketId` -> same packet id, which was received at the time of `PUBREL`. - no payload. 8) SUBSCRIBE - This packet is sent from `client` to `server` to create `subscription`. - Each subscription registers client's interest for one or more `topics`. - This is used when server wants to send `PUBLISH` packets to client. - `Subscribe` packet also describe `MAX QoS` with which server can send packets to client. - `Fixed Header` - `1 0 0 0 0 0 1 0` - `Remaining Length 2nd.. bytes` - `Variable Header` - `PacketID` -> unique u16 id to identify the packet. - `Payload` - List of `Topic Filters` plus `QoS`. Where topic filters must be UTF-8 encoded strings. 9) SUBACK - Sent from server to client to confirm the subscription for client on perticular topic filter. - This contains list of return codes, that spacifies the max QoS was granted in each subscription. - `Fixed Header` - `1 0 0 1 0 0 0 0` - `Remaining Length` - Length of variable header + payload. - `Variable Header` - Packet ID - `Payload` - The payload contains a list of return codes. Each return code corresponds to a Topic Filter in the SUBSCRIBE Packet being acknowledged. ``` Allowed return codes: 0x00 - Success - Maximum QoS 0 0x01 - Success - Maximum QoS 1 0x02 - Success - Maximum QoS 2 0x80 - Failure ``` 10) UNSUBSCRIBE - Sent from `client` to `server` to remove interest from one or more topics. - `Fixed Header` - `1 0 1 0 0 0 1 0` - `Remaining Length` - `Variable Header` - Packet ID - `Payload` - List of topic filters client want to unscribe to. - Topics must be UTF-8 encoded strings. 11) UNSUBACK - The UNSUBACK Packet is sent by the `Server` to the `Client` to confirm receipt of an UNSUBSCRIBE Packet. - `Fixed Header` - `1 0 1 1 0 0 0 0` - `Remaining Length` - `Variable Header` - Packet ID received from unsubscribe request. - No Payload. 12) PINGREQ - The PINGREQ Packet is sent from a Client to the Server. - Indicate to the Server that the Client is alive in the absence of any other Control Packets being sent from the Client to the Server. - Request that the Server responds to confirm that it is alive. - Exercise the network to indicate that the Network Connection is active. - `Fixed Header` - `1 1 0 0 0 0 0 0` - remaining length is 0. - Has no payload or variable headers. 13) PINGRESP - A PINGRESP Packet is sent by the Server to the Client in response to a PINGREQ Packet. That indicates that server is alive. - `Fixed Header` - `1 1 0 1 0 0 0 0` - remaining length is 0. - Has no payload or variable headers. 14) DISCONNECT - The DISCONNECT Packet is the final Control Packet sent from the Client to the Server. This indicates that client is disconnecting cleanly. - `Fixed Header` - `1 1 1 0 0 0 0 0` - remaining length is 0. - Has no payload or variable headers. - After sending this packet, client must close the network connection, and not send any more control packets. - server should close the client connection, if client failed to do so, and not accept any new packets from the client.