3 MQTT Control Packets
3.1 CONNECT – Client requests a connection to a Server
After a Network Connection is established by a Client to a Server, the first Packet sent from the Client to the Server MUST be a CONNECT Packet[MQTT-3.1.0-1].
A Client can only send the CONNECT Packet once over a Network Connection. The Server MUST process a second CONNECT Packet sent from a Client as a protocol violation and disconnect the Client[MQTT-3.1.0-2]. See section 4.8 Handling errors for information about handling errors.
The payload contains one or more encoded fields. They specify a unique Client identifier for the Client, a Will topic, Will Message, User Name and Password. All but the Client identifier are optional and their presence is determined based on flags in the variable header.
3.1.1 Fixed header
Figure 3.1 – CONNECT Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (1) |
Reserved |
||||||
|
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
byte 2… |
Remaining Length |
Remaining Length field
Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload. It is encoded in the manner described in section 2.2.3 Remaining Length.
3.1.2 Variable header
The variable header for the CONNECT Packet consists of four fields in the following order: Protocol Name, Protocol Level, Connect Flags, and Keep Alive.
3.1.2.1 Protocol Name
Figure 3.2 - Protocol Name bytes
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Protocol Name |
|||||||||
byte 1 |
Length MSB (0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 2 |
Length LSB (4) |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
byte 3 |
‘M’ |
0 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
byte 4 |
‘Q’ |
0 |
1 |
0 |
1 |
0 |
0 |
0 |
1 |
byte 5 |
‘T’ |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
byte 6 |
‘T’ |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
The Protocol Name is a UTF-8 encoded string that represents the protocol name “MQTT”, capitalized as shown. The string, its offset and length will not be changed by future versions of the MQTT specification.
If the protocol name is incorrect the Server MAY disconnect the Client, or it MAY continue processing the CONNECT packet in accordance with some other specification. In the latter case, the Server MUST NOT continue to process the CONNECT packet in line with this specification[MQTT-3.1.2-1].
Non normative comment
Packet inspectors, such as firewalls, could use the Protocol Name to identify MQTT traffic.
3.1.2.2 Protocol Level
Figure 3.3 - Protocol Level byte
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Protocol Level |
|||||||||
byte 7 |
Level(4) |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
The 8 bit unsigned value that represents the revision level of the protocol used by the Client. The value of the Protocol Level field for the version 3.1.1 of the protocol is 4 (0x04). The Server MUST respond to the CONNECT Packet with a CONNACK return code 0x01 (unacceptable protocol level) and then disconnect the Client if the Protocol Level is not supported by the Server[MQTT-3.1.2-2].
3.1.2.3 Connect Flags
The Connect Flags byte contains a number of parameters specifying the behavior of the MQTT connection. It also indicates the presence or absence of fields in the payload.
Figure 3.4 - Connect Flag bits
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
User Name Flag |
Password Flag |
Will Retain |
Will QoS |
Will Flag |
Clean Session |
Reserved |
|
byte 8 |
X |
X |
X |
X |
X |
X |
X |
0 |
The Server MUST validate that the reserved flag in the CONNECT Control Packet is set to zero and disconnect the Client if it is not zero[MQTT-3.1.2-].
3.1.2.4 Clean Session
Position: bit 1 of the Connect Flags byte.
Solace Implementation Note
When a connection with CleanSession set to 0 is disconnected:
- The Solace server continues to store any currently queued and newly arriving QoS 1 and QoS 2 messages that match QoS 1 subscriptions.
- The Solace server discards any currently queued QoS 0 messages and does not enqueue any QoS 0 messages that arrive after the session is disconnected.
If CleanSession is set to 1, the Client and Server MUST discard any previous Session and start a new one. This Session lasts as long as the Network Connection. State data associated with this Session MUST NOT be reused in any subsequent Session[MQTT-3.1.2-6].
The Session state in the Client consists of:
- QoS 1 and QoS 2 messages which have been sent to the Server, but have not been completely acknowledged.
- QoS 2 messages which have been received from the Server, but have not been completely acknowledged.
The Session state in the Server consists of:
- The existence of a Session, even if the rest of the Session state is empty.
- The Client’s subscriptions.
- QoS 1 and QoS 2 messages which have been sent to the Client, but have not been completely acknowledged.
- QoS 1 and QoS 2 messages pending transmission to the Client.
- QoS 2 messages which have been received from the Client, but have not been completely acknowledged.
- Optionally, QoS 0 messages pending transmission to the Client.
Solace Implementation Note
- When a connection is established with CleanSession set to 0, the Solace server stores all new subscriptions for all QoS classes even after the network connection disconnects.
- When a Session (last connected with CleanSession set to 0) has no active connection, QoS 0 subscriptions are stored in the Session but they are inactive and do not cause messages to be enqueued. QoS 0 subscriptions cause messages to be enqueued automatically to the connection when the Session is re-connected with CleanSession set to 0.
Retained messages do not form part of the Session state in the Server, they MUST NOT be deleted when the Session ends[MQTT-3.1.2.7].
See Section 4.1 Storing state for details and limitations of stored state.
When CleanSession is set to 1 the Client and Server need not process the deletion of state atomically.
Non normative comment
To ensure consistent state in the event of a failure, the Client should repeat its attempts to connect with CleanSession set to 1, until it connects successfully.
Non normative comment
Typically, a Client will always connect using CleanSession set to 0 or CleanSession set to 1 and not swap between the two values. The choice will depend on the application. A Client using CleanSession set to 1 will not receive old Application Messages and has to subscribe afresh to any topics that it is interested in each time it connects. A Client using CleanSession set to 0 will receive all QoS 1 or QoS 2 messages that were published while it was disconnected. Hence, to ensure that you do not lose messages while disconnected, use QoS 1 or QoS 2 with CleanSession set to 0.
Non normative comment
When a Client connects with CleanSession set to 0, it is requesting that the Server maintain its MQTT session state after it disconnects. Clients should only connect with CleanSession set to 0, if they intend to reconnect to the Server at some later point in time. When a Client has determined that it has no further use for the session it should do a final connect with CleanSession set to 1 and then disconnect.
3.1.2.5 Will Flag
Position: bit 2 of the Connect Flags.
If the Will Flag is set to 1 this indicates that, if the Connect request is accepted, a Will Message MUST be stored on the Server and associated with the Network Connection. The Will Message MUST be published when the Network Connection is subsequently closed unless the Will Message has been deleted by the Server on receipt of a DISCONNECT Packet [MQTT-3.1.2-8].
Situations in which the Will Message is published include, but are not limited to:
- An I/O error or network failure detected by the Server.
- The Client fails to communicate within the Keep Alive time.
- The Client closes the Network Connection without first sending a DISCONNECT Packet.
- The Server closes the Network Connection because of a protocol error.
If the Will Flag is set to 1, the Will QoS and Will Retain fields in the Connect Flags will be used by the Server, and the Will Topic and Will Message fields MUST be present in the payload[MQTT-3.1.2-9].
The Will Message MUST be removed from the stored Session state in the Server once it has been published or the Server has received a DISCONNECT packet from the Client[MQTT-3.1.2-10].
If the Will Flag is set to 0 the Will QoS and Will Retain fields in the Connect Flags MUST be set to zero and the Will Topic and Will Message fields MUST NOT be present in the payload[MQTT-3.1.2-11].
If the Will Flag is set to 0, a Will Message MUST NOT be published when this Network Connection ends[MQTT-3.1.2-12].
The Server SHOULD publish Will Messages promptly. In the case of a Server shutdown or failure the server MAY defer publication of Will Messages until a subsequent restart. If this happens there might be a delay between the time the server experienced failure and a Will Message being published.
Solace Implementation Note
The Solace server supports Will Flag set to 1 and associated procedures as described above. Will messages are limited to 1,600 bytes in size. If a CONNECT packet is received with a Will Message that exceeds this limit, then the connection is rejected and a log is raised.
The Solace server will not send Will messages under the following conditions:
- an administrative shutdown
- an event broker HA failover or restart
3.1.2.6 Will QoS
Position: bits 4 and 3 of the Connect Flags.
These two bits specify the QoS level to be used when publishing the Will Message.
If the Will Flag is set to 0, then the Will QoS MUST be set to 0 (0x00)[MQTT-3.1.2-13].
If the Will Flag is set to 1, the value of Will QoS can be 0 (0x00), 1 (0x01), or 2 (0x02). It MUST NOT be 3 (0x03) [MQTT-3.1.2-14].
3.1.2.7 Will Retain
Position: bit 5 of the Connect Flags.
This bit specifies if the Will Message is to be Retained when it is published.
If the Will Flag is set to 0, then the Will Retain Flag MUST be set to 0[MQTT-3.1.2-15].
If the Will Flag is set to 1:
- If Will Retain is set to 0, the Server MUST publish the Will Message as a non-retained message[MQTT-3.1.2-16].
- If Will Retain is set to 1, the Server MUST publish the Will Message as a retained message [MQTT-3>.1.2-17.
3.1.2.8 User Name Flag
Position: bit 7 of the Connect Flags.
If the User Name Flag is set to 0, a user name MUST NOT be present in the payload[MQTT-3.1.2-18].
If the User Name Flag is set to 1, a user name MUST be present in the payload[MQTT-3.1.2-19].
3.1.2.9 Password Flag
Position: bit 6 of the Connect Flags byte.
If the Password Flag is set to 1, a password MUST be present in the payload[MQTT-3.1.2-21].
If the User Name Flag is set to 0, the Password Flag MUST be set to 0[MQTT-3.1.2-22].
3.1.2.10 Keep Alive
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 9 |
Keep Alive MSB |
|||||||
byte 10 |
Keep Alive LSB |
The Keep Alive is a time interval measured in seconds. Expressed as a 16-bit word, it is the maximum time interval that is permitted to elapse between the point at which the Client finishes transmitting one Control Packet and the point it starts sending the next. It is the responsibility of the Client to ensure that the interval between Control Packets being sent does not exceed the Keep Alive value. In the absence of sending any other Control Packets, the Client MUST send a PINGREQ Packet[MQTT-3.1.2-23].
The Client can send PINGREQ at any time, irrespective of the Keep Alive value, and use the PINGRESP to determine that the network and the Server are working.
If the Keep Alive value is non-zero and the Server does not receive a Control Packet from the Client within one and a half times the Keep Alive time period, it MUST disconnect the Network Connection to the Client as if the network had failed[MQTT-3.1.2-24].
If a Client does not receive a PINGRESP Packet within a reasonable amount of time after it has sent a PINGREQ, it SHOULD close the Network Connection to the Server.
A Keep Alive value of zero (0) has the effect of turning off the keep alive mechanism. This means that, in
this case, the Server is not required to disconnect the Client on the grounds of inactivity.
Note that
a Server is permitted to disconnect a Client that it determines to be inactive or non-responsive at any
time, regardless of the Keep Alive value provided by that Client.
Non normative comment
The actual value of the Keep Alive is application specific; typically this is a few minutes. The maximum value is 18 hours 12 minutes and 15 seconds.
Solace Implementation Note
A Solace PubSub+ event broker administrator can configure a minimum keepalive timeout value for clients. In this case, the Keep Alive provided by the client may be ignored in favor of the value configured on the broker. This could result in a client being disconnected after a lengthy period of inactivity even if it requested to be disconnected more aggressively. For more information, see Configuring a Minimum Keepalive Timeout.
3.1.2.11 Variable header non normative example
Figure 3.6 - Variable header non normative example
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Protocol Name |
|||||||||
byte 1 |
Length MSB (0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 2 |
Length LSB (4) |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
byte 3 |
‘M’ |
0 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
byte 4 |
‘Q’ |
0 |
1 |
0 |
1 |
0 |
0 |
0 |
1 |
byte 5 |
‘T’ |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
byte 6 |
‘T’ |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
Protocol Level |
|||||||||
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 7 |
Level (4) |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
Connect Flags |
|||||||||
byte 8 |
User Name Flag (1) Password Flag (1) Will Retain (0) Will QoS (01) Will Flag (1) Clean Session (1) Reserved (0) |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
0 |
Keep Alive |
|||||||||
byte 9 |
Keep Alive MSB (0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 10 |
Keep Alive LSB (10) |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
3.1.3 Payload
The payload of the CONNECT Packet contains one or more length-prefixed fields, whose presence is determined by the flags in the variable header. These fields, if present, MUST appear in the order Client Identifier, Will Topic, Will Message, User Name, Password[MQTT-3.1.3-1].
3.1.3.1 Client Identifier
The Client Identifier (ClientId) identifies the Client to the Server. Each Client connecting to the Server has a unique ClientId. The ClientId MUST be used by Clients and by Servers to identify state that they hold relating to this MQTT Session between the Client and the Server[MQTT-3.1.3-2].
The Client Identifier (ClientId) MUST be present and MUST be the first field in the CONNECT packet payload[MQTT-3.1.3-3].
The ClientId MUST be a UTF-8 encoded string as defined in Section 1.5.3 UTF-8 encoded strings[MQTT-3.1.3-4].
The Server MUST allow ClientIds which are between 1 and 23 UTF-8 encoded bytes in
length, and that contain only the characters
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[MQTT-3.1.3-5].
The Server MAY allow ClientId’s that contain more than 23 encoded bytes. The Server MAY allow ClientId’s that
contain characters not included in the list given above.
A Server MAY allow a Client to supply a ClientId that has a length of zero bytes,
however if it does so the Server MUST treat this as a special case and assign a unique ClientId to that
Client. It MUST then process the CONNECT packet as if the Client had provided that unique
ClientId[MQTT-3.1.3-6].
If the Client supplies a zero-byte ClientId, the Client MUST also set CleanSession to
1[MQTT-3.1.3-7].
If the Client supplies a zero-byte ClientId with CleanSession set to 0, the Server MUST
respond to the CONNECT Packet with a CONNACK return code 0x02 (Identifier rejected) and then close the
Network Connection[MQTT-3.1.3-8].
If the Server rejects the ClientId it MUST respond to the CONNECT Packet with a CONNACK
return code 0x02 (Identifier rejected) and then close the Network Connection[MQTT-3.1.3-9].
Non normative comment
A Client implementation could provide a convenience method to generate a random ClientId. Use of such a method should be actively discouraged when the CleanSession is set to 0.
Solace Implementation Note
- ClientIds can be up to 128 bytes in length
- ClientIds can contain any UTF-8 characters as allowed by Section 1.5.3
3.1.3.2 Will Topic
If the Will Flag is set to 1, the Will Topic is the next field in the payload. The Will Topic MUST be a UTF-8 encoded string as defined in Section 1.5.3 UTF-8 encoded strings[MQTT-3.1.3-10].
Solace Implementation Note
A Will Topic must be valid as per Solace limitations described in section 2.7. Invalid topics will cause the CONNECT to be rejected or the Will message to be discarded if published.
3.1.3.3 Will Message
If the Will Flag is set to 1 the Will Message is the next field in the payload. The Will Message defines the Application Message that is to be published to the Will Topic as described in Section 3.1.2.5 Will Flag. This field consists of a two byte length followed by the payload for the Will Message expressed as a sequence of zero or more bytes. The length gives the number of bytes in the data that follows and does not include the 2 bytes taken up by the length itself.
When the Will Message is published to the Will Topic its payload consists only of the data portion of this field, not the first two length bytes.
3.1.3.4 User Name
If the User Name Flag is set to 1, this is the next field in the payload. The User Name MUST be a UTF-8 encoded string as defined in Section 1.5.3 UTF-8 encoded strings[MQTT-3.1.3-11]. It can be used by the Server for authentication and authorization.
Solace Implementation Note
If OAuth is used to authenticate the MQTT Client, then the Solace client user name used to establish connection policy is taken from an OAuth token (or introspection thereof) and the MQTT User Name in the CONNECT packet is ignored.
If an SSL Client Certificate is used by the MQTT Client to authenticate, then the Solace client user name used to establish connection policy is taken from the certificate and the MQTT User Name in the CONNECT packet is ignored. This behavior is consistent across all Solace-supported protocols. MQTT is silent about the handling of the user name in the certificate versus user name in the CONNECT packet.
Otherwise
- The Solace server maps the MQTT User Name to the Solace Client User Name for authentication purposes.
- The Solace server supports the ability for MQTT User Names (that is, Solace Client User Names) to be predefined on the appliance and to map directly to a client profile and Access Control List (ACL) profile for authorization purposes.
- The Solace server supports the ability for MQTT User Names to NOT be predefined on the appliance. In this case, the MQTT connection is associated with a client profile and ACL profile either through the default client user name (named “default”) or through an LDAP lookup of an LDAP group based on the MQTT User Name, which then maps to a client profile and an ACL profile.
- The maximum supported length of the MQTT User Name is 189 characters – same as the Solace client user name. If the MQTT client provides a longer User Name, then the connection is rejected because the full user name cannot be passed to the appropriate authentication and authorization service.
3.1.3.5 Password
If the Password Flag is set to 1, this is the next field in the payload. The Password field contains 0 to 65535 bytes of binary data prefixed with a two byte length field which indicates the number of bytes used by the binary data (it does not include the two bytes taken up by the length field itself).
Solace Implementation Note
The length of passwords that may be used are limited as follows:
- For Solace PubSub+ software event brokers using software version 8.4.0 or greater, and for appliances using software version 8.3.0 or greater, MQTT clients that use LDAP servers to authenticate can use passwords that contain up to 64,000 characters, including null characters. Clients that use RADIUS authentication are limited to 128 characters.
- For Solace Solace PubSub+ software event brokers using software versions prior to 8.4.0, and appliances using software versions prior to 8.3.0, the maximum supported password length for LDAP and RADIUS authentication is 128 characters. If the MQTT client provides a longer password, then the connection will be rejected because the full password cannot be passed to the appropriate authentication service. Passwords cannot contain binary data because null characters were treated as string terminators.
- For clients that use the Solace internal database for authentication, the length of a password is limited to 128 characters.
For broker versions 9.2.0 or greater, the password field is allowed to contain OAuth v2 tokens. These tokens must be supplied in a very specific format:
OAUTH~<Provider>~access_token
For broker versions 9.3.0 or greater, the password field can also contain OpenID Connect tokens:
OPENID~<Provider>~id_token~access_token
In both cases, the password must start with a literal string "OAUTH~" or "OPENID~" and be followed by the name of the provider (which must match one of the configured providers on the broker, or it can be zero-length which indicates that we should use the configured default-provider on the broker), and then another tilde and then the tokens (separated by yet-another tilde).
The access_token must be either a JWT (for broker versions 9.3.0 or greater) or a URL-encoded opaque token.
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
Data length MSB |
|||||||
byte 2 |
Data length LSB |
|||||||
byte 3 …. |
Data, if length > 0. |
3.1.4 Response
Note that a Server MAY support multiple protocols (including earlier versions of this protocol) on the same TCP port or other network endpoint. If the Server determines that the protocol is MQTT 3.1.1 then it validates the connection attempt as follows.
- If the Server does not receive a CONNECT Packet within a reasonable amount of time after the Network Connection is established, the Server SHOULD close the connection.
- The Server MUST validate that the CONNECT Packet conforms to section 3.1 CONNECT – Client requests a connection to a Server and close the Network Connection without sending a CONNACK if it does not
conform[MQTT-3.1.4-1].
- The Server MAY check that the contents of the CONNECT Packet meet any further restrictions and MAY perform authentication and authorization checks. If any of these checks fail, it SHOULD send an appropriate CONNACK response with a non-zero return code as described in section 3.2 CONNACK – Acknowledge connection request and it MUST close the Network Connection.
If validation is successful the Server performs the following steps.
- If the ClientId represents a Client already connected to the Server then the Server
MUST disconnect the existing Client[MQTT-3.1.4-2].
Solace Implementation Note
By default, if the ClientId represents a Client already connected to the Solace PubSub+ event broker, then the existing Client connection will be disconnected. However, an administrator can use the no replace-duplicate-client-connections Authentication Config command in the Solace CLI to override this behavior to leave the existing client connected.
- The Server MUST perform the processing of CleanSession that is described in section 3.1.2.4 Clean Session[MQTT-3.1.4-3].
- The Server MUST acknowledge the CONNECT Packet with a CONNACK Packet containing a zero return code[MQTT-3.1.4-4].
- Start message delivery and keep alive monitoring.
Clients are allowed to send further Control Packets immediately after sending a CONNECT Packet; Clients need
not wait for a CONNACK Packet to arrive from the Server. If the Server rejects the CONNECT, it MUST NOT process any data sent by the Client after
the CONNECT Packet[MQTT-3.1.4-5].
Non normative comment
Clients typically wait for a CONNACK Packet, However, if the Client exploits its freedom to send
Control Packets before it receives a CONNACK, it might simplify the Client implementation as it does
not have to police the connected state. The Client accepts that any data that it sends before it receives a
CONNACK packet from the Server will not be processed if the Server rejects the connection.
3.2 CONNACK – Acknowledge connection request
The CONNACK Packet is the packet sent by the Server in response to a CONNECT Packet received from a Client. The first packet sent from the Server to the Client MUST be a CONNACK Packet[MQTT-3.2.0-1].
If the Client does not receive a CONNACK Packet from the Server within a reasonable amount of time, the Client SHOULD close the Network Connection. A "reasonable" amount of time depends on the type of application and the communications infrastructure.
3.2.1 Fixed header
The fixed header format is illustrated in Figure 3.8 – CONNACK Packet fixed header.
Figure 3.8 – CONNACK Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet Type (2) |
Reserved |
||||||
|
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
byte 2 |
Remaining Length (2) |
|||||||
|
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
Remaining Length field
This is the length of the variable header. For the CONNACK Packet this has the value 2.
3.2.2 Variable header
The variable header format is illustrated in Figure 3.9 – CONNACK Packet variable header.
Figure 3.9 – CONNACK Packet variable header
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Connect Acknowledge Flags |
Reserved |
SP1 |
|||||||
byte 1 |
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
X |
Connect Return code |
|||||||||
byte 2 |
|
X |
X |
X |
X |
X |
X |
X |
X |
3.2.2.1 Connect Acknowledge Flags
Byte 1 is the "Connect Acknowledge Flags". Bits 7-1 are reserved and MUST be set to 0.
Bit 0
(SP1) is the Session Present Flag.
3.2.2.2 Session Present
Position: bit 0 of the Connect Acknowledge Flags.
If the Server accepts a connection with CleanSession set to 1, the Server MUST set
Session Present to 0 in the CONNACK packet in addition to setting a zero return code in the CONNACK
packet[MQTT-3.2.2-1].
If the Server accepts a connection with CleanSession set to 0, the value set in Session
Present depends on whether the Server already has stored Session state for the supplied client ID. If
the Server has stored Session state, it MUST set Session Present to 1 in the CONNACK packet[MQTT-3.2.2-2].If the Server does not have stored Session state, it MUST set Session Present to 0 in
the CONNACK packet. This is in addition to setting a zero return code in the CONNACK packet[MQTT-3.2.2-3].
The Session Present flag enables a Client to establish
whether the Client and Server have a consistent view about whether there is already stored Session
state.
Once the initial setup of a Session is complete, a Client with stored Session state
will expect the Server to maintain its stored Session state. In the event that the value of Session Present
received by the Client from the Server is not as expected, the Client can choose whether to proceed with the
Session or to disconnect. The Client can discard the Session state on both Client and Server by
disconnecting, connecting with Clean Session set to 1 and then disconnecting again.
If a server sends a CONNACK packet containing a non-zero return code it MUST set Session
Present to 0[MQTT-3.2.2-4].
3.2.2.3 Connect Return code
Byte 2 in the Variable header.
The values for the one byte unsigned Connect Return code field are listed in Table 3.1 – Connect Return code values. If a well formed CONNECT Packet is received by the Server, but the Server is unable to process it for some reason, then the Server SHOULD attempt to send a CONNACK packet containing the appropriate non-zero Connect return code from this table. If a server sends a CONNACK packet containing a non-zero return code it MUST then close the Network Connection[MQTT-3.2.2-5].
Table 3.1 – Connect Return code values
Value |
Return Code Response |
Description |
0 |
0x00 Connection Accepted |
Connection accepted |
1 |
0x01 Connection Refused, unacceptable protocol version |
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 |
The Network Connection has been made but the MQTT service is unavailable |
4 |
0x04 Connection Refused, bad user name or password |
The data in the user name or password is malformed |
5 |
0x05 Connection Refused, not authorized |
The Client is not authorized to connect |
6-255 |
|
Reserved for future use |
If none of the return codes listed in Table 3.1 – Connect Return code valuesare deemed applicable, then the Server MUST close the Network Connection without sending a CONNACK[MQTT-3.2.2-6].
3.2.3 Payload
The CONNACK Packet has no payload.
3.3 PUBLISH – Publish message
A PUBLISH Control Packet is sent from a Client to a Server or from Server to a Client to transport an Application Message.
3.3.1 Fixed header
Figure 3.10 – PUBLISH Packet fixed header illustrates the fixed header format:
Figure 3.10 – PUBLISH Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (3) |
DUP flag |
QoS level |
RETAIN |
||||
|
0 |
0 |
1 |
1 |
X |
X |
X |
X |
byte 2 |
Remaining Length |
3.3.1.1 DUP
Position: byte 1, bit 3.
If the DUP flag is set to 0, it indicates that this is the first occasion that the Client or Server has attempted to send this MQTT PUBLISH Packet. If the DUP flag is set to 1, it indicates that this might be re-delivery of an earlier attempt to send the Packet.
The DUP flag MUST be set to 1 by the Client or Server when it attempts to re-deliver a PUBLISH Packet[MQTT-3.3.1.-1]. The DUP flag MUST be set to 0 for all QoS 0 messages[MQTT-3.3.1-2].
The value of the DUP flag from an incoming PUBLISH packet is not propagated when the PUBLISH Packet is sent to subscribers by the Server. The DUP flag in the outgoing PUBLISH packet is set independently to the incoming PUBLISH packet, its value MUST be determined solely by whether the outgoing PUBLISH packet is a retransmission[MQTT-3.3.1-3].
Non normative comment
The recipient of a Control Packet that contains the DUP flag set to 1 cannot assume that it has seen an earlier copy of this packet.
Non normative comment
It is important to note that the DUP flag refers to the Control Packet itself and not to the Application Message that it contains. When using QoS 1, it is possible for a Client to receive a PUBLISH Packet with DUP flag set to 0 that contains a repetition of an Application Message that it received earlier, but with a different Packet Identifier. Section 2.3.1 Packet Identifier provides more information about Packet Identifiers.
3.3.1.2 QoS
Position: byte 1, bits 2-1.
This field indicates the level of assurance for delivery of an Application Message. The QoS levels are listed in the Table 3.2 - QoS definitions, below.
QoS value |
Bit 2 |
bit 1 |
Description |
0 |
0 |
0 |
At most once delivery |
1 |
0 |
1 |
At least once delivery |
2 |
1 |
0 |
Exactly once delivery |
- |
1 |
1 |
Reserved – must not be used |
A PUBLISH Packet MUST NOT have both QoS bits set to 1. If a Server or Client receives a PUBLISH Packet which has both QoS bits set to 1 it MUST close the Network Connection [MQTT-3.3.1-4].
3.3.1.3 RETAIN
Position: byte 1, bit 0.
If the RETAIN flag is set to 1, in a PUBLISH Packet sent by a Client to a Server, the Server MUST store the Application Message and its QoS, so that it can be delivered to future subscribers whose subscriptions match its topic name[MQTT-3.3.1-5]. When a new subscription is established, the last retained message, if any, on each matching topic name MUST be sent to the subscriber[MQTT-3.3.1-6]. If the Server receives a QoS 0 message with the RETAIN flag set to 1 it MUST discard any message previously retained for that topic. It SHOULD store the new QoS 0 message as the new retained message for that topic, but MAY choose to discard it at any time - if this happens there will be no retained message for that topic[MQTT-3.3.1-7]. See Section 4.1 Storing state for more information on storing state.
When sending a PUBLISH Packet to a Client the Server MUST set the RETAIN flag to 1 if a message is sent as a result of a new subscription being made by a Client[MQTT-3.3.1-8]. It MUST set the RETAIN flag to 0 when a PUBLISH Packet is sent to a Client because it matches an established subscription regardless of how the flag was set in the message it received[MQTT-3.3.1-9].
A PUBLISH Packet with a RETAIN flag set to 1 and a payload containing zero bytes will be processed as normal by the Server and sent to Clients with a subscription matching the topic name. Additionally any existing retained message with the same topic name MUST be removed and any future subscribers for the topic will not receive a retained message[MQTT-3.3.1-10]. “As normal” means that the RETAIN flag is not set in the message received by existing Clients. A zero byte retained message MUST NOT be stored as a retained message on the Server[MQTT-3.3.1-11].
If the RETAIN flag is 0, in a PUBLISH Packet sent by a Client to a Server, the Server MUST NOT store the message and MUST NOT remove or replace any existing retained message[MQTT-3.3.1-12].
Non normative comment
Retained messages are useful where publishers send state messages on an irregular basis. A new subscriber will receive the most recent state.
Remaining Lenght field
This is the length of variable header plus the length of the payload.
Solace Implementation Note
Support for MQTT Retained Messages is a Controlled Availability (CA) feature. Please contact Solace to find out if this feature is supported for your use case.
3.3.2 Variable header
The variable header contains the following fields in the order: Topic Name, Packet Identifier.
3.3.2.1 Topic Name
The Topic Name identifies the information channel to which payload data is published.
The Topic Name MUST be present as the first field in the PUBLISH Packet Variable header. It MUST be a UTF-8 encoded string[MQTT-3.3.2-1] as defined in section 1.5.3 UTF-8 encoded strings.
The Topic Name in the PUBLISH Packet MUST NOT contain wildcard characters[MQTT-3.3.2-2].
The Topic Name in a PUBLISH Packet sent by a Server to a subscribing Client MUST match the Subscription’s Topic Filter according to the matching process defined in Section 4.7 Topic Names and Topic Filters[MQTT-3.3.2-3]. However, since the Server is permitted to override the Topic Name, it might not be the same as the Topic Name in the original PUBLISH Packet.
Solace Implementation Note
Topics must comply with the limits discussed in Solace Message Format Topics. Topics outside these bounds cause the connection to be closed.
3.3.2.2 Packet Identifier
The Packet Identifier field is only present in PUBLISH Packets where the QoS level is 1 or 2. Section 2.3.1 Packet Identifier provides more information about Packet Identifiers.
3.3.2.3 Variable header non normative example
Figure 3.11 - Publish Packet variable header non normative example illustrates an example variable header for the PUBLISH Packet briefly described in Table 3.3 - Publish Packet non normative example.
Table 3.3 - Publish Packet non normative example
Field |
Value |
Topic Name |
a/b |
Packet Identifier |
10 |
Figure 3.11 - Publish Packet variable header non normative example
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Topic Name |
|||||||||
byte 1 |
Length MSB (0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 2 |
Length LSB (3) |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
byte 3 |
‘a’ (0x61) |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
1 |
byte 4 |
‘/’ (0x2F) |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
byte 5 |
‘b’ (0x62) |
0 |
1 |
1 |
0 |
0 |
0 |
1 |
0 |
Packet Identifier |
|||||||||
byte 6 |
Packet Identifier MSB (0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 7 |
Packet Identifier LSB (10) |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
3.3.3 Payload
The Payload contains the Application Message that is being published. The content and format of the data is application specific. The length of the payload can be calculated by subtracting the length of the variable header from the Remaining Length field that is in the Fixed Header. It is valid for a PUBLISH Packet to contain a zero length payload.
Solace Implementation Note
Solace has limits to the size of a message, depending on the message QoS and the type of event broker.
When a Solace server receives a message whose length + QoS combination exceeds these limits the connection is closed and an appropriate log is raised. Note that the Solace PubSub+ event broker administrator may configure lower limits than these.
3.3.4 Response
The receiver of a PUBLISH Packet MUST respond according to Table 3.4 - Expected Publish Packet response as determined by the QoS in the PUBLISH Packet[MQTT-3.3.4-1].
Table 3.4 - Expected Publish Packet response
QoS Level |
Expected Response |
QoS 0 |
None |
QoS 1 |
PUBACK Packet |
QoS 2 |
PUBREC Packet |
3.3.5 Actions
The Client uses a PUBLISH Packet to send an Application Message to the Server, for distribution to Clients with matching subscriptions.
The Server uses a PUBLISH Packet to send an Application Message to each Client which has a matching subscription.
When Clients make subscriptions with Topic Filters that include wildcards, it is possible for a Client’s subscriptions to overlap so that a published message might match multiple filters. In this case the Server MUST deliver the message to the Client respecting the maximum QoS of all the matching subscriptions[MQTT-3.3.5-1]. In addition, the Server MAY deliver further copies of the message, one for each additional matching subscription and respecting the subscription’s QoS in each case.
Solace Implementation Note
When the Solace server delivers the message to the Client, it will respect the maximum QoS of all the matching subscriptions. In addition, if there is one or more QoS 1 subscriptions and one or more QoS 0 subscriptions that overlap, then the Solace server will deliver two instances of the message – one for each QoS level.
The action of the recipient when it receives a PUBLISH Packet depends on the QoS level as described in Section 4.3 Quality of Service levels and protocol flows.
If a Server implementation does not authorize a PUBLISH to be performed by a Client; it has no way of informing that Client. It MUST either make a positive acknowledgement, according to the normal QoS rules, or close the Network Connection[MQTT-3.3.5-2].
Solace Implementation Note
The Solace server does not fully support the two-phase commit semantics of receiving a PUBLISH packet with QoS 2. However, to provide maximum interoperability, as allowed by the above section, the Solace server will respond to a PUBLISH packet with QoS 2 (that is, the Solace server will respond to a received QoS 2 PUBLISH packet with a PUBREC packet, and will respond to a received PUBREL packet with a PUBCOMP packet). This response effectively provides the same quality of service treatment as a QoS 1 message.
3.4 PUBACK – Publish acknowledgement
A PUBACK Packet is the response to a PUBLISH Packet with QoS level 1.
3.4.1 Fixed header
Figure 3.12 - PUBACK Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (4) |
Reserved |
||||||
|
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 2 |
Remaining Length (2) |
|||||||
|
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
Remaining Length field
This is the length of the variable header. For the PUBACK Packet this has the value 2.
3.4.2 Variable header
This contains the Packet Identifier from the PUBLISH Packet that is being acknowledged.
Figure 3.13 – PUBACK Packet variable header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
Packet Identifier MSB |
|||||||
byte 2 |
Packet Identifier LSB |
3.4.3 Payload
The PUBACK Packet has no payload.
3.4.4 Actions
This is fully described in Section 4.3.2 QoS 1: At least once delivery.
3.5 PUBREC – Publish received (QoS 2 publish received, part 1)
A PUBREC Packet is the response to a PUBLISH Packet with QoS 2. It is the second packet of the QoS 2 protocol exchange.
3.5.1 Fixed header
Figure 3.14 – PUBREC Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (5) |
Reserved |
||||||
|
0 |
1 |
0 |
1 |
0 |
0 |
0 |
0 |
byte 2 |
Remaining Length (2) |
|||||||
|
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
Remaining Length field
This is the length of the variable header. For the PUBREC Packet this has the value 2.
3.5.2 Variable header
The variable header contains the Packet Identifier from the PUBLISH Packet that is being acknowledged.
Figure 3.15 – PUBREC Packet variable header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
Packet Identifier MSB |
|||||||
byte 2 |
Packet Identifier LSB |
3.5.3 Payload
The PUBREC Packet has no payload.
3.5.4 Actions
This is fully described in Section 4.3.3 QoS 2: Exactly once delivery.
3.6 PUBREL – Publish release (QoS 2 publish received, part 2)
A PUBREL Packet is the response to a PUBREC Packet. It is the third packet of the QoS 2 protocol exchange.
3.6.1 Fixed header
Figure 3.16 – PUBREL Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
||||||
byte 1 |
MQTT Control Packet type (6) |
Reserved |
||||||||||||
|
0 |
1 |
1 |
0 |
0 |
0 |
1 |
0 |
||||||
byte 2 |
Remaining Length (2) |
|||||||||||||
|
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
Bits 3,2,1 and 0 of the fixed header in the PUBREL Control Packet are reserved and MUST be set to 0,0,1 and 0 respectively. The Server MUST treat any other value as malformed and close the Network Connection[MQTT-3.6.1-1].
Remaining Length field
This is the length of the variable header. For the PUBREL Packet this has the value 2.
3.6.2 Variable header
The variable header contains the same Packet Identifier as the PUBREC Packet that is being acknowledged.
Figure 3.17 – PUBREL Packet variable header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
Packet Identifier MSB |
|||||||
byte 2 |
Packet Identifier LSB |
3.6.3 Payload
The PUBREL Packet has no payload.
3.6.4 Actions
This is fully described in 4.3.3 QoS 2: Exactly once delivery.
3.7 PUBCOMP – Publish complete (QoS 2 publish received, part 3)
The PUBCOMP Packet is the response to a PUBREL Packet. It is the fourth and final packet of the QoS 2 protocol exchange.
3.7.1 Fixed header
Figure 3.18 – PUBCOMP Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (7) |
Reserved |
||||||
|
0 |
1 |
1 |
1 |
0 |
0 |
0 |
0 |
byte 2 |
Remaining Length (2) |
|||||||
|
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
Remaining Length field
This is the length of the variable header. For the PUBCOMP Packet this has the value 2.
3.7.2 Variable header
The variable header contains the same Packet Identifier as the PUBREL Packet that is being acknowledged.
Figure 3.19 – PUBCOMP Packet variable header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
Packet Identifier MSB |
|||||||
byte 2 |
Packet Identifier LSB |
3.7.3 Payload
The PUBCOMP Packet has no payload.
3.7.4 Actions
This is fully described in Section 4.3.3 QoS 2: Exactly once delivery.
3.8 SUBSCRIBE - Subscribe to topics
The SUBSCRIBE Packet is sent from the Client to the Server to create one or more Subscriptions. Each Subscription registers a Client’s interest in one or more Topics. The Server sends PUBLISH Packets to the Client in order to forward Application Messages that were published to Topics that match these Subscriptions. The SUBSCRIBE Packet also specifies (for each Subscription) the maximum QoS with which the Server can send Application Messages to the Client.
3.8.1 Fixed header
Figure 3.20 – SUBSCRIBE Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (8) |
Reserved |
||||||
|
1 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
byte 2 |
Remaining Length |
Bits 3,2,1 and 0 of the fixed header of the SUBSCRIBE Control Packet are reserved and MUST be set to 0,0,1 and 0 respectively. The Server MUST treat any other value as malformed and close the Network Connection[MQTT-3.8.1-1].
Remaining Length field
This is the length of variable header (2 bytes) plus the length of the payload.
3.82 Variable header
The variable header contains a Packet Identifier. Section 2.3.1 Packet Identifier provides more information about Packet Identifiers.
3.8.2.1 Variable header non normative example
Figure 3.21 shows a variable header with Packet Identifier set to 10.
Figure 3.21 - Variable header with a Packet Identifier of 10, Non normative example
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Packet Identifier |
|||||||||
byte 1 |
Packet Identifier MSB (0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 2 |
Packet Identifier LSB (10) |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
3.8.3 Payload
The payload of a SUBSCRIBE Packet contains a list of Topic Filters indicating the Topics to which the Client wants to subscribe. The Topic Filters in a SUBSCRIBE packet payload MUST be UTF-8 encoded strings as defined in Section 1.5.3 UTF-8 encoded strings[MQTT-3.8.3-1]. A Server SHOULD support Topic filters that contain the wildcard characters defined in Section 4.7.1. If it chooses not to support topic filters that contain wildcard characters it MUST reject any Subscription request whose filter contains them[MQTT-3.8.3-2]. Each filter is followed by a byte called the Requested QoS. This gives the maximum QoS level at which the Server can send Application Messages to the Client.
The payload of a SUBSCRIBE packet MUST contain at least one Topic Filter / QoS pair. A SUBSCRIBE packet with no payload is a protocol violation[MQTT-3.8.3-3]. See section 4.8 Handling errors for information about handling errors.
The requested maximum QoS field is encoded in the byte following each UTF-8 encoded topic name, and these Topic Filter / QoS pairs are packed contiguously.
Figure 3.22 – SUBSCRIBE Packet payload format
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Topic Filter |
||||||||
byte 1 |
Length MSB |
|||||||
byte 2 |
Length LSB |
|||||||
bytes 3..N |
Topic Filter |
|||||||
Requested QoS |
||||||||
|
Reserved |
QoS |
||||||
byte N+1 |
0 |
0 |
0 |
0 |
0 |
0 |
X |
X |
The upper 6 bits of the Requested QoS byte are not used in the current version of the protocol. They are reserved for future use. The Server MUST treat a SUBSCRIBE packet as malformed and close the Network Connection if any of Reserved bits in the payload are non-zero, or QoS is not 0,1 or 2[MQTT-3-8.3-4].
Solace Implementation Note
- Topics must comply with the limits discussed in Solace Message Format Topics. Topics outside these bounds are rejected with a SUBACK containing the value 0x80 to indicate failure.
- SUBSCRIBE packets can contain at most 1,024 Topic Filters. Exceeding this limit will cause the connection to be closed.
3.8.3.1 Payload non normative example
Figure 3.23 - Payload byte format non normative exampleshows the payload for the SUBSCRIBE Packet briefly described inTable 3.5 - Payload non normative example.
Table 3.5 - Payload non normative example
Topic Name |
“a/b” |
Requested QoS |
0x01 |
Topic Name |
“c/d” |
Requested QoS |
0x02 |
Figure 3.23 - Payload byte format non normative example
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Topic Filter |
|||||||||
byte 1 |
Length MSB (0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 2 |
Length LSB (3) |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
byte 3 |
‘a’ (0x61) |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
1 |
byte 4 |
‘/’ (0x2F) |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
byte 5 |
‘b’ (0x62) |
0 |
1 |
1 |
0 |
0 |
0 |
1 |
0 |
Requested QoS |
|||||||||
byte 6 |
Requested QoS(1) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
Topic Filter |
|||||||||
byte 7 |
Length MSB (0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 8 |
Length LSB (3) |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
byte 9 |
‘c’ (0x63) |
0 |
1 |
1 |
0 |
0 |
0 |
1 |
1 |
byte 10 |
‘/’ (0x2F) |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
byte 11 |
‘d’ (0x64) |
0 |
1 |
1 |
0 |
0 |
1 |
0 |
0 |
Requested QoS |
|||||||||
byte 12 |
Requested QoS(2) |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
3.8.4 Response
When the Server receives a SUBSCRIBE Packet from a Client, the Server MUST respond with a SUBACK Packet[MQTT-3.8.4-1]. The SUBACK Packet MUST have the same Packet Identifier as the SUBSCRIBE Packet that it is acknowledging[MQTT-3.8.4-2].
The Server is permitted to start sending PUBLISH packets matching the Subscription before the Server sends the SUBACK Packet.
If a Server receives a SUBSCRIBE Packet containing a Topic Filter that is identical to an existing Subscription’s Topic Filter then it MUST completely replace that existing Subscription with a new Subscription. The Topic Filter in the new Subscription will be identical to that in the previous Subscription, although its maximum QoS value could be different. Any existing retained messages matching the Topic Filter MUST be re-sent, but the flow of publications MUST NOT be interrupted[MQTT-3.8.4-3].
Where the Topic Filter is not identical to any existing Subscription’s filter, a new Subscription is created and all matching retained messages are sent.
If a Server receives a SUBSCRIBE packet that contains multiple Topic Filters it MUST handle that packet as if it had received a sequence of multiple SUBSCRIBE packets, except that it combines their responses into a single SUBACK response[MQTT-3.8.4-4].
The SUBACK Packet sent by the Server to the Client MUST contain a return code for each Topic Filter/QoS pair. This return code MUST either show the maximum QoS that was granted for that Subscription or indicate that the subscription failed[MQTT-3.8.4-5].The Server might grant a lower maximum QoS than the subscriber requested. The QoS of Payload Messages sent in response to a Subscription MUST be the minimum of the QoS of the originally published message and the maximum QoS granted by the Server. The server is permitted to send duplicate copies of a message to a subscriber in the case where the original message was published with QoS 1 and the maximum QoS granted was QoS 0[MQTT-3.8.4-6].
Non normative examples
If a subscribing Client has been granted maximum QoS 1 for a particular Topic Filter, then a
QoS 0 Application Message matching the filter is delivered to the Client at QoS 0. This means that at most
one copy of the message is received by the Client. On the other hand a QoS 2 Message published to the same
topic is downgraded by the Server to QoS 1 for delivery to the Client, so that Client might receive
duplicate copies of the Message.
If the subscribing Client has been granted maximum QoS 0, then an Application Message originally published as QoS 2 might get lost on the hop to the Client, but the Server should never send a duplicate of that Message. A QoS 1 Message published to the same topic might either get lost or duplicated on its transmission to that Client.
Non normative comment
Subscribing to a Topic Filter at QoS 2 is equivalent to saying "I would like to receive Messages matching this filter at the QoS with which they were published". This means a publisher is responsible for determining the maximum QoS a Message can be delivered at, but a subscriber is able to require that the Server downgrades the QoS to one more suitable for its usage.
3.9 SUBACK – Subscribe acknowledgement
A SUBACK Packet is sent by the Server to the Client to confirm receipt and processing of a SUBSCRIBE Packet.
A SUBACK Packet contains a list of return codes, that specify the maximum QoS level that was granted in each Subscription that was requested by the SUBSCRIBE.
3.9.1 Fixed header
Figure 3.24 – SUBACK Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (9) |
Reserved |
||||||
|
1 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
byte 2 |
Remaining Length |
Remaining Length field
This is the length of variable header (2 bytes) plus the length of the payload.
3.9.2 Variable header
The variable header contains the Packet Identifier from the SUBSCRIBE Packet that is being acknowledged. Figure 3.25 - variable header format below illustrates the format of the variable header.
Figure 3.25 – SUBACK Packet variable header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
Packet Identifier MSB |
|||||||
byte 2 |
Packet Identifier LSB |
3.9.3 Payload
The payload contains a list of return codes. Each return code corresponds to a Topic Filter in the SUBSCRIBE Packet being acknowledged. The order of return codes in the SUBACK Packet MUST match the order of SUBSCRIBE Packet[MQTT-3.9.3-1].
Figure 3.26 - Payload format below illustrates the Return Code field encoded in a byte in the Payload.
Figure 3.26 – SUBACK Packet payload format
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
Return Code |
|||||||
byte 1 |
X |
0 |
0 |
0 |
0 |
0 |
X |
X |
Allowed return codes:
0x00 - Success - Maximum QoS 0
0x01 - Success - Maximum QoS 1
0x02 - Success - Maximum
QoS 2
0x80 - Failure
SUBACK return codes other than 0x00, 0x01, 0x02 and 0x80 are reserved and MUST NOT be used [MQTT-3.9.3-2].
Solace Implementation Note
The Solace server grants a Maximum QoS of 1 when a client requests a QoS 2 subscription. The Solace server never returns a QoS 2 in a SUBACK packet.
3.9.3.1 Payload non normative example
Figure 3.27 - Payload byte format non normative example shows the payload for the SUBACK Packet briefly described in Table 3.6 - Payload non normative example.
Table 3.6 - Payload non normative example
Success - Maximum QoS 0 |
0 |
Success - Maximum QoS 2 |
2 |
Failure |
128 |
Figure 3.27 - Payload byte format non normative example
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
Success - Maximum QoS 0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 2 |
Success - Maximum QoS 2 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
byte 3 |
Failure |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
3.10 UNSUBSCRIBE – Unsubscribe from topics
An UNSUBSCRIBE Packet is sent by the Client to the Server, to unsubscribe from topics.
3.10.1 Fixed header
Figure 3.28 – UNSUBSCRIBE Packet Fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (10) |
Reserved |
||||||
|
1 |
0 |
1 |
0 |
0 |
0 |
1 |
0 |
byte 2 |
Remaining Length |
Bits 3,2,1 and 0 of the fixed header of the UNSUBSCRIBE Control Packet are reserved and MUST be set to 0,0,1 and 0 respectively. The Server MUST treat any other value as malformed and close the Network Connection[MQTT-3.10.1-1].
Remaining Length field
This is the length of variable header (2 bytes) plus the length of the payload.
3.10.2 Variable header
The variable header contains a Packet Identifier. Section 2.3.1 Packet Identifier provides more information about Packet Identifiers.
Figure 3.29 – UNSUBSCRIBE Packet variable header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
Packet Identifier MSB |
|||||||
byte 2 |
Packet Identifier LSB |
3.10.3 Payload
The payload for the UNSUBSCRIBE Packet contains the list of Topic Filters that the Client wishes to unsubscribe from. The Topic Filters in an UNSUBSCRIBE packet MUST be UTF-8 encoded strings as defined in Section 1.5.3 UTF-8 encoded strings, packed contiguously[MQTT-3.10.3-1].
The Payload of an UNSUBSCRIBE packet MUST contain at least one Topic Filter. AnUNSUBSCRIBE packet with no payload is a protocol violation[MQTT-3.10.3-2]. See section 4.8 Handling errors for information about handling errors.
Solace Implementation Note
- Topics must comply with the limits discussed in Solace Message Format Topics. Topics outside these bounds will cause the connection to be closed.
- UNSUBSCRIBE packets can contain at most 1024 Topic Filters. Exceeding this limit will cause the connection to be closed.
3.10.3 .1Payload non normative example
Figure 3.30 - Payload byte format non normative exampleshow the payload for the UNSUBSCRIBE Packet briefly described inTable3.7 - Payload non normative example.
Table3.7 - Payload non normative example
Topic Filter |
“a/b” |
Topic Filter |
“c/d” |
Figure 3.30 - Payload byte format non normative example
|
Description |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Topic Filter |
|||||||||
byte 1 |
Length MSB (0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 2 |
Length LSB (3) |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
byte 3 |
‘a’ (0x61) |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
1 |
byte 4 |
‘/’ (0x2F) |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
byte 5 |
‘b’ (0x62) |
0 |
1 |
1 |
0 |
0 |
0 |
1 |
0 |
Topic Filter |
|||||||||
byte 6 |
Length MSB (0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 7 |
Length LSB (3) |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
byte 8 |
‘c’ (0x63) |
0 |
1 |
1 |
0 |
0 |
0 |
1 |
1 |
byte 9 |
‘/’ (0x2F) |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
byte 10 |
‘d’ (0x64) |
0 |
1 |
1 |
0 |
0 |
1 |
0 |
0 |
3.10.4 Response
The Topic Filters (whether they contain wildcards or not) supplied in an UNSUBSCRIBE
packet MUST be compared character-by-character with the current set of Topic Filters held by the Server
for the Client. If any filter matches exactly then its owning Subscription is deleted, otherwise no
additional processing occurs[MQTT-3.10.4-1].
If a Server deletes a Subscription:
- It MUST stop adding any new messages for delivery to the Client[MQTT-3.10.4-2].
- It MUST complete the delivery of any QoS 1 or QoS 2 messages which it has started to send to the Client[MQTT-3.10.4-3].
- It MAY continue to deliver any existing messages buffered for delivery to the Client.
The Server MUST respond to an UNSUBSUBCRIBE request by sending an UNSUBACK packet. The
UNSUBACK Packet MUST have the same Packet Identifier as the UNSUBSCRIBE Packet[MQTT-3.10.4-4]. Even where no Topic Subscriptions are deleted, the Server MUST respond with an
UNSUBACK[MQTT-3.10.4-5].
If a Server receives an UNSUBSCRIBE packet that contains multiple Topic Filters it MUST handle that packet as if it had received a sequence of multiple UNSUBSCRIBE packets, except that it sends just one UNSUBACK response[MQTT-3.10.4-6].
3.11 UNSUBACK – Unsubscribe acknowledgement
The UNSUBACK Packet is sent by the Server to the Client to confirm receipt of an UNSUBSCRIBE Packet.
3.11.1Fixed header
Figure 3.31 – UNSUBACK Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (11) |
Reserved |
||||||
|
1 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
byte 2 |
Remaining Length (2) |
|||||||
|
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
Remaining Length field
This is the length of the variable header. For the UNSUBACK Packet this has the value 2.
3.11.2 Variable header
The variable header contains the Packet Identifier of the UNSUBSCRIBE Packet that is being acknowledged.
Figure 3.32 – UNSUBACK Packet variable header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
Packet Identifier MSB |
|||||||
byte 2 |
Packet Identifier LSB |
3.11.3 Payload
The UNSUBACK Packet has no payload.
3.12 PINGREQ – PING request
The PINGREQ Packet is sent from a Client to the Server. It can be used to:
- 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.
This Packet is used in Keep Alive processing, see Section 3.1.2.10 Keep Alive for more details.
Figure 3.33 – PINGREQ Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (12) |
Reserved |
||||||
|
1 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
byte 2 |
Remaining Length (0) |
|||||||
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
3.12.2 Variable header
The PINGREQ Packet has no variable header.
3.12.3 Payload
The PINGREQ Packet has no payload.
3.12.4 Response
The Server MUST send a PINGRESP Packet in response to a PINGREQ Packet[MQTT-3.12.4-1].
3.13 PINGRESP – PING response
A PINGRESP Packet is sent by the Server to the Client in response to a PINGREQ Packet. It indicates that the Server is alive.
This Packet is used in Keep Alive processing, see Section 3.1.2.10 Keep Alive for more details.
3.13.1 Fixed header
Figure 3.34 – PINGRESP Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (13) |
Reserved |
||||||
|
1 |
1 |
0 |
1 |
0 |
0 |
0 |
0 |
byte 2 |
Remaining Length (0) |
|||||||
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
3.13.2 Variable header
The PINGRESP Packet has no variable header.
3.13.3 Payload
The PINGRESP Packet has no payload.
3.14 DISCONNECT – Disconnect notification
The DISCONNECT Packet is the final Control Packet sent from the Client to the Server. It indicates that the Client is disconnecting cleanly.
3.14.1 Fixed header
Figure 3.35 – DISCONNECT Packet fixed header
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte 1 |
MQTT Control Packet type (14) |
Reserved |
||||||
|
1 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
byte 2 |
Remaining Length (0) |
|||||||
|
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
The Server MUST validate that reserved bits are set to zero and disconnect the Client if they are not zero[MQTT-3.14.1-1].
3.14.2 Variable header
The DISCONNECT Packet has no variable header.
3.14.3 Payload
The DISCONNECT Packet has no payload.
3.14.4 Response
After sending a DISCONNECT Packet the Client:
- MUST close the Network Connection[MQTT-3.14.4-1].
- MUST NOT send any more Control Packets on that Network Connection[MQTT-3.14.4-2].
On receipt of DISCONNECT the Server:
- MUST discard any Will Message associated with the current connection without publishing it, as described in Section 3.1.2.5 Will Flag[MQTT-3.14.4-3].
- SHOULD close the Network Connection if the Client has not already done so.