MQTT Swiftlet
Overview
The MQTT Swiftlet provides MQTT 3.1.1 protocol support for SwiftMQ routers, enabling MQTT clients to connect, publish, and subscribe to topics using the standard protocol. It manages MQTT connections, sessions (including persistent sessions), topic subscriptions, message delivery, and protocol-specific features such as retained messages and QoS handling. The Swiftlet integrates MQTT messaging seamlessly with the SwiftMQ topic and queue infrastructure, translating MQTT topics to SwiftMQ topic names and ensuring reliable delivery and session management.
Features
MQTT Protocol Support (3.1.1)
The Swiftlet implements the MQTT 3.1.1 protocol, supporting all standard message types including CONNECT, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, PINGREQ, PINGRESP, and DISCONNECT. It handles the full MQTT connection lifecycle, including authentication, session establishment, keepalive, and protocol error handling. MQTT topics are translated to SwiftMQ topic names by replacing slashes (/) with dots ('.'). Wildcards in topic filters ('#', '+') are translated to the SwiftMQ % wildcard, with additional validation to ensure compliance with both MQTT and SwiftMQ topic filter rules.
Topic Name Translation
MQTT topic names are mapped to SwiftMQ topic names by replacing / with '.'. Wildcards in topic filters ('#', '+') are mapped to %. The Swiftlet enforces that wildcards are not allowed at the root node and that system topics (starting with $) are not supported.
QoS Handling
All MQTT QoS levels (0, 1, 2) are supported. The Swiftlet manages the full publish/subscribe flow, including message acknowledgments and retransmissions as required by the protocol.
Retained Messages
The Swiftlet implements retained message support as per MQTT specification. Retained messages are stored in-memory and delivered to new subscribers as appropriate. A retained message with a zero-length payload will remove the retained message for the topic.
Connection and Listener Management
The Swiftlet allows configuration of one or more TCP listeners for MQTT clients, each with its own port, bind address, connection template, and optional host access restrictions. Connection templates define socket and buffer parameters, maximum message size, and other network-level properties. Each listener can restrict access to specific hosts or networks using host access lists. The Swiftlet enforces a configurable maximum number of concurrent connections per listener.
Connection Templates
Connection templates define socket factory, TCP options (such as TCP_NODELAY), buffer sizes, idle timeouts, and maximum message size. These templates can be referenced by listeners to standardize connection properties.
Host Access Lists
Each listener can specify a host access list to restrict inbound connections to specific IP addresses or subnets. Host access entries are predicates (typically IP addresses or patterns) that are checked for each incoming connection.
Configuration Example:
<swiftlet name="sys$mqtt">
<listeners>
<listener name="mqtt-default" port="1883" max-connections="100" connection-template="default">
<host-access-list>
<host-access-entry name="192.168.1.%"/>
</host-access-list>
</listener>
</listeners>
</swiftlet>
Session and Subscription Management
The Swiftlet manages both transient and persistent MQTT sessions. Persistent sessions are stored in the internal queue sys$mqtt_sessionstore and survive router restarts. Each session tracks its subscriptions, QoS, and message delivery state. The Swiftlet enforces a session timeout, after which unused persistent sessions are automatically deleted. Subscriptions are mapped to SwiftMQ topic subscriptions, and durable subscriptions are managed for persistent sessions.
Persistent Sessions
When a client connects with cleanSession=false, a persistent session is created or resumed. All subscriptions and undelivered messages are retained for the client. Persistent sessions are stored in the sys$mqtt_sessionstore queue using a JSON-encoded MapMessage format.
Session Timeout
A configurable session timeout (in hours) determines how long unused persistent sessions are kept. Sessions that are not associated with an active connection and have exceeded the timeout are automatically removed.
Subscription Management
Subscriptions are tracked per session. For persistent sessions, durable subscriptions are created and managed. Unsubscribing removes the subscription and, for persistent sessions, updates the session store.
Configuration Example:
<swiftlet name="sys$mqtt" session-timeout="72"/>
Live Usage and Statistics
The Swiftlet provides detailed live usage information for MQTT connections and sessions. For each active connection, statistics such as messages sent/received per second, total messages, client ID, username, and protocol level are tracked. For each session (including persistent sessions), the associated subscriptions and their QoS are displayed. These statistics are updated periodically based on the collect-interval setting.
Collect Interval
The collect-interval property determines how frequently message rate statistics (messages per second) are updated for connections and subscriptions.
Configuration Example:
<swiftlet name="sys$mqtt" collect-interval="5000"/>
Internal Queue Naming
sys$mqtt_sessionstore— Internal queue used to persist MQTT session state for persistent sessions.
Configuration Guide
Restrict MQTT Listener to a Specific Network and Limit Connections
Use this scenario to restrict an MQTT listener to accept connections only from a specific subnet and to limit the number of concurrent client connections.
- Define a listener with the desired port and connection template.
- Set the max-connections attribute to the desired limit.
- Add host-access-list entries for allowed subnets or IP addresses.
<swiftlet name="sys$mqtt">
<listeners>
<listener name="mqtt-secure" port="1883" max-connections="50" connection-template="default">
<host-access-list>
<host-access-entry name="10.0.0.%"/>
</host-access-list>
</listener>
</listeners>
</swiftlet>
Change Session Timeout for Persistent Sessions
Adjust the session-timeout to control how long unused persistent MQTT sessions are retained before automatic removal.
- Set the session-timeout attribute on the sys$mqtt Swiftlet to the desired number of hours.
<swiftlet name="sys$mqtt" session-timeout="24"/>
Configuration Reference
The top-level entity in routerconfig.xml is <swiftlet name="sys$mqtt">.
<swiftlet name="sys$mqtt"> Properties
These properties are attributes of the <swiftlet name="sys$mqtt"> entity.
| Parameter | Type | Default | Mandatory | Reboot Required | Description |
|---|---|---|---|---|---|
collect-interval |
Long | 1000 |
No | No | Collect Interval Messages/Sec |
session-timeout |
Long | 168 |
No | No | Time in hours after which a unused Session is deleted |
<swiftlet name="sys$mqtt" collect-interval="1000" session-timeout="168"/>
<declarations> Entity
Declarations Section
This is a fixed child entity of <swiftlet name="sys$mqtt">.
<swiftlet name="sys$mqtt">
<declarations/>
</swiftlet>
<connection-templates> in <declarations>
Templates for Connections
Each <connection-template> entry is identified by its name attribute (the Connection Template).
| Parameter | Type | Default | Mandatory | Reboot Required | Description |
|---|---|---|---|---|---|
socketfactory-class |
String | com.swiftmq.net.PlainSocketFactory |
No | No | Socketfactory Class |
use-tcp-no-delay |
Boolean | true |
No | No | Use Tcp No Delay |
idle-timeout |
Long | 90000 |
No | No | Inactivity timeout (ms) after which a Connection is disconnected |
max-message-size |
Integer | 10485760 |
No | No | Maximum Message Size (range: 0–2147483647) |
reject-disconnect-delay |
Long | 5000 |
No | No | Time (ms) after which a rejected Connection is closed (min: 1000) |
router-input-buffer-size |
Integer | 131072 |
No | No | Router Network Input Buffer Size (min: 1024) |
router-input-extend-size |
Integer | 65536 |
No | No | Router Network Input Extend Size (min: 1024) |
router-output-buffer-size |
Integer | 131072 |
No | No | Router Network Output Buffer Size (min: 1024) |
router-output-extend-size |
Integer | 65536 |
No | No | Router Network Output Extend Size (min: 1024) |
<swiftlet name="sys$mqtt">
<declarations>
<connection-templates>
<connection-template name="..."/>
</connection-templates>
</declarations>
</swiftlet>
<listeners> in <swiftlet name="sys$mqtt">
Listener Definitions
Each <listener> entry is identified by its name attribute (the Listener).
| Parameter | Type | Default | Mandatory | Reboot Required | Description |
|---|---|---|---|---|---|
bindaddress |
String | — | No | No | Listener Bind IP Address |
port |
Integer | 1883 |
Yes | No | Listener Port |
max-connections |
Integer | -1 |
Yes | No | Maximum Connections for Listener |
connection-template |
String | default |
Yes | No | Connection Template to use |
<swiftlet name="sys$mqtt">
<listeners>
<listener name="..." port="..." max-connections="..." connection-template="..."/>
</listeners>
</swiftlet>
<host-access-list> in <listeners>
Host Access List
Each <host-access-entry> entry is identified by its name attribute (the Host Access Entry).
<swiftlet name="sys$mqtt">
<listeners>
<listener name="...">
<host-access-list>
<host-access-entry name="..."/>
</host-access-list>
</listener>
</listeners>
</swiftlet>
Changelog
13.2.0 (2025-11-03)
- SessionStore: migrated from XStream to JSON