# MQTT : Packets
## Structure
- All packets have a *Fixed Header*.
- Some packets have a *Variable Header*.
- Some packets have a *Payload*.
### Fixed Header
- *Packet Type* (1..14)
- *Packet Length* (<= 256MB) (not including Fixed Header)
- In PUBLISH packets only -> a set of flags
### Variable Header
Varies by packet type and instance.
- *Packet ID* — Used in all Pub/Sub/Unsub packets (except PUBLISH w/QoS=0) to correlate replies.
- Arbitrary two-byte value that must NOT currently be in use.
- When re-sending the same packet, you must use the same Packet ID.
- Once the Client has processed the corresponding acknowledgement packet(s), that ID is freed and can be re-used.
- Same for Broker in the opposite direction.
- It's possible for a Client to send a PUBLISH Packet with Packet ID 0x1234 and then receive a different PUBLISH with Packet ID 0x1234 from the Broker before it receives a PUBACK for the PUBLISH that it sent. Each direction uses a different ID namespace.
### Payload
Packet Types with Payloads:
- CONNECT — connection information
- PUBLISH — aka "Application Message" (optional - can have zero-byte payloads)
- SUBSCRIBE — list of topics + requested QoS
- SUBACK — list of topics + granted QoS
- UNSUBSCRIBE — list of topics w/unsub results
## Packet Types
```
1 CONNECT -> Client request to connect to Server
2 CONNACK <- Connect acknowledgment
3 PUBLISH <-> Publish message
4 PUBACK <-> Publish acknowledgment
5 PUBREC <-> Publish received (assured delivery part 1)
6 PUBREL <-> Publish release (assured delivery part 2)
7 PUBCOMP <-> Publish complete (assured delivery part 3)
8 SUBSCRIBE -> Client subscribe request
9 SUBACK <- Subscribe acknowledgment
10 UNSUBSCRIBE -> Unsubscribe request
11 UNSUBACK <- Unsubscribe acknowledgment
12 PINGREQ -> PING request
13 PINGRESP <- PING response
14 DISCONNECT -> Client is disconnecting
```
## Packet Details
#### CONNECT
**Variable Header**
- *Protocol Name* -> always "MQTT"
- *Protocol Level*
- 4 -> v3.1.1
- 5 -> v5.0
- Connect Flags
- *User Name* -> whether *User Name* is present in the Payload
- *Password* -> whether *Password* is present in the Payload (if so, must also include User Name)
- *Will* -> whether *Will Topic* + *Will Message* are present in the Payload
- *Will Retain* -> whether the Will is a Retained Message
- *Will QoS* -> the publish QoS of the Will message
- *Keep-Alive* -> two-byte integer value, expressed in seconds (max: 65535 / 18h12m15s)
- It's the Client's responsibility to ensure that the interval between Packets does not exceed the Keep-Alive value.
- Client can use PINGREQ to keep connection alive.
**Payload**
- Client ID -> required; unique; 1 <= length <= 23; valid chars: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
- If another Client with same ID is currently connected, they will be disconnected.
- *Will Topic*
- *Will Message*
- *User Name*
- *Password*
Clients need not wait for a CONNACK Packet to send more Packets.
#### CONNACK
**Variable Header**
- Flags:
- *SP* (Session Present) -> whether an existing Session was found and resumed
- *Return Code*:
- 0 -> accepted
- 1..5 -> various rejection reasons
#### PUBLISH
**Fixed Header**
- *DUP* -> 0 if first time sending, 1 if re-sending
- Even if sent multiple times to Broker, DUP will be set to 0 when Broker publishes to subscribing Clients.
- *QoS* -> 0..2 (for that hop, only — QoS used to publish to Broker has nothing to do with QoS used by Broker to publish to Client, which is negotiated during subscription)
- *RETAIN* -> 1 for Retained Message
- Set on Packet sent to Broker to make it the new Retained Message on that Topic.
- Set on Packet sent from Broker when receiving a Retained Messages as a result of subscribing to that Topic.
- To un-retain a message in a Topic, send a new Retained Message with no Payload.
**Variable Header**
- *Topic Name*
- *Packet ID* (if QoS > 0)
**Payload**
- zero or more arbitrary bytes (Application Message)
#### PUBACK, PUBREC, PUBREL, PUBCOMP
**Variable Header**
- *Packet ID* -> the PUBLISH packet's ID
#### SUBSCRIBE
**Variable Header**
- *Packet ID*
**Payload**
- list of Topic Filters w/Requested QoS
> [!NOTE]
> If an identical Subscription exists, it will be replaced, and Retained Messages will be re-sent.
#### SUBACK
**Variable Header**
- *Packet ID* -> the SUBSCRIBE packet's ID
**Payload**
- list of return codes in same order as list of Topic Filters in SUBSCRIBE packet
- 0..2 -> granted QoS
- 128 -> Subscription failed
#### UNSUBSCRIBE
**Variable Header**
- *Packet ID*
**Payload**
- list of Topic Filters (must exactly match Topic Filters used to subscribe)
After unsubscribing, Broker...
- MUST stop adding any new messages for delivery to the Client
- MUST complete the delivery of any QoS 1 or QoS 2 messages which it has started to send to the Client
- MAY continue to deliver any existing messages buffered for delivery to the Client
#### UNSUBACK
**Variable Header**
- *Packet ID* -> the UNSUBSCRIBE packet's ID
#### PINGREQ, PINGRESP, DISCONNECT
No Variable Header or Payload.