4 Operational behavior

4.1 Storing state

It is necessary for the Client and Server to store Session state in order to provide Quality of Service guarantees. The Client and Server MUST store Session state for the entire duration of the Session[MQTT-4.1.0-1]. A Session MUST last at least as long it has an active Network Connection [MQTT-4.1.0-2].

Retained messages do not form part of the Session state in the Server. The Server SHOULD retain such messages until deleted by a Client.

Non normative comment

The storage capabilities of Client and Server implementations will of course have limits in terms of capacity and may be subject to administrative policies such as the maximum time that Session state is stored between Network Connections. Stored Session state can be discarded as a result of an administrator action, including an automated response to defined conditions. This has the effect of terminating the Session. These actions might be prompted by resource constraints or for other operational reasons. It is prudent to evaluate the storage capabilities of the Client and Server to ensure that they are sufficient.

Non normative comment

It is possible that hardware or software failures may result in loss or corruption of Session state stored by the Client or Server.

Non normative comment

Normal operation of the Client of Server could mean that stored state is lost or corrupted because of administrator action, hardware failure or software failure. An administrator action could be an automated response to defined conditions. These actions might be prompted by resource constraints or for other operational reasons. For example the server might determine that based on external knowledge, a message or messages can no longer be delivered to any current or future client.

Non normative comment

An MQTT user should evaluate the storage capabilities of the MQTT Client and Server implementations to ensure that they are sufficient for their needs.

4.1.1 Non normative example

For example, a user wishing to gather electricity meter readings may decide that they need to use QoS 1 messages because they need to protect the readings against loss over the network, however they may have determined that the power supply is sufficiently reliable that the data in the Client and Server can be stored in volatile memory without too much risk of its loss.

Conversely a parking meter payment application provider might decide that there are no circumstances where a payment message can be lost so they require that all data are force written to non-volatile memory before it is transmitted across the network.

4.2 Network Connections

The MQTT protocol requires an underlying transport that provides an ordered, lossless, stream of bytes from the Client to Server and Server to Client.

Non normative comment

The transport protocol used to carry MQTT 3.1 was TCP/IP as defined in [RFC793].TCP/IP can be used for MQTT 3.1.1. The following are also suitable:

Non normative comment

TCP ports 8883 and 1883 are registered with IANA for MQTT TLS and non TLS communication respectively.

Solace Implementation Note

  • The Solace server supports TCP/IP transport of MQTT.
  • The Solace server supports TLS transport of MQTT.
  • The Solace server supports WebSocket transport of MQTT.
  • The Solace server supports WebSocket Secure transport of MQTT.

Connectionless network transports such as User Datagram Protocol (UDP) are not suitable on their own because they might lose or reorder data.

4.3 Quality of Service levels and protocol flows

MQTT delivers Application Messages according to the Quality of Service (QoS) levels defined here. The delivery protocol is symmetric, in the description below the Client and Server can each take the role of either Sender or Receiver. The delivery protocol is concerned solely with the delivery of an application message from a single Sender to a single Receiver. When the Server is delivering an Application Message to more than one Client, each Client is treated independently. The QoS level used to deliver an Application Message outbound to the Client could differ from that of the inbound Application Message.

The non-normative flow diagrams in the following sections are intended to show possible implementation approaches.

Solace Implementation Note

The following table summarizes Solace PubSub+ software behavior for all combinations of a message published with one QoS matching a subscription with a second QoS. The behavior shown in the table adheres to the MQTT specification.

Resulting QoS Level of Messages to be Consumed

 

Subscribe QoS

Publish QoS

0

1

2

0

0

0

0

1

0

1

1

2

0

1

1

  • Messages published with QoS 0 are not queued on the Solace PubSub+ event broker if not subscribing.
  • Messages published with QoS 1 are queued on the Solace PubSub+ event broker even when subscribing clients are not connected. QoS 2 subscriptions are downgraded to QoS 1, and are therefore treated in the same manner.

4.3.1 QoS 0: At most once delivery

