@seriousme/opifex 1.11.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +1 -1
- package/README.md +102 -43
- package/bin/conformanceServer.ts +45 -13
- package/bin/demoServer.ts +38 -13
- package/bin/mqtt.ts +52 -30
- package/client/ConnectionState.ts +2 -0
- package/client/client.ts +57 -47
- package/client/context.ts +75 -21
- package/client/deps.ts +5 -0
- package/client/handlers/handleAuth.test.ts +193 -0
- package/client/handlers/handleAuth.ts +89 -0
- package/client/handlers/handleConnack.test.ts +173 -0
- package/client/handlers/handleConnack.ts +16 -6
- package/client/handlers/handleDisconnect.test.ts +22 -0
- package/client/handlers/handleDisconnect.ts +17 -0
- package/client/handlers/handlePacket.test.ts +242 -0
- package/client/handlers/handlePacket.ts +19 -5
- package/client/handlers/handlePuback.test.ts +99 -0
- package/client/handlers/handlePuback.ts +6 -0
- package/client/handlers/handlePubcomp.test.ts +112 -0
- package/client/handlers/handlePubcomp.ts +5 -0
- package/client/handlers/handlePublish.test.ts +188 -0
- package/client/handlers/handlePubrec.test.ts +119 -0
- package/client/handlers/handlePubrec.ts +5 -1
- package/client/handlers/handlePubrel.test.ts +136 -0
- package/client/handlers/handleSuback.test.ts +122 -0
- package/client/handlers/handleSuback.ts +3 -0
- package/client/handlers/handleUnsuback.test.ts +101 -0
- package/client/mod.ts +2 -2
- package/client/store/memoryStore.ts +2 -2
- package/client/store/store.ts +3 -1
- package/deno/README.md +1 -2
- package/deno/tcpClient.test.ts +75 -0
- package/deno/tcpClient.ts +16 -11
- package/deno/tcpServer.test.ts +22 -21
- package/deno/tcpServer.ts +5 -0
- package/deno/tlsServer.test.ts +97 -0
- package/deno/tlsServer.ts +42 -0
- package/deno/wsServer.test.ts +93 -0
- package/deno/wsServer.ts +73 -0
- package/dev_utils/generateCert.ts +95 -0
- package/dev_utils/mockConn.ts +36 -0
- package/dev_utils/mockServer.ts +28 -0
- package/dev_utils/mod.ts +30 -2
- package/dev_utils/packetHelpers.ts +404 -0
- package/dev_utils/test-handlers.ts +98 -0
- package/dev_utils/timers.ts +14 -0
- package/dev_utils/webStreamPair.test.ts +171 -0
- package/dev_utils/webStreamPair.ts +143 -0
- package/dist/bin/conformanceServer.js +17 -12
- package/dist/bin/conformanceServer.js.map +1 -1
- package/dist/bin/demoServer.js +16 -12
- package/dist/bin/demoServer.js.map +1 -1
- package/dist/bin/mqtt.js +19 -16
- package/dist/bin/mqtt.js.map +1 -1
- package/dist/client/ConnectionState.d.ts +2 -0
- package/dist/client/ConnectionState.d.ts.map +1 -1
- package/dist/client/ConnectionState.js +2 -0
- package/dist/client/ConnectionState.js.map +1 -1
- package/dist/client/client.d.ts +19 -22
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +34 -20
- package/dist/client/client.js.map +1 -1
- package/dist/client/context.d.ts +11 -3
- package/dist/client/context.d.ts.map +1 -1
- package/dist/client/context.js +44 -12
- package/dist/client/context.js.map +1 -1
- package/dist/client/deps.d.ts +3 -2
- package/dist/client/deps.d.ts.map +1 -1
- package/dist/client/deps.js +1 -1
- package/dist/client/deps.js.map +1 -1
- package/dist/client/handlers/handleAuth.d.ts +9 -0
- package/dist/client/handlers/handleAuth.d.ts.map +1 -0
- package/dist/client/handlers/handleAuth.js +66 -0
- package/dist/client/handlers/handleAuth.js.map +1 -0
- package/dist/client/handlers/handleConnack.d.ts +2 -2
- package/dist/client/handlers/handleConnack.d.ts.map +1 -1
- package/dist/client/handlers/handleConnack.js +16 -6
- package/dist/client/handlers/handleConnack.js.map +1 -1
- package/dist/client/handlers/handleDisconnect.d.ts +11 -0
- package/dist/client/handlers/handleDisconnect.d.ts.map +1 -0
- package/dist/client/handlers/handleDisconnect.js +15 -0
- package/dist/client/handlers/handleDisconnect.js.map +1 -0
- package/dist/client/handlers/handlePacket.d.ts.map +1 -1
- package/dist/client/handlers/handlePacket.js +14 -3
- package/dist/client/handlers/handlePacket.js.map +1 -1
- package/dist/client/handlers/handlePuback.d.ts.map +1 -1
- package/dist/client/handlers/handlePuback.js +5 -0
- package/dist/client/handlers/handlePuback.js.map +1 -1
- package/dist/client/handlers/handlePubcomp.d.ts.map +1 -1
- package/dist/client/handlers/handlePubcomp.js +5 -0
- package/dist/client/handlers/handlePubcomp.js.map +1 -1
- package/dist/client/handlers/handlePubrec.d.ts.map +1 -1
- package/dist/client/handlers/handlePubrec.js +5 -1
- package/dist/client/handlers/handlePubrec.js.map +1 -1
- package/dist/client/handlers/handleSuback.d.ts +1 -0
- package/dist/client/handlers/handleSuback.d.ts.map +1 -1
- package/dist/client/handlers/handleSuback.js +3 -0
- package/dist/client/handlers/handleSuback.js.map +1 -1
- package/dist/client/mod.d.ts +2 -2
- package/dist/client/mod.d.ts.map +1 -1
- package/dist/client/mod.js +1 -1
- package/dist/client/mod.js.map +1 -1
- package/dist/client/store/memoryStore.d.ts.map +1 -1
- package/dist/client/store/memoryStore.js +2 -2
- package/dist/client/store/memoryStore.js.map +1 -1
- package/dist/client/store/store.d.ts +2 -1
- package/dist/client/store/store.d.ts.map +1 -1
- package/dist/client/store/store.js +1 -1
- package/dist/client/store/store.js.map +1 -1
- package/dist/dev_utils/generateCert.d.ts +11 -0
- package/dist/dev_utils/generateCert.d.ts.map +1 -0
- package/dist/dev_utils/generateCert.js +76 -0
- package/dist/dev_utils/generateCert.js.map +1 -0
- package/dist/examples/authHandler.test.d.ts +2 -0
- package/dist/examples/authHandler.test.d.ts.map +1 -0
- package/dist/examples/authHandler.test.js +123 -0
- package/dist/examples/authHandler.test.js.map +1 -0
- package/dist/examples/mqtt.test.d.ts +2 -0
- package/dist/examples/mqtt.test.d.ts.map +1 -0
- package/dist/examples/mqtt.test.js +70 -0
- package/dist/examples/mqtt.test.js.map +1 -0
- package/dist/examples/mqtts.test.d.ts +2 -0
- package/dist/examples/mqtts.test.d.ts.map +1 -0
- package/dist/examples/mqtts.test.js +81 -0
- package/dist/examples/mqtts.test.js.map +1 -0
- package/dist/mqttConn/mqttConn.d.ts +25 -16
- package/dist/mqttConn/mqttConn.d.ts.map +1 -1
- package/dist/mqttConn/mqttConn.js +69 -40
- package/dist/mqttConn/mqttConn.js.map +1 -1
- package/dist/mqttPacket/AuthenticationResult.d.ts.map +1 -1
- package/dist/mqttPacket/BitMask.d.ts +12 -11
- package/dist/mqttPacket/BitMask.d.ts.map +1 -1
- package/dist/mqttPacket/BitMask.js +10 -18
- package/dist/mqttPacket/BitMask.js.map +1 -1
- package/dist/mqttPacket/PacketType.d.ts.map +1 -1
- package/dist/mqttPacket/Properties.d.ts +2 -2
- package/dist/mqttPacket/Properties.d.ts.map +1 -1
- package/dist/mqttPacket/Properties.js.map +1 -1
- package/dist/mqttPacket/ReasonCode.d.ts +1 -0
- package/dist/mqttPacket/ReasonCode.d.ts.map +1 -1
- package/dist/mqttPacket/ReasonCode.js +1 -0
- package/dist/mqttPacket/ReasonCode.js.map +1 -1
- package/dist/mqttPacket/RetainHandling.d.ts.map +1 -1
- package/dist/mqttPacket/auth.d.ts +3 -5
- package/dist/mqttPacket/auth.d.ts.map +1 -1
- package/dist/mqttPacket/auth.js +31 -30
- package/dist/mqttPacket/auth.js.map +1 -1
- package/dist/mqttPacket/codec.d.ts +48 -0
- package/dist/mqttPacket/codec.d.ts.map +1 -0
- package/dist/mqttPacket/codec.js +93 -0
- package/dist/mqttPacket/codec.js.map +1 -0
- package/dist/mqttPacket/connack.d.ts +4 -5
- package/dist/mqttPacket/connack.d.ts.map +1 -1
- package/dist/mqttPacket/connack.js +43 -45
- package/dist/mqttPacket/connack.js.map +1 -1
- package/dist/mqttPacket/connect.d.ts +26 -27
- package/dist/mqttPacket/connect.d.ts.map +1 -1
- package/dist/mqttPacket/connect.js +156 -157
- package/dist/mqttPacket/connect.js.map +1 -1
- package/dist/mqttPacket/decoder.d.ts +1 -13
- package/dist/mqttPacket/decoder.d.ts.map +1 -1
- package/dist/mqttPacket/decoder.js +7 -28
- package/dist/mqttPacket/decoder.js.map +1 -1
- package/dist/mqttPacket/disconnect.d.ts +4 -5
- package/dist/mqttPacket/disconnect.d.ts.map +1 -1
- package/dist/mqttPacket/disconnect.js +41 -43
- package/dist/mqttPacket/disconnect.js.map +1 -1
- package/dist/mqttPacket/encoder.d.ts +1 -15
- package/dist/mqttPacket/encoder.d.ts.map +1 -1
- package/dist/mqttPacket/encoder.js +4 -27
- package/dist/mqttPacket/encoder.js.map +1 -1
- package/dist/mqttPacket/length.js +1 -1
- package/dist/mqttPacket/length.js.map +1 -1
- package/dist/mqttPacket/mod.d.ts +21 -103
- package/dist/mqttPacket/mod.d.ts.map +1 -1
- package/dist/mqttPacket/mod.js +5 -94
- package/dist/mqttPacket/mod.js.map +1 -1
- package/dist/mqttPacket/pingreq.d.ts +4 -5
- package/dist/mqttPacket/pingreq.d.ts.map +1 -1
- package/dist/mqttPacket/pingreq.js +11 -13
- package/dist/mqttPacket/pingreq.js.map +1 -1
- package/dist/mqttPacket/pingres.d.ts +4 -5
- package/dist/mqttPacket/pingres.d.ts.map +1 -1
- package/dist/mqttPacket/pingres.js +11 -13
- package/dist/mqttPacket/pingres.js.map +1 -1
- package/dist/mqttPacket/protocolLevels.d.ts +11 -6
- package/dist/mqttPacket/protocolLevels.d.ts.map +1 -1
- package/dist/mqttPacket/protocolLevels.js +5 -1
- package/dist/mqttPacket/protocolLevels.js.map +1 -1
- package/dist/mqttPacket/pubblishAcks.d.ts +9 -10
- package/dist/mqttPacket/pubblishAcks.d.ts.map +1 -1
- package/dist/mqttPacket/pubblishAcks.js +43 -45
- package/dist/mqttPacket/pubblishAcks.js.map +1 -1
- package/dist/mqttPacket/publish.d.ts +14 -14
- package/dist/mqttPacket/publish.d.ts.map +1 -1
- package/dist/mqttPacket/publish.js +53 -55
- package/dist/mqttPacket/publish.js.map +1 -1
- package/dist/mqttPacket/suback.d.ts +4 -5
- package/dist/mqttPacket/suback.d.ts.map +1 -1
- package/dist/mqttPacket/suback.js +38 -40
- package/dist/mqttPacket/suback.js.map +1 -1
- package/dist/mqttPacket/subscribe.d.ts +36 -7
- package/dist/mqttPacket/subscribe.d.ts.map +1 -1
- package/dist/mqttPacket/subscribe.js +90 -89
- package/dist/mqttPacket/subscribe.js.map +1 -1
- package/dist/mqttPacket/types.d.ts +1 -8
- package/dist/mqttPacket/types.d.ts.map +1 -1
- package/dist/mqttPacket/unsuback.d.ts +4 -5
- package/dist/mqttPacket/unsuback.d.ts.map +1 -1
- package/dist/mqttPacket/unsuback.js +32 -34
- package/dist/mqttPacket/unsuback.js.map +1 -1
- package/dist/mqttPacket/unsubscribe.d.ts +23 -6
- package/dist/mqttPacket/unsubscribe.d.ts.map +1 -1
- package/dist/mqttPacket/unsubscribe.js +45 -44
- package/dist/mqttPacket/unsubscribe.js.map +1 -1
- package/dist/mqttPacket/validators.d.ts +4 -16
- package/dist/mqttPacket/validators.d.ts.map +1 -1
- package/dist/mqttPacket/validators.js +5 -26
- package/dist/mqttPacket/validators.js.map +1 -1
- package/dist/node/tcpClient.d.ts +1 -1
- package/dist/node/tcpClient.d.ts.map +1 -1
- package/dist/node/tcpClient.js +12 -7
- package/dist/node/tcpClient.js.map +1 -1
- package/dist/node/tcpServer.d.ts.map +1 -1
- package/dist/node/tcpServer.js +4 -0
- package/dist/node/tcpServer.js.map +1 -1
- package/dist/node/tlsServer.d.ts +19 -0
- package/dist/node/tlsServer.d.ts.map +1 -0
- package/dist/node/tlsServer.js +58 -0
- package/dist/node/tlsServer.js.map +1 -0
- package/dist/node/wrapNodeSocket.d.ts.map +1 -1
- package/dist/node/wrapNodeSocket.js +6 -28
- package/dist/node/wrapNodeSocket.js.map +1 -1
- package/dist/persistence/basicPersistence.d.ts +36 -0
- package/dist/persistence/basicPersistence.d.ts.map +1 -0
- package/dist/persistence/basicPersistence.js +306 -0
- package/dist/persistence/basicPersistence.js.map +1 -0
- package/dist/persistence/deps.d.ts +3 -2
- package/dist/persistence/deps.d.ts.map +1 -1
- package/dist/persistence/deps.js +2 -1
- package/dist/persistence/deps.js.map +1 -1
- package/dist/persistence/memory/memoryPersistence.d.ts +6 -23
- package/dist/persistence/memory/memoryPersistence.d.ts.map +1 -1
- package/dist/persistence/memory/memoryPersistence.js +12 -115
- package/dist/persistence/memory/memoryPersistence.js.map +1 -1
- package/dist/persistence/memory/memoryStorage.d.ts +45 -0
- package/dist/persistence/memory/memoryStorage.d.ts.map +1 -0
- package/dist/persistence/memory/memoryStorage.js +143 -0
- package/dist/persistence/memory/memoryStorage.js.map +1 -0
- package/dist/persistence/mod.d.ts +3 -3
- package/dist/persistence/mod.d.ts.map +1 -1
- package/dist/persistence/mod.js +6 -1
- package/dist/persistence/mod.js.map +1 -1
- package/dist/persistence/persistence.d.ts +44 -69
- package/dist/persistence/persistence.d.ts.map +1 -1
- package/dist/persistence/persistence.js +1 -2
- package/dist/persistence/persistence.js.map +1 -1
- package/dist/persistence/sqlite/sqliteDatabase.d.ts +46 -0
- package/dist/persistence/sqlite/sqliteDatabase.d.ts.map +1 -0
- package/dist/persistence/sqlite/sqliteDatabase.js +215 -0
- package/dist/persistence/sqlite/sqliteDatabase.js.map +1 -0
- package/dist/persistence/sqlite/sqlitePersistence.d.ts +16 -0
- package/dist/persistence/sqlite/sqlitePersistence.d.ts.map +1 -0
- package/dist/persistence/sqlite/sqlitePersistence.js +29 -0
- package/dist/persistence/sqlite/sqlitePersistence.js.map +1 -0
- package/dist/persistence/sqlite/sqliteStorage.d.ts +36 -0
- package/dist/persistence/sqlite/sqliteStorage.d.ts.map +1 -0
- package/dist/persistence/sqlite/sqliteStorage.js +194 -0
- package/dist/persistence/sqlite/sqliteStorage.js.map +1 -0
- package/dist/persistence/storage.d.ts +38 -0
- package/dist/persistence/storage.d.ts.map +1 -0
- package/dist/persistence/storage.js +5 -0
- package/dist/persistence/storage.js.map +1 -0
- package/dist/server/config.d.ts +47 -0
- package/dist/server/config.d.ts.map +1 -0
- package/dist/server/config.js +41 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/context.d.ts +198 -24
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/context.js +432 -53
- package/dist/server/context.js.map +1 -1
- package/dist/server/deps.d.ts +5 -6
- package/dist/server/deps.d.ts.map +1 -1
- package/dist/server/deps.js +2 -2
- package/dist/server/deps.js.map +1 -1
- package/dist/server/handlers/completeConnect.d.ts +8 -0
- package/dist/server/handlers/completeConnect.d.ts.map +1 -0
- package/dist/server/handlers/completeConnect.js +74 -0
- package/dist/server/handlers/completeConnect.js.map +1 -0
- package/dist/server/handlers/handleAuth.d.ts +9 -0
- package/dist/server/handlers/handleAuth.d.ts.map +1 -0
- package/dist/server/handlers/handleAuth.js +69 -0
- package/dist/server/handlers/handleAuth.js.map +1 -0
- package/dist/server/handlers/handleConnect.d.ts +2 -4
- package/dist/server/handlers/handleConnect.d.ts.map +1 -1
- package/dist/server/handlers/handleConnect.js +140 -67
- package/dist/server/handlers/handleConnect.js.map +1 -1
- package/dist/server/handlers/handleDisconnect.d.ts +1 -1
- package/dist/server/handlers/handleDisconnect.d.ts.map +1 -1
- package/dist/server/handlers/handleDisconnect.js +3 -3
- package/dist/server/handlers/handleDisconnect.js.map +1 -1
- package/dist/server/handlers/handlePacket.d.ts.map +1 -1
- package/dist/server/handlers/handlePacket.js +19 -6
- package/dist/server/handlers/handlePacket.js.map +1 -1
- package/dist/server/handlers/handlePuback.d.ts +1 -3
- package/dist/server/handlers/handlePuback.d.ts.map +1 -1
- package/dist/server/handlers/handlePuback.js +2 -8
- package/dist/server/handlers/handlePuback.js.map +1 -1
- package/dist/server/handlers/handlePubcomp.d.ts +1 -1
- package/dist/server/handlers/handlePubcomp.d.ts.map +1 -1
- package/dist/server/handlers/handlePubcomp.js +2 -4
- package/dist/server/handlers/handlePubcomp.js.map +1 -1
- package/dist/server/handlers/handlePublish.d.ts +1 -1
- package/dist/server/handlers/handlePublish.d.ts.map +1 -1
- package/dist/server/handlers/handlePublish.js +149 -45
- package/dist/server/handlers/handlePublish.js.map +1 -1
- package/dist/server/handlers/handlePubrec.d.ts.map +1 -1
- package/dist/server/handlers/handlePubrec.js +2 -3
- package/dist/server/handlers/handlePubrec.js.map +1 -1
- package/dist/server/handlers/handlePubrel.d.ts.map +1 -1
- package/dist/server/handlers/handlePubrel.js +6 -2
- package/dist/server/handlers/handlePubrel.js.map +1 -1
- package/dist/server/handlers/handleSubscribe.d.ts +1 -6
- package/dist/server/handlers/handleSubscribe.d.ts.map +1 -1
- package/dist/server/handlers/handleSubscribe.js +99 -38
- package/dist/server/handlers/handleSubscribe.js.map +1 -1
- package/dist/server/handlers/handleUnsubscribe.d.ts.map +1 -1
- package/dist/server/handlers/handleUnsubscribe.js +19 -4
- package/dist/server/handlers/handleUnsubscribe.js.map +1 -1
- package/dist/server/mod.d.ts +3 -3
- package/dist/server/mod.d.ts.map +1 -1
- package/dist/server/mod.js +1 -1
- package/dist/server/mod.js.map +1 -1
- package/dist/server/server.d.ts +29 -6
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +84 -15
- package/dist/server/server.js.map +1 -1
- package/dist/socket/socket.d.ts +11 -9
- package/dist/socket/socket.d.ts.map +1 -1
- package/dist/socket/socket.js +67 -15
- package/dist/socket/socket.js.map +1 -1
- package/dist/timer/timer.d.ts +32 -0
- package/dist/timer/timer.d.ts.map +1 -1
- package/dist/timer/timer.js +32 -0
- package/dist/timer/timer.js.map +1 -1
- package/dist/trie/trie.d.ts +10 -5
- package/dist/trie/trie.d.ts.map +1 -1
- package/dist/trie/trie.js +47 -17
- package/dist/trie/trie.js.map +1 -1
- package/dist/utils/assert.d.ts.map +1 -1
- package/dist/utils/{BufferedAsyncIterable.d.ts → bufferedAsyncIterable.d.ts} +1 -1
- package/dist/utils/bufferedAsyncIterable.d.ts.map +1 -0
- package/dist/utils/{BufferedAsyncIterable.js → bufferedAsyncIterable.js} +1 -1
- package/dist/utils/bufferedAsyncIterable.js.map +1 -0
- package/dist/utils/deferred.d.ts.map +1 -1
- package/dist/utils/deferred.js.map +1 -1
- package/dist/utils/getOrInsertPolyFill.d.ts +2 -0
- package/dist/utils/getOrInsertPolyFill.d.ts.map +1 -0
- package/dist/utils/getOrInsertPolyFill.js +12 -0
- package/dist/utils/getOrInsertPolyFill.js.map +1 -0
- package/dist/utils/logger.d.ts +40 -3
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +53 -7
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/mod.d.ts +6 -1
- package/dist/utils/mod.d.ts.map +1 -1
- package/dist/utils/mod.js +5 -1
- package/dist/utils/mod.js.map +1 -1
- package/dist/utils/outboundTopicAliasManager.d.ts +52 -0
- package/dist/utils/outboundTopicAliasManager.d.ts.map +1 -0
- package/dist/utils/outboundTopicAliasManager.js +74 -0
- package/dist/utils/outboundTopicAliasManager.js.map +1 -0
- package/dist/utils/queue.d.ts.map +1 -1
- package/dist/utils/topicFilter.d.ts +32 -0
- package/dist/utils/topicFilter.d.ts.map +1 -0
- package/dist/utils/topicFilter.js +52 -0
- package/dist/utils/topicFilter.js.map +1 -0
- package/dist/utils/utils.d.ts +2 -0
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +2 -0
- package/dist/utils/utils.js.map +1 -1
- package/dist/utils/validators.d.ts +34 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +61 -0
- package/dist/utils/validators.js.map +1 -0
- package/dist/web/webSocketStream.d.ts +29 -0
- package/dist/web/webSocketStream.d.ts.map +1 -0
- package/dist/web/webSocketStream.js +69 -0
- package/dist/web/webSocketStream.js.map +1 -0
- package/dist/web/wrapWebSocket.d.ts +12 -0
- package/dist/web/wrapWebSocket.d.ts.map +1 -0
- package/dist/web/wrapWebSocket.js +41 -0
- package/dist/web/wrapWebSocket.js.map +1 -0
- package/dist/web/wsClient.d.ts +7 -0
- package/dist/web/wsClient.d.ts.map +1 -0
- package/dist/web/wsClient.js +22 -0
- package/dist/web/wsClient.js.map +1 -0
- package/dist/web/wsClient.test.d.ts +2 -0
- package/dist/web/wsClient.test.d.ts.map +1 -0
- package/dist/web/wsClient.test.js +20 -0
- package/dist/web/wsClient.test.js.map +1 -0
- package/examples/authHandler.test.ts +164 -0
- package/examples/mqtt.test.ts +89 -0
- package/examples/mqtts.test.ts +100 -0
- package/examples/webSocket.test.ts +94 -0
- package/mqttConn/mqttConn.test.ts +9 -9
- package/mqttConn/mqttConn.ts +91 -49
- package/mqttPacket/BitMask.ts +11 -19
- package/mqttPacket/Properties.ts +6 -3
- package/mqttPacket/ReasonCode.ts +2 -1
- package/mqttPacket/auth.test.ts +1 -1
- package/mqttPacket/auth.ts +41 -48
- package/mqttPacket/codec.ts +146 -0
- package/mqttPacket/connack.ts +57 -68
- package/mqttPacket/connect.test.ts +2 -2
- package/mqttPacket/connect.ts +197 -204
- package/mqttPacket/decoder.test.ts +0 -39
- package/mqttPacket/decoder.ts +9 -36
- package/mqttPacket/disconnect.ts +57 -68
- package/mqttPacket/encoder.ts +5 -40
- package/mqttPacket/length.ts +1 -1
- package/mqttPacket/mod.ts +48 -200
- package/mqttPacket/pingreq.ts +21 -27
- package/mqttPacket/pingres.ts +21 -27
- package/mqttPacket/protocolLevels.ts +12 -7
- package/mqttPacket/pubblishAcks.ts +68 -77
- package/mqttPacket/publish.ts +76 -83
- package/mqttPacket/suback.ts +48 -58
- package/mqttPacket/subscribe.ts +141 -117
- package/mqttPacket/types.ts +1 -9
- package/mqttPacket/unsuback.ts +46 -58
- package/mqttPacket/unsubscribe.ts +74 -63
- package/mqttPacket/validators.ts +5 -31
- package/node/socket-node-stream.test.ts +322 -0
- package/node/socket-node-stream.ts +174 -0
- package/node/tcpClient.test.ts +70 -0
- package/node/tcpClient.ts +13 -12
- package/node/tcpServer.test.ts +24 -20
- package/node/tcpServer.ts +6 -0
- package/node/tlsServer.test.ts +94 -0
- package/node/tlsServer.ts +81 -0
- package/node/wrapNodeSocket.ts +7 -30
- package/package.json +73 -45
- package/persistence/basicPersistence.ts +495 -0
- package/persistence/deps.ts +11 -1
- package/persistence/memory/memoryPersistence.ts +12 -152
- package/persistence/memory/memoryStorage.ts +232 -0
- package/persistence/mod.ts +4 -4
- package/persistence/persistence.test.ts +24 -0
- package/persistence/persistence.testing.ts +1324 -0
- package/persistence/persistence.ts +111 -67
- package/persistence/sqlite/sqliteDatabase.ts +294 -0
- package/persistence/sqlite/sqlitePersistence.test.ts +48 -0
- package/persistence/sqlite/sqlitePersistence.ts +36 -0
- package/persistence/sqlite/sqliteStorage.ts +324 -0
- package/persistence/storage.ts +84 -0
- package/server/config.ts +65 -0
- package/server/context.ts +658 -74
- package/server/deps.ts +25 -5
- package/server/handlers/completeConnect.ts +93 -0
- package/server/handlers/duplicate.test.ts +196 -0
- package/server/handlers/handleAuth.test.ts +225 -0
- package/server/handlers/handleAuth.ts +88 -0
- package/server/handlers/handleConnect.test.ts +589 -0
- package/server/handlers/handleConnect.ts +201 -86
- package/server/handlers/handleConnect.version.test.ts +108 -0
- package/server/handlers/handleDisconnect.test.ts +56 -0
- package/server/handlers/handleDisconnect.ts +3 -3
- package/server/handlers/handlePacket.test.ts +24 -0
- package/server/handlers/handlePacket.ts +30 -8
- package/server/handlers/handlePingreq.test.ts +29 -0
- package/server/handlers/handlePuback.test.ts +28 -0
- package/server/handlers/handlePuback.ts +5 -8
- package/server/handlers/handlePubcomp.test.ts +28 -0
- package/server/handlers/handlePubcomp.ts +5 -4
- package/server/handlers/handlePublish.test.ts +471 -0
- package/server/handlers/handlePublish.ts +189 -35
- package/server/handlers/handlePubrec.test.ts +28 -0
- package/server/handlers/handlePubrec.ts +2 -3
- package/server/handlers/handlePubrel.test.ts +74 -0
- package/server/handlers/handlePubrel.ts +12 -2
- package/server/handlers/handleSubscribe.test.ts +971 -0
- package/server/handlers/handleSubscribe.ts +158 -39
- package/server/handlers/handleUnsubscribe.test.ts +79 -0
- package/server/handlers/handleUnsubscribe.ts +29 -5
- package/server/handlers/keepalive.test.ts +132 -0
- package/server/handlers/session.persistence.test.ts +194 -0
- package/server/handlers/will.delivery.test.ts +221 -0
- package/server/mod.ts +4 -3
- package/server/preconnect.test.ts +151 -0
- package/server/server.ts +115 -17
- package/socket/socket.test.ts +91 -0
- package/socket/socket.ts +81 -31
- package/timer/timer.test.ts +4 -7
- package/timer/timer.ts +36 -0
- package/tools/benchmarks/receiver.ts +51 -0
- package/tools/benchmarks/sender.ts +48 -0
- package/tools/benchmarks/utils.ts +31 -0
- package/tools/mqtt-compat/README.md +130 -0
- package/tools/mqtt-compat/broker.ts +52 -0
- package/tools/mqtt-compat/paho-mqtt4.test.ts +379 -0
- package/tools/mqtt-compat/paho-mqtt5.tests.ts +887 -0
- package/trie/trie.test.ts +9 -1
- package/trie/trie.ts +57 -22
- package/utils/bufferedAsyncIterable.test.ts +92 -0
- package/utils/{BufferedAsyncIterable.ts → bufferedAsyncIterable.ts} +1 -1
- package/utils/deferred.test.ts +36 -0
- package/utils/deferred.ts +0 -1
- package/utils/getOrInsertPolyFill.ts +12 -0
- package/utils/logger.test.ts +189 -0
- package/utils/logger.ts +62 -7
- package/utils/mod.ts +15 -1
- package/utils/outboundTopicAliasManager.ts +100 -0
- package/utils/queue.test.ts +61 -0
- package/utils/topicFilter.test.ts +63 -0
- package/utils/topicFilter.ts +61 -0
- package/utils/utils.ts +3 -0
- package/utils/validators.ts +67 -0
- package/web/webSocketStream.ts +97 -0
- package/web/wrapWebSocket.ts +52 -0
- package/web/wsClient.test.ts +26 -0
- package/web/wsClient.ts +25 -0
- package/benchmarks/receiver.ts +0 -35
- package/benchmarks/sender.ts +0 -32
- package/benchmarks/utils.ts +0 -9
- package/dev_utils/dummyConn.ts +0 -110
- package/dist/persistence/store.d.ts +0 -13
- package/dist/persistence/store.d.ts.map +0 -1
- package/dist/persistence/store.js +0 -2
- package/dist/persistence/store.js.map +0 -1
- package/dist/utils/BufferedAsyncIterable.d.ts.map +0 -1
- package/dist/utils/BufferedAsyncIterable.js.map +0 -1
- package/examples/tcpServer.test.ts +0 -148
- package/persistence/memory/memoryPersistence.test.ts +0 -156
- package/persistence/store.ts +0 -15
- package/server/test/handleConnect.test.ts +0 -130
- package/server/test/test-handlers.ts +0 -53
|
@@ -0,0 +1,887 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import type { AnyPacket, QoS } from "../../server/deps.ts";
|
|
4
|
+
import { logger, LogLevel, PacketType } from "../../server/deps.ts";
|
|
5
|
+
import {
|
|
6
|
+
addMockClient,
|
|
7
|
+
connect5,
|
|
8
|
+
delay,
|
|
9
|
+
disconnect5,
|
|
10
|
+
ping,
|
|
11
|
+
publish5,
|
|
12
|
+
receiveMessages5,
|
|
13
|
+
startMockServer,
|
|
14
|
+
subscribe5,
|
|
15
|
+
unsubscribe5,
|
|
16
|
+
} from "../../dev_utils/mod.ts";
|
|
17
|
+
import type {
|
|
18
|
+
ConnectProperties,
|
|
19
|
+
PublishProperties,
|
|
20
|
+
} from "../../mqttPacket/Properties.ts";
|
|
21
|
+
|
|
22
|
+
const txtEncoder = new TextEncoder();
|
|
23
|
+
logger.level(LogLevel.error);
|
|
24
|
+
|
|
25
|
+
// Global-like state setup matching Python suite
|
|
26
|
+
const topicPrefix = "client_test5/";
|
|
27
|
+
const topics = ["TopicA", "TopicA/B", "Topic/C", "TopicA/C", "/TopicA"].map(
|
|
28
|
+
(t) => topicPrefix + t,
|
|
29
|
+
);
|
|
30
|
+
const wildtopics = ["TopicA/+", "+/C", "#", "/#", "/+", "+/+", "TopicA/#"].map(
|
|
31
|
+
(t) => topicPrefix + t,
|
|
32
|
+
);
|
|
33
|
+
const nosubscribeTopics = ["test/nosubscribe"];
|
|
34
|
+
|
|
35
|
+
// --- Original Tests ---
|
|
36
|
+
|
|
37
|
+
test("Basic Connection and Publish Flow", async () => {
|
|
38
|
+
const { mqttConn } = startMockServer();
|
|
39
|
+
|
|
40
|
+
await connect5(mqttConn, { clientId: "myclientid" });
|
|
41
|
+
await disconnect5(mqttConn);
|
|
42
|
+
|
|
43
|
+
const { mqttConn: mqttConn2, mqttServer } = startMockServer();
|
|
44
|
+
await connect5(mqttConn2, { clientId: "myclientid" });
|
|
45
|
+
|
|
46
|
+
await subscribe5(mqttConn2, [{ topicFilter: topics[0], qos: 2 }]);
|
|
47
|
+
|
|
48
|
+
const mqttConn3 = addMockClient(mqttServer);
|
|
49
|
+
await connect5(mqttConn3, { clientId: "publisher" });
|
|
50
|
+
|
|
51
|
+
await publish5(mqttConn3, topics[0], 0, { payload: "qos 0" });
|
|
52
|
+
await publish5(mqttConn3, topics[0], 1, { payload: "qos 1", id: 1 });
|
|
53
|
+
await publish5(mqttConn3, topics[0], 2, { payload: "qos 2", id: 2 });
|
|
54
|
+
|
|
55
|
+
const messages = await receiveMessages5(mqttConn2);
|
|
56
|
+
assert.strictEqual(messages.length, 3);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("Retained Messages with User Properties", async () => {
|
|
60
|
+
const { mqttConn, mqttServer } = startMockServer();
|
|
61
|
+
|
|
62
|
+
await connect5(mqttConn, { clientId: "myclientid" });
|
|
63
|
+
|
|
64
|
+
const properties: PublishProperties = {
|
|
65
|
+
userProperty: [["a", "2"], ["c", "3"]],
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
await publish5(mqttConn, topics[1], 0, { retain: true, properties });
|
|
69
|
+
await publish5(mqttConn, topics[2], 1, { retain: true, properties, id: 3 });
|
|
70
|
+
await publish5(mqttConn, topics[3], 2, { retain: true, properties, id: 4 });
|
|
71
|
+
|
|
72
|
+
await delay(50);
|
|
73
|
+
|
|
74
|
+
const bConn = addMockClient(mqttServer);
|
|
75
|
+
await connect5(bConn, { clientId: "myclientid2" });
|
|
76
|
+
await subscribe5(bConn, [{ topicFilter: wildtopics[5], qos: 2 }]);
|
|
77
|
+
|
|
78
|
+
const packets: AnyPacket[] = await receiveMessages5(bConn);
|
|
79
|
+
|
|
80
|
+
assert.strictEqual(packets.length, 3);
|
|
81
|
+
assert.strictEqual(
|
|
82
|
+
packets.filter((p) => p.type === PacketType.publish).length,
|
|
83
|
+
3,
|
|
84
|
+
);
|
|
85
|
+
await disconnect5(mqttConn);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test("Will Message Configuration", async () => {
|
|
89
|
+
const { mqttConn: aConn, mqttServer } = startMockServer();
|
|
90
|
+
|
|
91
|
+
await connect5(aConn, {
|
|
92
|
+
clientId: "myclientid",
|
|
93
|
+
clean: true,
|
|
94
|
+
keepAlive: 2,
|
|
95
|
+
will: {
|
|
96
|
+
topic: topics[2],
|
|
97
|
+
payload: txtEncoder.encode("will message"),
|
|
98
|
+
qos: 2,
|
|
99
|
+
retain: false,
|
|
100
|
+
properties: {
|
|
101
|
+
willDelayInterval: 0,
|
|
102
|
+
userProperty: [["a", "2"], ["c", "3"]],
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const bConn = addMockClient(mqttServer);
|
|
108
|
+
await connect5(bConn, { clientId: "myclientid2" });
|
|
109
|
+
await subscribe5(bConn, [{ topicFilter: topics[2], qos: 2 }]);
|
|
110
|
+
|
|
111
|
+
aConn.close();
|
|
112
|
+
|
|
113
|
+
const { value: willPublish } = await bConn.next();
|
|
114
|
+
assert.strictEqual(willPublish.type, PacketType.publish);
|
|
115
|
+
assert.strictEqual(willPublish.topic, topics[2]);
|
|
116
|
+
|
|
117
|
+
await disconnect5(bConn);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("Zero Length Client Identifier Processing", async () => {
|
|
121
|
+
const { mqttConn } = startMockServer();
|
|
122
|
+
|
|
123
|
+
await connect5(mqttConn, { clientId: "" });
|
|
124
|
+
await disconnect5(mqttConn);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test("Offline Message Queueing (Session Expiry)", async () => {
|
|
128
|
+
const { mqttConn: aConn, mqttServer } = startMockServer();
|
|
129
|
+
|
|
130
|
+
await connect5(aConn, {
|
|
131
|
+
clientId: "offlineClient",
|
|
132
|
+
properties: { sessionExpiryInterval: 99999 },
|
|
133
|
+
});
|
|
134
|
+
await subscribe5(aConn, [{ topicFilter: wildtopics[5], qos: 2 }]);
|
|
135
|
+
await disconnect5(aConn);
|
|
136
|
+
|
|
137
|
+
const bConn = addMockClient(mqttServer);
|
|
138
|
+
await connect5(bConn, { clientId: "publisher" });
|
|
139
|
+
await publish5(bConn, topics[1], 0, { payload: "qos 0" });
|
|
140
|
+
await publish5(bConn, topics[2], 1, { payload: "qos 1", id: 10 });
|
|
141
|
+
await publish5(bConn, topics[3], 2, { payload: "qos 2", id: 11 });
|
|
142
|
+
await disconnect5(bConn);
|
|
143
|
+
|
|
144
|
+
const aReconnect = addMockClient(mqttServer);
|
|
145
|
+
await connect5(aReconnect, {
|
|
146
|
+
clientId: "offlineClient",
|
|
147
|
+
clean: false,
|
|
148
|
+
properties: { sessionExpiryInterval: 99999 },
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const packet1 = await aReconnect.next();
|
|
152
|
+
const packet2 = await aReconnect.next();
|
|
153
|
+
assert.strictEqual(packet1.value.type, PacketType.publish);
|
|
154
|
+
assert.strictEqual(packet2.value.type, PacketType.publish);
|
|
155
|
+
|
|
156
|
+
await disconnect5(aReconnect);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test("Shared Subscriptions Delivery Single-Instance Verification", async () => {
|
|
160
|
+
const { mqttConn: aConn, mqttServer } = startMockServer();
|
|
161
|
+
const sharedSubTopic = `$share/sharename/${topicPrefix}x`;
|
|
162
|
+
const sharedPubTopic = `${topicPrefix}x`;
|
|
163
|
+
|
|
164
|
+
await connect5(aConn, { clientId: "clientA" });
|
|
165
|
+
await subscribe5(aConn, [{ topicFilter: sharedSubTopic, qos: 2 }]);
|
|
166
|
+
|
|
167
|
+
const bConn = addMockClient(mqttServer);
|
|
168
|
+
await connect5(bConn, { clientId: "clientB" });
|
|
169
|
+
await subscribe5(bConn, [{ topicFilter: sharedSubTopic, qos: 2 }]);
|
|
170
|
+
|
|
171
|
+
const pConn = addMockClient(mqttServer);
|
|
172
|
+
await connect5(pConn, { clientId: "publisher" });
|
|
173
|
+
await publish5(pConn, sharedPubTopic, 0, { payload: "shared content" });
|
|
174
|
+
|
|
175
|
+
await delay(50);
|
|
176
|
+
|
|
177
|
+
await disconnect5(aConn);
|
|
178
|
+
await disconnect5(bConn);
|
|
179
|
+
await disconnect5(pConn);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// --- Added Missing Tests (from client_test5.py) ---
|
|
183
|
+
|
|
184
|
+
test("Overlapping Subscriptions", async () => {
|
|
185
|
+
const { mqttConn: aConn, mqttServer } = startMockServer();
|
|
186
|
+
await connect5(aConn, { clientId: "overlappingClient" });
|
|
187
|
+
|
|
188
|
+
await subscribe5(aConn, [
|
|
189
|
+
{ topicFilter: wildtopics[6], qos: 2 },
|
|
190
|
+
{ topicFilter: wildtopics[0], qos: 1 },
|
|
191
|
+
]);
|
|
192
|
+
|
|
193
|
+
const publisher = addMockClient(mqttServer);
|
|
194
|
+
await connect5(publisher, { clientId: "publishingClient" });
|
|
195
|
+
await publish5(publisher, topics[3], 2, {
|
|
196
|
+
payload: "overlapping topic filters",
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const { value: msg } = await aConn.next();
|
|
200
|
+
assert.strictEqual(msg.type, PacketType.publish);
|
|
201
|
+
await disconnect5(aConn);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test("Keepalive Timeout Triggering Will Message", async () => {
|
|
205
|
+
const { mqttConn: aConn, mqttServer } = startMockServer();
|
|
206
|
+
// set server keepalive small to speed up test
|
|
207
|
+
mqttServer.configuration.context.serverKeepAlive = 2;
|
|
208
|
+
|
|
209
|
+
await connect5(aConn, {
|
|
210
|
+
clientId: "keepaliveClient",
|
|
211
|
+
clean: true,
|
|
212
|
+
keepAlive: 1,
|
|
213
|
+
will: {
|
|
214
|
+
topic: topics[4],
|
|
215
|
+
payload: txtEncoder.encode("keepalive expiry"),
|
|
216
|
+
qos: 2,
|
|
217
|
+
retain: false,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const bConn = addMockClient(mqttServer);
|
|
222
|
+
await connect5(bConn, { clientId: "watcherClient" });
|
|
223
|
+
await subscribe5(bConn, [{ topicFilter: topics[4], qos: 2 }]);
|
|
224
|
+
|
|
225
|
+
// Wait for keepalive timeout on client A
|
|
226
|
+
await delay(2000);
|
|
227
|
+
|
|
228
|
+
const { value: willPublish } = await bConn.next();
|
|
229
|
+
assert.strictEqual(willPublish.type, PacketType.publish);
|
|
230
|
+
assert.strictEqual(willPublish.topic, topics[4]);
|
|
231
|
+
|
|
232
|
+
await disconnect5(bConn);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test("Redelivery on Reconnect", async () => {
|
|
236
|
+
const { mqttConn: bConn, mqttServer } = startMockServer();
|
|
237
|
+
const connProps: ConnectProperties = { sessionExpiryInterval: 99999 };
|
|
238
|
+
|
|
239
|
+
await connect5(bConn, {
|
|
240
|
+
clientId: "redeliverClient",
|
|
241
|
+
clean: false,
|
|
242
|
+
properties: connProps,
|
|
243
|
+
});
|
|
244
|
+
await subscribe5(bConn, [{ topicFilter: wildtopics[6], qos: 2 }]);
|
|
245
|
+
|
|
246
|
+
const publisher = addMockClient(mqttServer);
|
|
247
|
+
await connect5(publisher, { clientId: "publisher" });
|
|
248
|
+
await publish5(publisher, topics[1], 1, {
|
|
249
|
+
payload: "unacked qos 1",
|
|
250
|
+
id: 100,
|
|
251
|
+
});
|
|
252
|
+
await publish5(publisher, topics[3], 2, {
|
|
253
|
+
payload: "unacked qos 2",
|
|
254
|
+
id: 101,
|
|
255
|
+
});
|
|
256
|
+
await disconnect5(publisher);
|
|
257
|
+
bConn.close();
|
|
258
|
+
|
|
259
|
+
// Reconnect and verify redelivery
|
|
260
|
+
const bReconnect = addMockClient(mqttServer);
|
|
261
|
+
await connect5(bReconnect, {
|
|
262
|
+
clientId: "redeliverClient",
|
|
263
|
+
clean: false,
|
|
264
|
+
properties: connProps,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
const msg1 = await bReconnect.next();
|
|
268
|
+
const msg2 = await bReconnect.next();
|
|
269
|
+
assert.strictEqual(msg1.value.type, PacketType.publish);
|
|
270
|
+
assert.strictEqual(msg2.value.type, PacketType.publish);
|
|
271
|
+
|
|
272
|
+
await disconnect5(bReconnect);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
test("Subscribe Failure (Reason Code 0x80)", async () => {
|
|
276
|
+
const { mqttConn } = startMockServer();
|
|
277
|
+
await connect5(mqttConn, { clientId: "subFailClient" });
|
|
278
|
+
|
|
279
|
+
const suback = await subscribe5(mqttConn, [{
|
|
280
|
+
topicFilter: nosubscribeTopics[0],
|
|
281
|
+
qos: 2,
|
|
282
|
+
}]);
|
|
283
|
+
assert.strictEqual(suback.type, PacketType.suback);
|
|
284
|
+
|
|
285
|
+
await disconnect5(mqttConn);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
test("Dollar ($) Topics Wildcard Isolation", async () => {
|
|
289
|
+
const { mqttConn, mqttServer } = startMockServer();
|
|
290
|
+
|
|
291
|
+
await connect5(mqttConn, { clientId: "dollarSubscriber" });
|
|
292
|
+
await subscribe5(mqttConn, [{ topicFilter: wildtopics[5], qos: 2 }]);
|
|
293
|
+
|
|
294
|
+
const pConn = addMockClient(mqttServer);
|
|
295
|
+
await connect5(pConn, { clientId: "dollarPublisher" });
|
|
296
|
+
await publish5(pConn, "$" + topics[1], 1, {
|
|
297
|
+
payload: "dollar topic payload",
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
await delay(50);
|
|
301
|
+
await disconnect5(mqttConn);
|
|
302
|
+
await disconnect5(pConn);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
test("Unsubscribe Topics Flow", async () => {
|
|
306
|
+
const { mqttConn: bConn, mqttServer } = startMockServer();
|
|
307
|
+
|
|
308
|
+
await connect5(bConn, { clientId: "unsubClient" });
|
|
309
|
+
await subscribe5(bConn, [
|
|
310
|
+
{ topicFilter: topics[0], qos: 2 },
|
|
311
|
+
{ topicFilter: topics[1], qos: 2 },
|
|
312
|
+
{ topicFilter: topics[2], qos: 2 },
|
|
313
|
+
]);
|
|
314
|
+
|
|
315
|
+
await unsubscribe5(bConn, [topics[0]]);
|
|
316
|
+
|
|
317
|
+
const aConn = addMockClient(mqttServer);
|
|
318
|
+
await connect5(aConn, { clientId: "unsubPub" });
|
|
319
|
+
await publish5(aConn, topics[0], 1, { payload: "unsubscribed topic" });
|
|
320
|
+
await publish5(aConn, topics[1], 1, { payload: "active topic 1" });
|
|
321
|
+
await publish5(aConn, topics[2], 1, { payload: "active topic 2" });
|
|
322
|
+
|
|
323
|
+
const messages = await receiveMessages5(bConn);
|
|
324
|
+
assert.strictEqual(messages.length, 2);
|
|
325
|
+
await disconnect5(aConn);
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
test("Session Expiry Lifecycle and Reconnection", async () => {
|
|
329
|
+
const { mqttConn } = startMockServer();
|
|
330
|
+
|
|
331
|
+
// 1. Session Expiry = 0 (Immediate expiry)
|
|
332
|
+
await connect5(mqttConn, {
|
|
333
|
+
clientId: "expiryClient",
|
|
334
|
+
clean: true,
|
|
335
|
+
properties: { sessionExpiryInterval: 0 },
|
|
336
|
+
});
|
|
337
|
+
await subscribe5(mqttConn, [{ topicFilter: topics[0], qos: 2 }]);
|
|
338
|
+
await disconnect5(mqttConn);
|
|
339
|
+
|
|
340
|
+
// Reconnect clean=false -> session should not be present
|
|
341
|
+
const { mqttConn: conn2 } = startMockServer();
|
|
342
|
+
const connack2 = await connect5(conn2, {
|
|
343
|
+
clientId: "expiryClient",
|
|
344
|
+
clean: false,
|
|
345
|
+
properties: { sessionExpiryInterval: 0 },
|
|
346
|
+
});
|
|
347
|
+
assert.strictEqual(connack2.sessionPresent, false);
|
|
348
|
+
await disconnect5(conn2);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
test("User Properties in Publish Packets", async () => {
|
|
352
|
+
const { mqttConn, mqttServer } = startMockServer();
|
|
353
|
+
|
|
354
|
+
await connect5(mqttConn, { clientId: "userPropSub" });
|
|
355
|
+
await subscribe5(mqttConn, [{ topicFilter: topics[0], qos: 2 }]);
|
|
356
|
+
|
|
357
|
+
const pConn = addMockClient(mqttServer);
|
|
358
|
+
await connect5(pConn, { clientId: "userPropPub" });
|
|
359
|
+
|
|
360
|
+
const userProps: PublishProperties = {
|
|
361
|
+
userProperty: [["a", "2"], ["c", "3"]],
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
await publish5(pConn, topics[0], 0, { properties: userProps });
|
|
365
|
+
await publish5(pConn, topics[0], 1, { properties: userProps, id: 1 });
|
|
366
|
+
await publish5(pConn, topics[0], 2, { properties: userProps, id: 2 });
|
|
367
|
+
|
|
368
|
+
const messages = await receiveMessages5(mqttConn);
|
|
369
|
+
assert.strictEqual(messages.length, 3);
|
|
370
|
+
await disconnect5(pConn);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
test("Payload Format Indicator and Content Type", async () => {
|
|
374
|
+
const { mqttConn, mqttServer } = startMockServer();
|
|
375
|
+
|
|
376
|
+
await connect5(mqttConn, { clientId: "payloadFormatSub" });
|
|
377
|
+
await subscribe5(mqttConn, [{ topicFilter: topics[0], qos: 2 }]);
|
|
378
|
+
|
|
379
|
+
const pConn = addMockClient(mqttServer);
|
|
380
|
+
await connect5(pConn, { clientId: "payloadFormatPub" });
|
|
381
|
+
|
|
382
|
+
const props: PublishProperties = {
|
|
383
|
+
payloadFormatIndicator: true,
|
|
384
|
+
contentType: "application/json",
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
await publish5(pConn, topics[0], 1, {
|
|
388
|
+
payload: '{"key":"value"}',
|
|
389
|
+
properties: props,
|
|
390
|
+
id: 10,
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
const { value: pubMsg } = await mqttConn.next();
|
|
394
|
+
assert.strictEqual(pubMsg.type, PacketType.publish);
|
|
395
|
+
assert.strictEqual(pubMsg.properties?.payloadFormatIndicator, true);
|
|
396
|
+
assert.strictEqual(pubMsg.properties?.contentType, "application/json");
|
|
397
|
+
|
|
398
|
+
await disconnect5(mqttConn);
|
|
399
|
+
await disconnect5(pConn);
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
test("Publication Message Expiry Interval", async () => {
|
|
403
|
+
const { mqttConn: bConn, mqttServer } = startMockServer();
|
|
404
|
+
|
|
405
|
+
await connect5(bConn, {
|
|
406
|
+
clientId: "pubExpirySub",
|
|
407
|
+
clean: true,
|
|
408
|
+
properties: { sessionExpiryInterval: 99999 },
|
|
409
|
+
});
|
|
410
|
+
await subscribe5(bConn, [{ topicFilter: topics[0], qos: 2 }]);
|
|
411
|
+
await disconnect5(bConn, { properties: { sessionExpiryInterval: 99999 } });
|
|
412
|
+
|
|
413
|
+
const aConn = addMockClient(mqttServer);
|
|
414
|
+
await connect5(aConn, { clientId: "pubExpiryPub" });
|
|
415
|
+
|
|
416
|
+
await publish5(aConn, topics[0], 1, {
|
|
417
|
+
payload: "expired message",
|
|
418
|
+
properties: { messageExpiryInterval: 1 },
|
|
419
|
+
id: 1,
|
|
420
|
+
});
|
|
421
|
+
await publish5(aConn, topics[0], 1, {
|
|
422
|
+
payload: "valid message",
|
|
423
|
+
properties: { messageExpiryInterval: 60 },
|
|
424
|
+
id: 2,
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
await delay(1500); // Allow first message to expire
|
|
428
|
+
|
|
429
|
+
const bReconnect = addMockClient(mqttServer);
|
|
430
|
+
await connect5(bReconnect, { clientId: "pubExpirySub", clean: false });
|
|
431
|
+
|
|
432
|
+
const { value: recMsg } = await bReconnect.next();
|
|
433
|
+
assert.strictEqual(recMsg.type, PacketType.publish);
|
|
434
|
+
assert.deepEqual(recMsg.payload, txtEncoder.encode("valid message"));
|
|
435
|
+
|
|
436
|
+
await disconnect5(aConn);
|
|
437
|
+
await disconnect5(bReconnect);
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
test("Subscribe Options (noLocal, retainAsPublished, retainHandling)", async () => {
|
|
441
|
+
const { mqttConn: aConn, mqttServer } = startMockServer();
|
|
442
|
+
|
|
443
|
+
// --- 1. Test noLocal ---
|
|
444
|
+
await connect5(aConn, { clientId: "clientA" });
|
|
445
|
+
await subscribe5(aConn, [{ topicFilter: topics[0], qos: 2, noLocal: true }]);
|
|
446
|
+
|
|
447
|
+
const bConn = addMockClient(mqttServer);
|
|
448
|
+
await connect5(bConn, { clientId: "clientB" });
|
|
449
|
+
await subscribe5(bConn, [{ topicFilter: topics[0], qos: 2, noLocal: true }]);
|
|
450
|
+
|
|
451
|
+
// Client A publishes; should not receive its own message due to noLocal, but Client B should
|
|
452
|
+
await publish5(aConn, topics[0], 1, { payload: "noLocal test", id: 1 });
|
|
453
|
+
|
|
454
|
+
const { value: bMsg } = await bConn.next();
|
|
455
|
+
assert.strictEqual(bMsg.type, PacketType.publish);
|
|
456
|
+
assert.deepEqual(bMsg.payload, txtEncoder.encode("noLocal test"));
|
|
457
|
+
|
|
458
|
+
await disconnect5(aConn);
|
|
459
|
+
await disconnect5(bConn);
|
|
460
|
+
|
|
461
|
+
// --- 2. Test retainAsPublished ---
|
|
462
|
+
const { mqttConn: connRetain, mqttServer: mqttServer2 } = startMockServer();
|
|
463
|
+
await connect5(connRetain, { clientId: "retainAsPublishedClient" });
|
|
464
|
+
await subscribe5(connRetain, [{
|
|
465
|
+
topicFilter: topics[0],
|
|
466
|
+
qos: 2,
|
|
467
|
+
retainAsPublished: true,
|
|
468
|
+
}]);
|
|
469
|
+
|
|
470
|
+
const retainPublish = addMockClient(mqttServer2);
|
|
471
|
+
await connect5(retainPublish);
|
|
472
|
+
await publish5(retainPublish, topics[0], 1, {
|
|
473
|
+
payload: "retain false",
|
|
474
|
+
retain: false,
|
|
475
|
+
id: 2,
|
|
476
|
+
});
|
|
477
|
+
await publish5(retainPublish, topics[0], 1, {
|
|
478
|
+
payload: "retain true",
|
|
479
|
+
retain: true,
|
|
480
|
+
id: 3,
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
const { value: msg1 } = await connRetain.next();
|
|
484
|
+
const { value: msg2 } = await connRetain.next();
|
|
485
|
+
|
|
486
|
+
assert.strictEqual(msg1.retain, false);
|
|
487
|
+
assert.strictEqual(msg2.retain, true);
|
|
488
|
+
|
|
489
|
+
await disconnect5(connRetain);
|
|
490
|
+
await disconnect5(retainPublish);
|
|
491
|
+
|
|
492
|
+
// --- 3. Test retainHandling ---
|
|
493
|
+
// Clean start & prepare some retained messages via Client A
|
|
494
|
+
const { mqttConn: publisherConn, mqttServer: retainServer } =
|
|
495
|
+
startMockServer();
|
|
496
|
+
await connect5(publisherConn, { clientId: "retainPublisher" });
|
|
497
|
+
await publish5(publisherConn, topics[1], 0, {
|
|
498
|
+
payload: "qos 0",
|
|
499
|
+
retain: true,
|
|
500
|
+
});
|
|
501
|
+
await publish5(publisherConn, topics[2], 1, {
|
|
502
|
+
payload: "qos 1",
|
|
503
|
+
retain: true,
|
|
504
|
+
id: 4,
|
|
505
|
+
});
|
|
506
|
+
await publish5(publisherConn, topics[3], 2, {
|
|
507
|
+
payload: "qos 2",
|
|
508
|
+
retain: true,
|
|
509
|
+
id: 5,
|
|
510
|
+
});
|
|
511
|
+
await delay(50);
|
|
512
|
+
|
|
513
|
+
// retainHandling = 1 (send retained messages only on NEW subscription)
|
|
514
|
+
const subscriberConn = addMockClient(retainServer);
|
|
515
|
+
await connect5(subscriberConn, { clientId: "retainHandlerClient" });
|
|
516
|
+
|
|
517
|
+
// 1st subscription -> messages should arrive
|
|
518
|
+
await subscribe5(subscriberConn, [{
|
|
519
|
+
topicFilter: wildtopics[5],
|
|
520
|
+
qos: 2,
|
|
521
|
+
retainHandling: 1,
|
|
522
|
+
}]);
|
|
523
|
+
const r1 = await subscriberConn.next();
|
|
524
|
+
const r2 = await subscriberConn.next();
|
|
525
|
+
const r3 = await subscriberConn.next();
|
|
526
|
+
assert.strictEqual(r1.value.type, PacketType.publish);
|
|
527
|
+
assert.strictEqual(r2.value.type, PacketType.publish);
|
|
528
|
+
assert.strictEqual(r3.value.type, PacketType.publish);
|
|
529
|
+
|
|
530
|
+
// 2nd subscription to the same filter -> retainHandling=1 ensures they are NOT re-sent
|
|
531
|
+
await subscribe5(subscriberConn, [{
|
|
532
|
+
topicFilter: wildtopics[5],
|
|
533
|
+
qos: 2,
|
|
534
|
+
retainHandling: 1,
|
|
535
|
+
}]);
|
|
536
|
+
await delay(100);
|
|
537
|
+
|
|
538
|
+
// retainHandling = 2 (NEVER send retained messages on subscribe)
|
|
539
|
+
await subscribe5(subscriberConn, [{
|
|
540
|
+
topicFilter: wildtopics[5],
|
|
541
|
+
qos: 2,
|
|
542
|
+
retainHandling: 2,
|
|
543
|
+
}]);
|
|
544
|
+
await delay(100);
|
|
545
|
+
|
|
546
|
+
await disconnect5(publisherConn);
|
|
547
|
+
await disconnect5(subscriberConn);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
test("Assigned Client Identifier", async () => {
|
|
551
|
+
const { mqttConn } = startMockServer();
|
|
552
|
+
|
|
553
|
+
// Send a CONNECT packet with an empty clientId
|
|
554
|
+
const connack = await connect5(mqttConn, { clientId: "" });
|
|
555
|
+
|
|
556
|
+
assert.strictEqual(connack.type, PacketType.connack);
|
|
557
|
+
// The broker must return an AssignedClientIdentifier in properties
|
|
558
|
+
assert.ok(connack.properties?.assignedClientIdentifier);
|
|
559
|
+
assert.notStrictEqual(connack.properties.assignedClientIdentifier, "");
|
|
560
|
+
|
|
561
|
+
await disconnect5(mqttConn);
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
test("Subscribe Identifiers", async () => {
|
|
565
|
+
const { mqttConn: aConn, mqttServer } = startMockServer();
|
|
566
|
+
|
|
567
|
+
await connect5(aConn, { clientId: "subIdClientA" });
|
|
568
|
+
await subscribe5(
|
|
569
|
+
aConn,
|
|
570
|
+
[{ topicFilter: topics[0], qos: 2 }],
|
|
571
|
+
{ subscriptionIdentifier: 456789 },
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
const bConn = addMockClient(mqttServer);
|
|
575
|
+
await connect5(bConn, { clientId: "subIdClientB" });
|
|
576
|
+
await subscribe5(
|
|
577
|
+
bConn,
|
|
578
|
+
[{ topicFilter: topics[0], qos: 2 }],
|
|
579
|
+
{ subscriptionIdentifier: 2 },
|
|
580
|
+
);
|
|
581
|
+
await subscribe5(
|
|
582
|
+
bConn,
|
|
583
|
+
[{ topicFilter: topics[0] + "/#", qos: 2 }],
|
|
584
|
+
{ subscriptionIdentifier: 3 },
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
const publisher = addMockClient(mqttServer);
|
|
588
|
+
await connect5(publisher);
|
|
589
|
+
await publish5(publisher, topics[0], 1, {
|
|
590
|
+
payload: "sub identifier test",
|
|
591
|
+
id: 1,
|
|
592
|
+
});
|
|
593
|
+
await disconnect5(publisher);
|
|
594
|
+
|
|
595
|
+
const { value: msgA } = await aConn.next();
|
|
596
|
+
assert.strictEqual(msgA.type, PacketType.publish);
|
|
597
|
+
assert.deepStrictEqual(msgA.properties?.subscriptionIdentifiers, [456789]);
|
|
598
|
+
|
|
599
|
+
const { value: msgB } = await bConn.next();
|
|
600
|
+
assert.strictEqual(msgB.type, PacketType.publish);
|
|
601
|
+
// For multiple matching subscription IDs, expect them as an array/set
|
|
602
|
+
const subIds = msgB.properties?.subscriptionIdentifiers;
|
|
603
|
+
assert.deepStrictEqual(new Set(subIds), new Set([2, 3]));
|
|
604
|
+
|
|
605
|
+
await disconnect5(aConn);
|
|
606
|
+
await disconnect5(bConn);
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
test("Request Response Pattern", async () => {
|
|
610
|
+
const { mqttConn: aConn, mqttServer } = startMockServer();
|
|
611
|
+
|
|
612
|
+
await connect5(aConn, { clientId: "requester" });
|
|
613
|
+
const bConn = addMockClient(mqttServer);
|
|
614
|
+
await connect5(bConn, { clientId: "responder" });
|
|
615
|
+
|
|
616
|
+
await subscribe5(aConn, [{ topicFilter: topics[1], qos: 2 }]);
|
|
617
|
+
await subscribe5(bConn, [{ topicFilter: topics[0], qos: 2 }]);
|
|
618
|
+
|
|
619
|
+
const reqProps: PublishProperties = {
|
|
620
|
+
responseTopic: topics[1],
|
|
621
|
+
correlationData: txtEncoder.encode("334"),
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
// Requester sends a request
|
|
625
|
+
await publish5(aConn, topics[0], 1, {
|
|
626
|
+
payload: "request",
|
|
627
|
+
properties: reqProps,
|
|
628
|
+
id: 1,
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
// Responder receives the request
|
|
632
|
+
const { value: reqMsg } = await bConn.next();
|
|
633
|
+
assert.strictEqual(reqMsg.type, PacketType.publish);
|
|
634
|
+
assert.strictEqual(reqMsg.properties?.responseTopic, topics[1]);
|
|
635
|
+
|
|
636
|
+
// Responder sends a response back to responseTopic using correlationData
|
|
637
|
+
await publish5(bConn, reqMsg.properties.responseTopic, 1, {
|
|
638
|
+
payload: "response",
|
|
639
|
+
properties: { correlationData: reqMsg.properties.correlationData },
|
|
640
|
+
id: 2,
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
// Requester receives the response
|
|
644
|
+
const { value: respMsg } = await aConn.next();
|
|
645
|
+
assert.strictEqual(respMsg.type, PacketType.publish);
|
|
646
|
+
assert.deepEqual(respMsg.payload, txtEncoder.encode("response"));
|
|
647
|
+
|
|
648
|
+
await disconnect5(aConn);
|
|
649
|
+
await disconnect5(bConn);
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
test("Client Topic Alias", async () => {
|
|
653
|
+
const { mqttConn } = startMockServer();
|
|
654
|
+
|
|
655
|
+
// Test 1: Topic Alias 0 is invalid and must trigger a disconnect
|
|
656
|
+
await connect5(mqttConn);
|
|
657
|
+
await publish5(mqttConn, topics[0], 1, {
|
|
658
|
+
id: 1,
|
|
659
|
+
payload: "invalid alias 0",
|
|
660
|
+
properties: { topicAlias: 0 },
|
|
661
|
+
checkAcks: false,
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
const { value: disc1 } = await mqttConn.next();
|
|
665
|
+
assert.strictEqual(disc1.type, PacketType.disconnect);
|
|
666
|
+
|
|
667
|
+
// Test 2: Valid Topic Alias usage
|
|
668
|
+
const { mqttConn: publisher, mqttServer } = startMockServer();
|
|
669
|
+
const connack = await connect5(publisher, {
|
|
670
|
+
clientId: "publisher",
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
if ((connack.properties?.topicAliasMaximum ?? 0) > 0) {
|
|
674
|
+
const subscriber = addMockClient(mqttServer);
|
|
675
|
+
await connect5(subscriber, { clientId: "topicAliasClient" });
|
|
676
|
+
await subscribe5(subscriber, [{ topicFilter: topics[0], qos: 2 }]);
|
|
677
|
+
|
|
678
|
+
// First message sets up the alias mapping
|
|
679
|
+
await publish5(publisher, topics[0], 1, {
|
|
680
|
+
payload: "alias mapping",
|
|
681
|
+
properties: { topicAlias: 1 },
|
|
682
|
+
id: 2,
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
// Subsequent message uses an empty topic string with the existing alias
|
|
686
|
+
await publish5(publisher, "", 1, {
|
|
687
|
+
payload: "using alias",
|
|
688
|
+
properties: { topicAlias: 1 },
|
|
689
|
+
id: 3,
|
|
690
|
+
});
|
|
691
|
+
const results = await receiveMessages5(subscriber);
|
|
692
|
+
assert.strictEqual(results.length, 2);
|
|
693
|
+
assert.strictEqual(results[0].type, PacketType.publish);
|
|
694
|
+
assert.strictEqual(results[1].type, PacketType.publish);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
await disconnect5(publisher);
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
test("Server Topic Alias", async () => {
|
|
701
|
+
const { mqttConn: subscriber, mqttServer } = startMockServer();
|
|
702
|
+
const publisher = addMockClient(mqttServer);
|
|
703
|
+
|
|
704
|
+
// Client indicates support for server topic aliases (max 1)
|
|
705
|
+
await connect5(subscriber, {
|
|
706
|
+
clientId: "serverTopicAliasClient",
|
|
707
|
+
properties: { topicAliasMaximum: 1 },
|
|
708
|
+
});
|
|
709
|
+
await subscribe5(subscriber, [{ topicFilter: topics[0], qos: 2 }]);
|
|
710
|
+
|
|
711
|
+
await connect5(publisher, {
|
|
712
|
+
clientId: "publisher",
|
|
713
|
+
});
|
|
714
|
+
for (let qos = 0; qos < 3; qos++) {
|
|
715
|
+
await publish5(publisher, topics[0], qos as QoS, {
|
|
716
|
+
payload: `msg qos ${qos}`,
|
|
717
|
+
id: qos || undefined,
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// First received message establishes the alias on the client
|
|
722
|
+
const { value: msg1 } = await subscriber.next();
|
|
723
|
+
assert.strictEqual(msg1.type, PacketType.publish);
|
|
724
|
+
assert.ok(msg1.properties?.topicAlias);
|
|
725
|
+
assert.strictEqual(msg1.topic, topics[0]);
|
|
726
|
+
|
|
727
|
+
// Subsequent messages use the alias and may contain an empty topic string
|
|
728
|
+
const { value: msg2 } = await subscriber.next();
|
|
729
|
+
assert.strictEqual(msg2.type, PacketType.publish);
|
|
730
|
+
assert.strictEqual(msg2.properties?.topicAlias, msg1.properties.topicAlias);
|
|
731
|
+
|
|
732
|
+
await disconnect5(publisher);
|
|
733
|
+
await disconnect5(subscriber);
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
test("Maximum Packet Size Handling", async () => {
|
|
737
|
+
const { mqttConn: subscriber, mqttServer } = startMockServer();
|
|
738
|
+
const publisher = addMockClient(mqttServer);
|
|
739
|
+
const maxPacketSize = 64;
|
|
740
|
+
|
|
741
|
+
await connect5(subscriber, {
|
|
742
|
+
clientId: "maxPacketClient",
|
|
743
|
+
properties: { maximumPacketSize: maxPacketSize },
|
|
744
|
+
});
|
|
745
|
+
await subscribe5(subscriber, [{ topicFilter: topics[0], qos: 2 }]);
|
|
746
|
+
|
|
747
|
+
await connect5(publisher, {
|
|
748
|
+
clientId: "publisher",
|
|
749
|
+
});
|
|
750
|
+
// Messages smaller than maximum packet size should be processed normally
|
|
751
|
+
const smallPayload = "a".repeat(Math.floor(maxPacketSize / 2));
|
|
752
|
+
await publish5(publisher, topics[0], 0, { payload: smallPayload });
|
|
753
|
+
|
|
754
|
+
const { value: smallMsg } = await subscriber.next();
|
|
755
|
+
assert.strictEqual(smallMsg.type, PacketType.publish);
|
|
756
|
+
|
|
757
|
+
// Messages exceeding MaximumPacketSize must not be delivered
|
|
758
|
+
const hugePayload = "a".repeat(maxPacketSize * 2);
|
|
759
|
+
await publish5(publisher, topics[0], 1, { payload: hugePayload, id: 10 });
|
|
760
|
+
|
|
761
|
+
// run ping to ensure no other packet was delivered
|
|
762
|
+
await ping(subscriber);
|
|
763
|
+
await disconnect5(subscriber);
|
|
764
|
+
await disconnect5(publisher);
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
test("Server Keep Alive Enforcement", async () => {
|
|
768
|
+
const { mqttConn } = startMockServer({
|
|
769
|
+
configuration: { context: { serverKeepAlive: 60 } },
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
// Request a keepAlive of 120 seconds
|
|
773
|
+
const connack = await connect5(mqttConn, {
|
|
774
|
+
clientId: "keepAliveClient",
|
|
775
|
+
keepAlive: 120,
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
// Verify the server enforces a ServerKeepAlive (e.g., 60 seconds)
|
|
779
|
+
assert.ok(connack.properties?.serverKeepAlive !== undefined);
|
|
780
|
+
assert.strictEqual(connack.properties.serverKeepAlive, 60);
|
|
781
|
+
|
|
782
|
+
await disconnect5(mqttConn);
|
|
783
|
+
});
|
|
784
|
+
|
|
785
|
+
test("Flow Control - Client Receive Maximum", async () => {
|
|
786
|
+
const { mqttConn: subscriber, mqttServer } = startMockServer();
|
|
787
|
+
const publisher = addMockClient(mqttServer);
|
|
788
|
+
const clientReceiveMaximum = 2;
|
|
789
|
+
|
|
790
|
+
await connect5(subscriber, {
|
|
791
|
+
clientId: "flowControlClient1",
|
|
792
|
+
properties: { receiveMaximum: clientReceiveMaximum },
|
|
793
|
+
});
|
|
794
|
+
await subscribe5(subscriber, [{ topicFilter: topics[0], qos: 2 }]);
|
|
795
|
+
|
|
796
|
+
await connect5(publisher, {
|
|
797
|
+
clientId: "publisher",
|
|
798
|
+
});
|
|
799
|
+
// Send 1 more than the allowed maximum number of unacknowledged messages
|
|
800
|
+
for (let i = 1; i <= clientReceiveMaximum + 1; i++) {
|
|
801
|
+
await publish5(publisher, topics[0], 1, {
|
|
802
|
+
payload: `flow msg ${i}`,
|
|
803
|
+
id: i,
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
// Receive the initial allowed messages
|
|
808
|
+
const { value: msg1 } = await subscriber.next();
|
|
809
|
+
const { value: msg2 } = await subscriber.next();
|
|
810
|
+
assert.strictEqual(msg1.type, PacketType.publish);
|
|
811
|
+
assert.strictEqual(msg2.type, PacketType.publish);
|
|
812
|
+
// ensure that there are no more messages
|
|
813
|
+
await ping(subscriber);
|
|
814
|
+
|
|
815
|
+
// Send PUBACK to free up a slot
|
|
816
|
+
await subscriber.send({
|
|
817
|
+
type: PacketType.puback,
|
|
818
|
+
protocolLevel: 5,
|
|
819
|
+
id: msg1.id,
|
|
820
|
+
});
|
|
821
|
+
|
|
822
|
+
// Now the 3rd message should be received
|
|
823
|
+
const { value: msg3 } = await subscriber.next();
|
|
824
|
+
assert.strictEqual(msg3.type, PacketType.publish);
|
|
825
|
+
|
|
826
|
+
await disconnect5(subscriber);
|
|
827
|
+
await disconnect5(publisher);
|
|
828
|
+
});
|
|
829
|
+
|
|
830
|
+
test("Flow Control - Exceeding Server Receive Maximum", async () => {
|
|
831
|
+
const { mqttConn } = startMockServer();
|
|
832
|
+
|
|
833
|
+
const connack = await connect5(mqttConn, { clientId: "flowControlClient2" });
|
|
834
|
+
const serverReceiveMax = connack.properties?.receiveMaximum ?? 65535;
|
|
835
|
+
|
|
836
|
+
// If the server enforces a low limit, exceed it to test disconnect reason code 0x93
|
|
837
|
+
if (serverReceiveMax < 10) {
|
|
838
|
+
for (let i = 1; i <= serverReceiveMax + 1; i++) {
|
|
839
|
+
await publish5(mqttConn, topics[0], 2, {
|
|
840
|
+
payload: `exceed msg ${i}`,
|
|
841
|
+
id: i,
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
const { value: disc } = await mqttConn.next();
|
|
846
|
+
assert.strictEqual(disc.type, PacketType.disconnect);
|
|
847
|
+
// Reason Code 147 (0x93) = Receive Maximum exceeded
|
|
848
|
+
assert.strictEqual(disc.reasonCode, 0x93);
|
|
849
|
+
} else {
|
|
850
|
+
await disconnect5(mqttConn);
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
|
|
854
|
+
test("Will Delay Interval and Session Expiry Interaction", async () => {
|
|
855
|
+
const { mqttConn: aConn, mqttServer } = startMockServer();
|
|
856
|
+
|
|
857
|
+
// Test case: WillDelayInterval is set
|
|
858
|
+
await connect5(aConn, {
|
|
859
|
+
clientId: "willDelayClient",
|
|
860
|
+
clean: true,
|
|
861
|
+
keepAlive: 0,
|
|
862
|
+
properties: { sessionExpiryInterval: 5 },
|
|
863
|
+
will: {
|
|
864
|
+
topic: topics[0],
|
|
865
|
+
payload: txtEncoder.encode("delayed will message"),
|
|
866
|
+
qos: 2,
|
|
867
|
+
retain: false,
|
|
868
|
+
properties: { willDelayInterval: 1 },
|
|
869
|
+
},
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
const bConn = addMockClient(mqttServer);
|
|
873
|
+
await connect5(bConn, { clientId: "watcherClient" });
|
|
874
|
+
await subscribe5(bConn, [{ topicFilter: topics[0], qos: 2 }]);
|
|
875
|
+
|
|
876
|
+
// Force an unclean disconnection of Client A
|
|
877
|
+
aConn.close();
|
|
878
|
+
|
|
879
|
+
// The will message should not arrive immediately, but only after the willDelayInterval (1s)
|
|
880
|
+
await delay(1200);
|
|
881
|
+
|
|
882
|
+
const { value: willPub } = await bConn.next();
|
|
883
|
+
assert.strictEqual(willPub.type, PacketType.publish);
|
|
884
|
+
assert.strictEqual(willPub.topic, topics[0]);
|
|
885
|
+
|
|
886
|
+
await disconnect5(bConn);
|
|
887
|
+
});
|