2 MQTT Control Packet format
2.1 Structure of an MQTT Control Packet
The MQTT protocol works by exchanging a series of MQTT Control Packets in a defined way. This section describes the format of these packets.
An MQTT Control Packet consists of up to three parts, always in the following order as illustrated in Figure 2.1 - Structure of an MQTT Control Packet.
Figure 2.1 – Structure of an MQTT Control Packet
Fixed header, present in all MQTT Control Packets |
Variable header, present in some MQTT Control Packets |
Payload, present in some MQTT Control Packets |
2.2 Fixed header
Each MQTT Control Packet contains a fixed header. Figure 2.2 - Fixed header format illustrates the fixed header format.
Figure 2.2 - Fixed header format
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type |
Flags specific to each MQTT Control Packet type |
||||||
byte 2… |
Remaining Length |
2.2.1 MQTT Control Packet type
Represented as a 4-bit unsigned value, the values are listed in Table 2.1 - Control packet types.
Table 2.1 - Control packet types
Name |
Value |
Direction of flow |
Description |
Reserved |
0 |
Forbidden |
Reserved |
CONNECT |
1 |
Client to Server |
Client request to connect to Server |
CONNACK |
2 |
Server to Client |
Connect acknowledgment |
PUBLISH |
3 |
Client to Server or Server to Client |
Publish message |
PUBACK |
4 |
Client to Server or Server to Client |
Publish acknowledgment |
PUBREC |
5 |
Client to Server or Server to Client |
Publish received (assured delivery part 1) |
PUBREL |
6 |
Client to Server or Server to Client |
Publish release (assured delivery part 2) |
PUBCOMP |
7 |
Client to Server or Server to Client |
Publish complete (assured delivery part 3) |
SUBSCRIBE |
8 |
Client to Server |
Client subscribe request |
SUBACK |
9 |
Server to Client |
Subscribe acknowledgment |
UNSUBSCRIBE |
10 |
Client to Server |
Unsubscribe request |
UNSUBACK |
11 |
Server to Client |
Unsubscribe acknowledgment |
PINGREQ |
12 |
Client to Server |
PING request |
PINGRESP |
13 |
Server to Client |
PING response |
DISCONNECT |
14 |
Client to Server |
Client is disconnecting |
Reserved |
15 |
Forbidden |
Reserved |
2.2 Flags
The remaining bits [3-0] of byte 1 in the fixed header contain flags specific to each MQTT Control Packet type as listed in the Table 2.2 - Flag Bits below. Where a flag bit is marked as “Reserved” in Table 2.2 - Flag Bits, it is reserved for future use and MUST be set to the value listed in that table[MQTT-2.2.2-1]. If invalid flags are received, the receiver MUST close the Network Connection [MQTT-2.2.2-2].See Section 4.8 Handling errors for details about handling errors.
Table 2.2 - Flag Bits
Control Packet |
Fixed header flags |
Bit 3 |
Bit 2 |
Bit 1 |
Bit 0 |
CONNECT |
Reserved |
0 |
0 |
0 |
0 |
CONNACK |
Reserved |
0 |
0 |
0 |
0 |
PUBLISH |
Used in MQTT 3.1.1 |
DUP1 |
QoS2 |
QoS2 |
RETAIN3 |
PUBACK |
Reserved |
0 |
0 |
0 |
0 |
PUBREC |
Reserved |
0 |
0 |
0 |
0 |
PUBREL |
Reserved |
0 |
0 |
1 |
0 |
PUBCOMP |
Reserved |
0 |
0 |
0 |
0 |
SUBSCRIBE |
Reserved |
0 |
0 |
1 |
0 |
SUBACK |
Reserved |
0 |
0 |
0 |
0 |
UNSUBSCRIBE |
Reserved |
0 |
0 |
1 |
0 |
UNSUBACK |
Reserved |
0 |
0 |
0 |
0 |
PINGREQ |
Reserved |
0 |
0 |
0 |
0 |
PINGRESP |
Reserved |
0 |
0 |
0 |
0 |
DISCONNECT |
Reserved |
0 |
0 |
0 |
0 |
DUP1 = Duplicate delivery of a PUBLISH Control Packet
QoS2 = PUBLISH Quality of Service
RETAIN3 = PUBLISH Retain flag
See Section 3.3.1 Fixed header for a description of the DUP, QoS, and RETAIN flags in the PUBLISH Control Packet.
2.2.3 Remaining Length
Position: starts at byte 2.
The Remaining Length is the number of bytes remaining within the current packet, including data in the variable header and the payload. The Remaining Length does not include the bytes used to encode the Remaining Length.
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 a "continuation bit". The maximum number of bytes in the Remaining Length field is four.
Non normative comment
For example, the number 64 decimal is encoded as a single byte, decimal value 64, hexadecimal 0x40. The number 321 decimal (= 65 + 2*128) is encoded as two bytes, least significant first. The first byte is 65+128 = 193. Note that the top bit is set to indicate at least one following byte. The second byte is 2.
Non normative comment
This allows applications to send Control Packets of size up to 268,435,455 (256 MB). The representation of this number on the wire is: 0xFF, 0xFF, 0xFF, 0x7F.
Solace Implementation Note
Solace has limits to the size of a message, depending on the message QoS and the type of event broker.
Table 2.4 shows the Remaining Length values represented by increasing numbers of bytes.
Table 2.4 Size of Remaining Length field
Digits |
From |
To |
1 |
0 (0x00) |
127 (0x7F) |
2 |
128 (0x80, 0x01) |
16 383 (0xFF, 0x7F) |
3 |
16 384 (0x80, 0x80, 0x01) |
2 097 151 (0xFF, 0xFF, 0x7F) |
4 |
2 097 152 (0x80, 0x80, 0x80, 0x01) |
268 435 455 (0xFF, 0xFF, 0xFF, 0x7F) |
Non normative comment
The algorithm for encoding a non negative integer (X) into the variable length encoding scheme is as follows:
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 )
Where MOD is the modulo operator (% in C), DIV is integer division (/ in C), and OR is bit-wise or (| in C).
Non normative comment
The algorithm for decoding the Remaining Length field is as follows:
multiplier = 1
value = 0
do
encodedByte = 'next byte from stream'
value += ( encodedByte AND 127) * multiplier
multiplier *= 128
if (multiplier > 128*128*128)
throw Error(Malformed Remaining Length)
while (( encodedByte AND 128) != 0)
where AND is the bit-wise and operator (& in C).
When this algorithm terminates, value contains the Remaining Length value.
2.3 Variable header
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.3.1 Packet Identifier
Figure 2.3 - Packet Identifier bytes
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
Packet Identifier MSB |
|||||||
byte 2 |
Packet Identifier LSB |
The variable header component of many of the Control Packet types includes a 2 byte Packet Identifier field. These Control Packets are PUBLISH (where QoS > 0), PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK.
SUBSCRIBE, UNSUBSCRIBE, and PUBLISH (in cases where QoS > 0) Control Packets MUST contain a non-zero 16-bit Packet Id entifier [MQTT-2.3.1-1]. Each time a Client sends a new packet of one of these types it MUST assign it a currently unused Packet Identifier [MQTT-2.3.1-2]. If a Client re-sends a particular Control Packet, then it MUST use the same Packet Identifier in subsequent re-sends of that packet. The Packet Identifier becomes available for reuse after the Client has processed the corresponding acknowledgement packet. In the case of a QoS 1 PUBLISH this is the corresponding PUBACK; in the case of QoS 2 it is PUBCOMP. For SUBSCRIBE or UNSUBSCRIBE it is the corresponding SUBACK or UNSUBACK [MQTT-2.3.1-3]. The same conditions apply to a Server when it sends a PUBLISH with QoS > 0 [MQTT-2.3.1-4].
A PUBLISH Packet MUST NOT contain a Packet Identifier if its QoS value is set to 0[MQTT-2.3.1-5].
A PUBACK, PUBREC or PUBREL Packet MUST contain the same Packet Identifier as the PUBLISH Packet that was originally sent [MQTT-2.3.1-6]. Similarly SUBACK and UNSUBACK MUST contain the Packet Id entifier that was used in the corresponding SUBSCRIBE and UNSUBSCRIBE Packet respectively [MQTT-2.3>.1-7].
Control Packets that require a Packet Identifier are listed in Table 2.5 - Control Packets that contain a Packet Identifier.
Table 2.5 - Control Packets that contain a Packet Identifier
Control Packet |
Packet Identifier field |
CONNECT |
NO |
CONNACK |
NO |
PUBLISH |
YES (If QoS > 0) |
PUBACK |
YES |
PUBREC |
YES |
PUBREL |
YES |
PUBCOMP |
YES |
SUBSCRIBE |
YES |
SUBACK |
YES |
UNSUBSCRIBE |
YES |
UNSUBACK |
YES |
PINGREQ |
NO |
PINGRESP |
NO |
DISCONNECT |
NO |
The Client and Server assign Packet Identifiers independently of each other. As a result, Client Server pairs can participate in concurrent message exchanges using the same Packet Identifiers.
Non normative comment
It is possible for a Client to send a PUBLISH Packet with Packet Identifier 0x1234 and then receive a different PUBLISH with Packet Identifier 0x1234 from its Server before it receives a PUBACK for the PUBLISH that it sent.
Client Server
PUBLISH Packet Identifier=0x1234---à
ß--PUBLISH Packet Identifier=0x1234
PUBACK Packet Identifier=0x1234---à
ß--PUBACK Packet Identifier=0x1234
2.4 Payload
Table 2.6 - Control Packets that contain a Payload
Some MQTT Control Packets contain a payload as the final part of the packet, as described in Chapter 3 MQTT Control Packets. In the case of the PUBLISH packet this is the Application Message. Table 2.6 - Control Packets that contain a Payload lists the Control Packets that require a Payload.
Table 2.6 - Control Packets that contain a Payload
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 |