The message is delivered according to the capabilities of the underlying network. No response is sent by the receiver and no retry is performed by the sender. The message arrives at the receiver either once or not at all.

In the QoS 0 delivery protocol, the Sender

  • MUST send a PUBLISH packet with QoS=0, DUP=0[MQTT-4.3.1-1].

In the QoS 0 delivery protocol, the Receiver

  • Accepts ownership of the message when it receives the PUBLISH packet.

Figure 4.1 – QoS 0 protocol flow diagram, non normative example

Sender Action

Control Packet

Receiver Action

PUBLISH QoS 0, DUP=0

 

 

 

 

---------->

 

 

 

Deliver Application Message to appropriate onward recipient(s)

4.3.2 QoS 1: At least once delivery

This quality of service ensures that the message arrives at the receiver at least once. A QoS 1 PUBLISH Packet has a Packet Identifier in its variable header and is acknowledged by a PUBACK Packet. Section 2.3.1 Packet Identifier provides more information about Packet Identifiers.

In the QoS 1 delivery protocol, the Sender

  • MUST assign an unused Packet Identifier each time it has a new Application Message to publish.
  • MUST send a PUBLISH Packet containing this Packet Identifier with QoS=1, DUP=0.
  • MUST treat the PUBLISH Packet as “unacknowledged” until it has received the corresponding PUBACK packet from the receiver. See Section 4.4 Message delivery retry for a discussion of unacknowledged messages.

[MQTT-4.3.2-1]

The Packet Identifier becomes available for reuse once the Sender has received the PUBACK Packet.

Note that a Sender is permitted to send further PUBLISH Packets with different Packet Identifiers while it is waiting to receive acknowledgements.

In the QoS 1 delivery protocol, the Receiver

  • MUST respond with a PUBACK Packet containing the Packet Identifier from the incoming PUBLISH Packet, having accepted ownership of the Application Message
  • After it has sent a PUBACK Packet the Receiver MUST treat any incoming PUBLISH packet that contains the same Packet Identifier as being a new publication, irrespective of the setting of its DUP flag.

[MQTT-4.3.2-2].

Figure 4.2 – QoS 1 protocol flow diagram, non normative example

Sender Action

Control Packet

Receiver action

Store message

 

 

Send PUBLISH QoS 1, DUP 0,
<Packet Identifier>

---------->

 

 

 

Initiate onward delivery of the Application Message1

 

<----------

Send PUBACK <Packet Identifier>

Discard message

 

 

1 The receiver is not required to complete delivery of the Application Message before sending the PUBACK. When its original sender receives the PUBACK packet, ownership of the Application Message is transferred to the receiver.

4.3.3 QoS 2: Exactly once delivery

This is the highest quality of service, for use when neither loss nor duplication of messages are acceptable. There is an increased overhead associated with this quality of service.

Solace Implementation Note

QoS 2 messages from clients are accepted but are treated as QoS 1 messages. QoS 2 subscriptions from clients are accepted but are downgraded to QoS 1. Both of these behaviors are allowed by the specification.

A QoS 2 message has a Packet Identifier in its variable header. Section 2.3.1 Packet Identifier provides more information about Packet Identifiers. The receiver of a QoS 2 PUBLISH Packet acknowledges receipt with a two-step acknowledgement process.

In the QoS 2 delivery protocol, the Sender

  • MUST assign an unused Packet Identifier when it has a new Application Message to publish.
  • MUST send a PUBLISH packet containing this Packet Identifier with QoS=2, DUP=0.
  • MUST treat the PUBLISH packet as “unacknowledged” until it has received the corresponding PUBREC packet from the receiver. See Section 4.4 Message delivery retry for a discussion of unacknowledged messages.
  • MUST send a PUBREL packet when it receives a PUBREC packet from the receiver. This PUBREL packet MUST contain the same Packet Identifier as the original PUBLISH packet.
  • MUST treat the PUBREL packet as “unacknowledged” until it has received the corresponding PUBCOMP packet from the receiver.
  • MUST NOT re-send the PUBLISH once it has sent the corresponding PUBREL packet.

[MQTT-4.3.3-1].

The Packet Identifier becomes available for reuse once the Sender has received the PUBCOMP Packet.

Note that a Sender is permitted to send further PUBLISH Packets with different Packet Identifiers while it is waiting to receive acknowledgements.

In the QoS 2 delivery protocol, the Receiver

  • MUST respond with a PUBREC containing the Packet Identifier from the incoming PUBLISH Packet, having accepted ownership of the Application Message.
  • Until it has received the corresponding PUBREL packet, the Receiver MUST acknowledge any subsequent PUBLISH packet with the same Packet Identifier by sending a PUBREC. It MUST NOT cause duplicate messages to be delivered to any onward recipients in this case.

Solace Implementation Note

In this case the Solace server MAY cause duplicate messages to be delivered onward to QoS 1 subscribers.

  • MUST respond to a PUBREL packet by sending a PUBCOMP packet containing the same Packet Identifier as the PUBREL.
  • After it has sent a PUBCOMP, the receiver MUST treat any subsequent PUBLISH packet that contains that Packet Identifier as being a new publication.

[MQTT-4.3.3-2].

Figure 4.3 – QoS 2 protocol flow diagram, non normative example

1 The receiver is not required to complete delivery of the Application Message before sending the PUBREC or PUBCOMP. When its original sender receives the PUBREC packet, ownership of the Application Message is transferred to the receiver.

Figure 4.3 shows that there are two methods by which QoS 2 can be handled by the receiver. They differ in the point within the flow at which the message is made available for onward delivery. The choice of Method A or Method B is implementation specific. As long as an implementation chooses exactly one of these approaches, this does not affect the guarantees of a QoS 2 flow.

4.4 Message delivery retry

When a Client reconnects with CleanSession set to 0, both the Client and Server MUST re-send any unacknowledged PUBLISH Packets (where QoS > 0) and PUBREL Packets using their original Packet Identifiers[MQTT-4.4.0-1]. This is the only circumstance where a Client or Server is REQUIRED to redeliver messages.


Non normative comment
Historically retransmission of Control Packets was required to overcome data loss on some older TCP networks. This might remain a concern where MQTT 3.1.1 implementations are to be deployed in such environments.

4.5 Message receipt

When a Server takes ownership of an incoming Application Message it MUST add it to the Session state of those clients that have matching Subscriptions. Matching rules are defined in Section 4.7 Topic Names and Topic Filters[MQTT-4.5.0-1].

Under normal circumstances Clients receive messages in response to Subscriptions they have created. A Client could also receive messages that do not match any of its explicit Subscriptions. This can happen if the Server automatically assigned a subscription to the Client. A Client could also receive messages while an UNSUBSCRIBE operation is in progress. The Client MUST acknowledge any Publish Packet it receives according to the applicable QoS rules regardless of whether it elects to process the Application Message that it contains[MQTT-4.5.0-2].

4.6 Message ordering

A Client MUST follow these rules when implementing the protocol flows defined elsewhere in this chapter:

  • When it re-sends any PUBLISH packets, it MUST re-send them in the order in which the original PUBLISH packets were sent (this applies to QoS 1 and QoS 2 messages)[MQTT-4.6.0-1]
  • It MUST send PUBACK packets in the order in which the corresponding PUBLISH packets were received (QoS 1 messages)[MQTT-4.6.0-2]
  • It MUST send PUBREC packets in the order in which the corresponding PUBLISH packets were received (QoS 2 messages)[MQTT-4.6.0-3]
  • It MUST send PUBREL packets in the order in which the corresponding PUBREC packets were received (QoS 2 messages)[MQTT-4.6.0-4]

A Server MUST by default treat each Topic as an "Ordered Topic". It MAY provide an administrative or other mechanism to allow one or more Topics to be treated as an "Unordered Topic"[MQTT-4.6.0-5].

When a Server processes a message that has been published to an Ordered Topic, it MUST follow the rules listed above when delivering messages to each of its subscribers. In addition it MUST send PUBLISH packets to consumers (for the same Topic and QoS) in the order that they were received from any given Client[MQTT-4.6.0-6].

Non normative comment

The rules listed above ensure that when a stream of messages is published and subscribed to with QoS 1, the final copy of each message received by the subscribers will be in the order that they were originally published in, but the possibility of message duplication could result in a re-send of an earlier message being received after one of its successor messages. For example a publisher might send messages in the order 1,2,3,4 and the subscriber might receive them in the order 1,2,3,2,3,4.

If both Client and Server make sure that no more than one message is “in-flight” at any one time (by not sending a message until its predecessor has been acknowledged), then no QoS 1 message will be received after any later one - for example a subscriber might receive them in the order 1,2,3,3,4 but not 1,2,3,2,3,4. Setting an in-flight window of 1 also means that order will be preserved even if the publisher sends a sequence of messages with different QoS levels on the same topic.

4.7 Topic Names and Topic Filters

4.7.1 Topic wildcards

The topic level separator is used to introduce structure into the Topic Name. If present, it divides the Topic Name into multiple “topic levels”.

A subscription’s Topic Filter can contain special wildcard characters, which allow you to subscribe to multiple topics at once.

The wildcard characters can be used in Topic Filters, but MUST NOT be used within a Topic Name [MQTT-4.7.1-1].

Solace Implementation Note

The Solace server allows wildcard characters to be used in Topic Names. However, it will treat them as literal characters with no special meaning.

4.7.1.1 Topic level separator

The forward slash (‘/’ U+002F) is used to separate each level within a topic tree and provide a hierarchical structure to the Topic Names. The use of the topic level separator is significant when either of the two wildcard characters is encountered in Topic Filters specified by subscribing Clients. Topic level separators can appear anywhere in a Topic Filter or Topic Name. Adjacent Topic level separators indicate a zero length topic level.

4.7.1.2 Multi-level wildcard

The number sign (‘#’ U+0023) is a wildcard character that matches any number of levels within a topic. The multi-level wildcard represents the parent and any number of child levels. The multi-level wildcard character MUST be specified either on its own or following a topic level separator. In either case it MUST be the last character specified in the Topic Filter[MQTT-4.7.1-2].

Non normative comment

For example, if a Client subscribes to “sport/tennis/player1/#”, it would receive messages published using these topic names:

  • “sport/tennis/player1”
  • “sport/tennis/player1/ranking”
  • “sport/tennis/player1/score/wimbledon”

Non normative comment

  • “sport/#” also matches the singular “sport”, since # includes the parent level.
  • “#” is valid and will receive every Application Message
  • “sport/tennis/#” is valid
  • “sport/tennis#” is not valid
  • “sport/tennis/#/ranking” is not valid

4.7.1.3 Single level wildcard

The plus sign (‘+’ U+002B) is a wildcard character that matches only one topic level.

The single-level wildcard can be used at any level in the Topic Filter, including first and last levels. Where it is used it MUST occupy an entire level of the filter[MQTT-4.7.1-3]. It can be used at more than one level in the Topic Filter and can be used in conjunction with the multilevel wildcard.

Solace Implementation Note

A Solace server allows the single-level wildcard to be used to do prefix matching within a level in a Topic Filter. For example, “sport/bas+” matches both “sport/basketball” and “sport/baseball”, but not “sport/badminton”. If any string follows the single-level wildcard it is treated as a literal ‘+’ character.

Non normative comment

For example, “sport/tennis/+” matches “sport/tennis/player1” and “sport/tennis/player2”, but not “sport/tennis/player1/ranking”. Also, because the single-level wildcard matches only a single level, “sport/+” does not match “sport” but it does match “sport/”.

Non normative comment

  • “+” is valid
  • “+/tennis/#” is valid
  • “sport+” is not valid
  • “sport/+/player1” is valid                                                                                                                                           
  • “/finance” matches “+/+” and “/+”, but not “+”

4.7.2 Topics beginning with $

The Server MUST NOT match Topic Filters starting with a wildcard character (# or +) with Topic Names beginning with a $ character[MQTT-4.7.2>-1]. The Server SHOULD prevent Clients from using such Topic Names to exchange messages with other Clients. Server implementations MAY use Topic Names that start with a leading $ character for other purposes.

Solace Implementation Note

A Solace server will reject subscriptions beginning with $ unless the server has a defined meaning for the subscription. Refer to Special Solace MQTT Topics for a list of subscriptions beginning with $ that are understood by the Solace server.

Non normative comment

  • $SYS/ has been widely adopted as a prefix to topics that contain Server-specific information or control APIs
  • Applications cannot use a topic with a leading $ character for their own purposes

Non normative comment

  • A subscription to “#” will not receive any messages published to a topic beginning with a $
  • A subscription to “+/monitor/Clients” will not receive any messages published to “$SYS/monitor/Clients”
  • A subscription to “$SYS/#” will receive messages published to topics beginning with “$SYS/”
  • A subscription to “$SYS/monitor/+” will receive messages published to “$SYS/monitor/Clients”
  • For a Client to receive messages from topics that begin with $SYS/ and from topics that don’t begin with a $, it has to subscribe to both “#” and “$SYS/#”

4.7.3 Topic semantic and usage

The following rules apply to Topic Names and Topic Filters:

  • All Topic Names and Topic Filters MUST be at least one character long[MQTT-4.7.3-1]
  • Topic Names and Topic Filters are case sensitive
  • Topic Names and Topic Filters can include the space character
  • A leading or trailing ‘/’ creates a distinct Topic Name or Topic Filter
  • A Topic Name or Topic Filter consisting only of the ‘/’ character is valid 
  • Topic Names and Topic Filters MUST NOT include the null character (Unicode U+0000)[MQTT-4.7.3-2]
  • Topic Names and Topic Filters are UTF-8 encoded strings, they MUST NOT encode to more than 65535 bytes[MQTT-4.7.3-3]. See Section 1.5.3 UTF-8 encoded strings

There is no limit to the number of levels in a Topic Name or Topic Filter, other than that imposed by the overall length of a UTF-8 encoded string.

Solace Implementation Note

Topics must comply with the limits discussed in Solace Message Format Topics.

When it performs subscription matching the Server MUST NOT perform any normalization of Topic Names or Topic Filters, or any modification or substitution of unrecognized characters[MQTT-4.7.3-4]. Each non-wildcarded level in the Topic Filter has to match the corresponding level in the Topic Name character for character for the match to succeed.

Non normative comment

The UTF-8 encoding rules mean that the comparison of Topic Filter and Topic Name could be performed either by comparing the encoded UTF-8 bytes, or by comparing decoded Unicode characters 

Non normative comment

  • “ACCOUNTS” and “Accounts” are two different topic names
  • “Accounts payable” is a valid topic name
  • “/finance” is different from “finance”

An Application Message is sent to each Client Subscription whose Topic Filter matches the Topic Name attached to an Application Message. The topic resource MAY be either predefined in the Server by an administrator or it MAY be dynamically created by the Server when it receives the first subscription or an Application Message with that Topic Name. The Server MAY also use a security component to selectively authorize actions on the topic resource for a given Client.

4.8 Handling errors

Unless stated otherwise, if either the Server or Client encounters a protocol violation, it MUST close the Network Connection on which it received that Control Packet which caused the protocol violation[MQTT-4.8.0-1].

A Client or Server implementation might encounter a Transient Error (for example an internal buffer full condition) that prevents successful processing of an MQTT packet.

If the Client or Server encounters a Transient Error while processing an inbound Control Packet it MUST close the Network Connection on which it received that Control Packet[MQTT-4.8.0-2]. If a Server detects a Transient Error it SHOULD NOT disconnect or have any other effect on its interactions with any other Client.