@seriousme/opifex 1.11.3 → 2.1.0
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/README.md +99 -40
- package/bin/conformanceServer.ts +45 -13
- package/bin/demoServer.ts +38 -13
- package/bin/mqtt.ts +2 -2
- package/client/ConnectionState.ts +3 -1
- package/client/client.ts +88 -47
- package/client/context.ts +79 -27
- package/client/deps.ts +10 -3
- 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 +18 -8
- 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 +13 -2
- package/client/store/memoryStore.ts +12 -11
- package/client/store/store.ts +4 -2
- package/deno/README.md +1 -2
- package/deno/tcpClient.test.ts +75 -0
- package/deno/tcpClient.ts +36 -18
- package/deno/tcpServer.test.ts +22 -21
- package/deno/tcpServer.ts +26 -4
- package/deno/tlsServer.test.ts +97 -0
- package/deno/tlsServer.ts +58 -0
- package/deno/wsServer.test.ts +93 -0
- package/deno/wsServer.ts +96 -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 -3
- 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 +2 -2
- package/dist/bin/mqtt.js.map +1 -1
- package/dist/client/ConnectionState.d.ts +3 -1
- 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 +47 -21
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +57 -20
- package/dist/client/client.js.map +1 -1
- package/dist/client/context.d.ts +15 -7
- 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 +4 -3
- 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 +3 -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 +3 -3
- package/dist/client/store/memoryStore.d.ts.map +1 -1
- package/dist/client/store/memoryStore.js +3 -3
- package/dist/client/store/memoryStore.js.map +1 -1
- package/dist/client/store/store.d.ts +3 -2
- 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 +24 -31
- package/dist/mqttConn/mqttConn.d.ts.map +1 -1
- package/dist/mqttConn/mqttConn.js +57 -36
- package/dist/mqttConn/mqttConn.js.map +1 -1
- package/dist/mqttPacket/AuthenticationResult.d.ts +4 -0
- package/dist/mqttPacket/AuthenticationResult.d.ts.map +1 -1
- package/dist/mqttPacket/AuthenticationResult.js.map +1 -1
- package/dist/mqttPacket/BitMask.d.ts.map +1 -1
- package/dist/mqttPacket/PacketType.d.ts +4 -0
- package/dist/mqttPacket/PacketType.d.ts.map +1 -1
- package/dist/mqttPacket/Properties.d.ts +4 -4
- package/dist/mqttPacket/Properties.d.ts.map +1 -1
- package/dist/mqttPacket/Properties.js.map +1 -1
- package/dist/mqttPacket/ReasonCode.d.ts +4 -5
- 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 +4 -0
- package/dist/mqttPacket/RetainHandling.d.ts.map +1 -1
- package/dist/mqttPacket/auth.d.ts +7 -8
- 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 +11 -10
- 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 +7 -7
- 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 +6 -16
- 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 +9 -8
- 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 +7 -19
- package/dist/mqttPacket/encoder.d.ts.map +1 -1
- package/dist/mqttPacket/encoder.js +5 -28
- package/dist/mqttPacket/encoder.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 +6 -6
- 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 +6 -6
- 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 +8 -7
- 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 +9 -8
- 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 +41 -10
- 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 +2 -29
- package/dist/mqttPacket/types.d.ts.map +1 -1
- package/dist/mqttPacket/unsuback.d.ts +9 -8
- 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 +26 -8
- 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 +22 -2
- package/dist/node/tcpClient.d.ts.map +1 -1
- package/dist/node/tcpClient.js +29 -10
- package/dist/node/tcpClient.js.map +1 -1
- package/dist/node/tcpServer.d.ts +18 -0
- package/dist/node/tcpServer.d.ts.map +1 -1
- package/dist/node/tcpServer.js +21 -2
- package/dist/node/tcpServer.js.map +1 -1
- package/dist/node/tlsServer.d.ts +37 -0
- package/dist/node/tlsServer.d.ts.map +1 -0
- package/dist/node/tlsServer.js +73 -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 +45 -70
- 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 +199 -25
- 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 +9 -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 +32 -9
- 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 +15 -9
- package/dist/socket/socket.d.ts.map +1 -1
- package/dist/socket/socket.js +66 -18
- 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 +61 -41
- 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 +42 -5
- 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 +14 -0
- package/dist/web/wsClient.d.ts.map +1 -0
- package/dist/web/wsClient.js +33 -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 +76 -60
- package/mqttPacket/AuthenticationResult.ts +6 -0
- package/mqttPacket/PacketType.ts +5 -0
- package/mqttPacket/Properties.ts +8 -5
- package/mqttPacket/ReasonCode.ts +8 -9
- package/mqttPacket/RetainHandling.ts +5 -0
- package/mqttPacket/auth.test.ts +1 -1
- package/mqttPacket/auth.ts +44 -51
- package/mqttPacket/codec.ts +147 -0
- package/mqttPacket/connack.ts +63 -73
- package/mqttPacket/connect.test.ts +2 -2
- package/mqttPacket/connect.ts +178 -192
- package/mqttPacket/decoder.test.ts +0 -39
- package/mqttPacket/decoder.ts +17 -46
- package/mqttPacket/disconnect.ts +60 -71
- package/mqttPacket/encoder.test.ts +2 -2
- package/mqttPacket/encoder.ts +13 -46
- package/mqttPacket/mod.ts +48 -204
- package/mqttPacket/pingreq.ts +22 -28
- package/mqttPacket/pingres.ts +22 -28
- package/mqttPacket/protocolLevels.ts +12 -7
- package/mqttPacket/pubblishAcks.ts +61 -75
- package/mqttPacket/publish.ts +70 -84
- package/mqttPacket/publishAcks.test.ts +3 -3
- package/mqttPacket/suback.ts +53 -68
- package/mqttPacket/subscribe.ts +146 -128
- package/mqttPacket/types.ts +2 -35
- package/mqttPacket/unsuback.ts +50 -61
- package/mqttPacket/unsubscribe.ts +77 -72
- 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 +33 -17
- package/node/tcpServer.test.ts +24 -20
- package/node/tcpServer.ts +29 -6
- package/node/tlsServer.test.ts +94 -0
- package/node/tlsServer.ts +97 -0
- package/node/wrapNodeSocket.ts +7 -30
- package/package.json +72 -44
- package/persistence/basicPersistence.ts +495 -0
- package/persistence/deps.ts +11 -1
- package/persistence/memory/memoryPersistence.ts +12 -153
- package/persistence/memory/memoryStorage.ts +232 -0
- package/persistence/mod.ts +5 -10
- package/persistence/persistence.test.ts +24 -0
- package/persistence/persistence.testing.ts +1324 -0
- package/persistence/persistence.ts +112 -68
- 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 +660 -76
- package/server/deps.ts +24 -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 +188 -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 +157 -39
- package/server/handlers/handleUnsubscribe.test.ts +79 -0
- package/server/handlers/handleUnsubscribe.ts +28 -4
- 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 +5 -4
- package/server/preconnect.test.ts +151 -0
- package/server/server.ts +117 -19
- package/socket/socket.test.ts +91 -0
- package/socket/socket.ts +85 -34
- 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 +70 -45
- package/utils/bufferedAsyncIterable.test.ts +92 -0
- 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 +64 -9
- 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 +37 -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/dev_utils/socketPair.ts +0 -85
- package/dist/persistence/store.d.ts +0 -14
- 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 -16
- package/server/test/handleConnect.test.ts +0 -122
- package/server/test/test-handlers.ts +0 -53
- /package/utils/{BufferedAsyncIterable.ts → bufferedAsyncIterable.ts} +0 -0
|
@@ -1,119 +1,234 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
AuthenticatedResult,
|
|
3
|
+
ConnectOptions,
|
|
4
|
+
Context,
|
|
5
|
+
} from "../context.ts";
|
|
6
|
+
import {
|
|
7
|
+
invalidmaxTopicLevels,
|
|
8
|
+
invalidTopic,
|
|
9
|
+
logger,
|
|
10
|
+
PacketType,
|
|
11
|
+
ReasonCode,
|
|
12
|
+
} from "../deps.ts";
|
|
13
|
+
import type { ConnectPacket, ExtPublishPacket } from "../deps.ts";
|
|
14
|
+
import { completeConnect } from "./completeConnect.ts";
|
|
3
15
|
|
|
4
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Extracts options from MQTT v5 packet properties.
|
|
18
|
+
*/
|
|
19
|
+
function extractConnectOptions(packet: ConnectPacket): ConnectOptions {
|
|
20
|
+
if (packet.protocolLevel !== 5) {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
sessionExpiryInterval: packet.properties?.sessionExpiryInterval,
|
|
26
|
+
willDelayInterval: packet.will?.properties?.willDelayInterval,
|
|
27
|
+
topicAliasMaximum: packet.properties?.topicAliasMaximum,
|
|
28
|
+
maximumOutgoingPacketSize: packet.properties?.maximumPacketSize,
|
|
29
|
+
receiveMaximum: packet.properties?.receiveMaximum,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
5
32
|
|
|
6
33
|
/**
|
|
7
|
-
* Checks if
|
|
8
|
-
* @param ctx - The connection context
|
|
9
|
-
* @param packet - The MQTT CONNECT packet
|
|
10
|
-
* @returns Authentication result indicating if the client is authenticated
|
|
34
|
+
* Checks if client credentials are valid.
|
|
11
35
|
*/
|
|
12
|
-
function
|
|
36
|
+
async function authenticateClient(
|
|
13
37
|
ctx: Context,
|
|
38
|
+
clientId: string,
|
|
14
39
|
packet: ConnectPacket,
|
|
15
|
-
):
|
|
40
|
+
): Promise<AuthenticatedResult> {
|
|
41
|
+
const isProtocolV5 = packet.protocolLevel === 5;
|
|
42
|
+
const authMethod = isProtocolV5
|
|
43
|
+
? packet.properties?.authenticationMethod
|
|
44
|
+
: undefined;
|
|
45
|
+
|
|
16
46
|
if (ctx.handlers.isAuthenticated) {
|
|
17
|
-
|
|
18
|
-
ctx
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
47
|
+
try {
|
|
48
|
+
const result = await ctx.handlers.isAuthenticated(
|
|
49
|
+
ctx,
|
|
50
|
+
clientId,
|
|
51
|
+
packet.username || "",
|
|
52
|
+
packet.password || new Uint8Array(0),
|
|
53
|
+
packet,
|
|
54
|
+
);
|
|
55
|
+
if (
|
|
56
|
+
isProtocolV5 && result.reasonCode === ReasonCode.success &&
|
|
57
|
+
authMethod !== undefined && ctx.handlers.processAuth
|
|
58
|
+
) {
|
|
59
|
+
const authData = packet.properties?.authenticationData;
|
|
60
|
+
return await ctx.handlers.processAuth(
|
|
61
|
+
ctx,
|
|
62
|
+
clientId,
|
|
63
|
+
authMethod,
|
|
64
|
+
authData!,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
} catch (err) {
|
|
69
|
+
let message = "unknown error";
|
|
70
|
+
if (err instanceof Error) {
|
|
71
|
+
message = err.message;
|
|
72
|
+
}
|
|
73
|
+
logger.error("Authentication failed with error", message);
|
|
74
|
+
return {
|
|
75
|
+
reasonCode: ReasonCode.unspecifiedError,
|
|
76
|
+
reasonString: "Authentication failed",
|
|
77
|
+
};
|
|
78
|
+
}
|
|
23
79
|
}
|
|
24
|
-
return
|
|
80
|
+
return { reasonCode: ReasonCode.success };
|
|
25
81
|
}
|
|
26
82
|
|
|
27
83
|
/**
|
|
28
|
-
* Validates the CONNECT packet
|
|
29
|
-
* @param ctx - The connection context
|
|
30
|
-
* @param packet - The MQTT CONNECT packet to validate
|
|
31
|
-
* @returns Authentication result indicating if the CONNECT packet is valid
|
|
84
|
+
* Validates the CONNECT packet structure and Will configuration.
|
|
32
85
|
*/
|
|
33
|
-
function
|
|
86
|
+
async function validateConnectPacket(
|
|
34
87
|
ctx: Context,
|
|
35
88
|
packet: ConnectPacket,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
89
|
+
sessionExpiryInterval: number,
|
|
90
|
+
): Promise<AuthenticatedResult | null> {
|
|
91
|
+
const cfg = ctx.config.context;
|
|
92
|
+
|
|
93
|
+
// Protocol version check
|
|
94
|
+
if (!cfg.protocols.includes(packet.protocolLevel)) {
|
|
95
|
+
return {
|
|
96
|
+
reasonCode: ReasonCode.unsupportedProtocolVersion,
|
|
97
|
+
reasonString: `Protocol version ${packet.protocolLevel} is not supported`,
|
|
98
|
+
};
|
|
39
99
|
}
|
|
40
100
|
|
|
41
|
-
|
|
42
|
-
|
|
101
|
+
// Will message validation
|
|
102
|
+
if (packet.will) {
|
|
103
|
+
const isProtocolV5 = packet.protocolLevel === 5;
|
|
104
|
+
const will = packet.will as ExtPublishPacket;
|
|
43
105
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
ctx.will = {
|
|
59
|
-
type: PacketType.publish,
|
|
60
|
-
protocolLevel: ctx.protocolLevel,
|
|
61
|
-
qos: packet.will.qos,
|
|
62
|
-
retain: packet.will.retain,
|
|
63
|
-
topic: packet.will.topic,
|
|
64
|
-
payload: packet.will.payload,
|
|
106
|
+
if (
|
|
107
|
+
will.topic === "" || invalidTopic(will.topic) ||
|
|
108
|
+
invalidmaxTopicLevels(will.topic, cfg.maxTopicLevels)
|
|
109
|
+
) {
|
|
110
|
+
return {
|
|
111
|
+
reasonCode: ReasonCode.topicNameInvalid,
|
|
112
|
+
reasonString: "Invalid will topic",
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (!cfg.retainAvailable && will.retain) {
|
|
117
|
+
return {
|
|
118
|
+
reasonCode: ReasonCode.retainNotSupported,
|
|
119
|
+
reasonString: "Publish will with retain=true is not supported",
|
|
65
120
|
};
|
|
66
121
|
}
|
|
67
122
|
|
|
68
|
-
ctx.
|
|
69
|
-
ctx.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
123
|
+
const checkAuthz = ctx.handlers.isAuthorizedToPublish;
|
|
124
|
+
if (checkAuthz && !await checkAuthz(ctx, will.topic)) {
|
|
125
|
+
return {
|
|
126
|
+
reasonCode: ReasonCode.notAuthorized,
|
|
127
|
+
reasonString: `Client not authorized to publish will to ${will.topic}`,
|
|
128
|
+
};
|
|
73
129
|
}
|
|
74
130
|
|
|
75
|
-
const
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
131
|
+
const qos = will.qos || 0;
|
|
132
|
+
if (qos > cfg.maximumQos) {
|
|
133
|
+
return {
|
|
134
|
+
reasonCode: ReasonCode.qosNotSupported,
|
|
135
|
+
reasonString: `Server does not support publish will with QoS ${qos}`,
|
|
136
|
+
};
|
|
81
137
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
138
|
+
|
|
139
|
+
if (isProtocolV5) {
|
|
140
|
+
const requestedInterval = packet.will.properties?.willDelayInterval || 0;
|
|
141
|
+
if (requestedInterval > sessionExpiryInterval) {
|
|
142
|
+
return {
|
|
143
|
+
reasonCode: ReasonCode.payloadFormatInvalid,
|
|
144
|
+
reasonString:
|
|
145
|
+
"Will delay interval larger than allowed session expiry interval",
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const expiryInterval = packet.will.properties?.messageExpiryInterval;
|
|
149
|
+
if (expiryInterval) {
|
|
150
|
+
will.expiresAtMs = Date.now() + expiryInterval * 1000;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const authMethod = packet.properties?.authenticationMethod;
|
|
154
|
+
const authData = packet.properties?.authenticationData;
|
|
155
|
+
|
|
156
|
+
if (
|
|
157
|
+
// both need to be either present or absent, one is not enough
|
|
158
|
+
(authMethod !== undefined) !== (authData !== undefined) ||
|
|
159
|
+
// authMethod without a handler won't work
|
|
160
|
+
(authMethod !== undefined || !ctx.handlers.processAuth)
|
|
161
|
+
) {
|
|
162
|
+
return {
|
|
163
|
+
reasonCode: ReasonCode.badAuthenticationMethod,
|
|
164
|
+
reasonString:
|
|
165
|
+
"Bad authentication method or missing authentication data",
|
|
166
|
+
};
|
|
167
|
+
}
|
|
89
168
|
}
|
|
90
|
-
return previousSession || false;
|
|
91
169
|
}
|
|
92
|
-
|
|
170
|
+
|
|
171
|
+
return null;
|
|
93
172
|
}
|
|
94
173
|
|
|
95
174
|
/**
|
|
96
|
-
* Handles the MQTT CONNECT packet
|
|
97
|
-
* @param ctx - The connection context
|
|
98
|
-
* @param packet - The MQTT CONNECT packet to handle
|
|
175
|
+
* Handles the MQTT CONNECT packet.
|
|
99
176
|
*/
|
|
100
|
-
export function handleConnect(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
177
|
+
export async function handleConnect(
|
|
178
|
+
ctx: Context,
|
|
179
|
+
packet: ConnectPacket,
|
|
180
|
+
): Promise<void> {
|
|
181
|
+
const isProtocolV5 = packet.protocolLevel === 5;
|
|
182
|
+
const cfg = ctx.config.context;
|
|
183
|
+
|
|
184
|
+
// Assign Client ID if missing
|
|
185
|
+
let clientId = packet.clientId;
|
|
186
|
+
let assignedClientIdentifier = undefined;
|
|
187
|
+
if (!clientId) {
|
|
188
|
+
clientId = `Opifex-${crypto.randomUUID()}`;
|
|
189
|
+
assignedClientIdentifier = clientId;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Extract connect options for v5
|
|
193
|
+
const connectOpts = extractConnectOptions(packet);
|
|
194
|
+
// Limit session Expiry Interval to server maximum
|
|
195
|
+
connectOpts.sessionExpiryInterval = Math.min(
|
|
196
|
+
connectOpts.sessionExpiryInterval || 0,
|
|
197
|
+
cfg.maxSessionExpiryInterval,
|
|
198
|
+
);
|
|
199
|
+
connectOpts.keepAlive = packet.keepAlive;
|
|
200
|
+
connectOpts.assignedClientIdentifier = assignedClientIdentifier;
|
|
201
|
+
|
|
202
|
+
// Validate Packet & Authenticate Client
|
|
203
|
+
const validationError = await validateConnectPacket(
|
|
106
204
|
ctx,
|
|
107
|
-
|
|
205
|
+
packet,
|
|
206
|
+
connectOpts.sessionExpiryInterval,
|
|
108
207
|
);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
ctx.
|
|
208
|
+
const authResult = validationError ??
|
|
209
|
+
await authenticateClient(ctx, clientId, packet);
|
|
210
|
+
const { reasonCode, reasonString, authData } = authResult;
|
|
211
|
+
const requireAuth = reasonCode === ReasonCode.continueAuthentication;
|
|
212
|
+
|
|
213
|
+
ctx.prepareConnect(packet, clientId, connectOpts);
|
|
214
|
+
if (isProtocolV5 && requireAuth) {
|
|
215
|
+
const authMethod = packet.properties?.authenticationMethod;
|
|
216
|
+
await ctx.send({
|
|
217
|
+
type: PacketType.auth,
|
|
218
|
+
protocolLevel: 5,
|
|
219
|
+
reasonCode,
|
|
220
|
+
properties: {
|
|
221
|
+
authenticationMethod: authMethod,
|
|
222
|
+
authenticationData: authData,
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
return;
|
|
118
226
|
}
|
|
227
|
+
|
|
228
|
+
await completeConnect(
|
|
229
|
+
ctx,
|
|
230
|
+
packet.protocolLevel || 4,
|
|
231
|
+
reasonCode,
|
|
232
|
+
reasonString,
|
|
233
|
+
);
|
|
119
234
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import type { AnyPacket, ProtocolLevel } from "../deps.ts";
|
|
4
|
+
import { AuthenticationResult, MQTTLevel, PacketType } from "../deps.ts";
|
|
5
|
+
import { startMockServer } from "../../dev_utils/mod.ts";
|
|
6
|
+
|
|
7
|
+
const txtEncoder = new TextEncoder();
|
|
8
|
+
|
|
9
|
+
const baseConnectPacket: AnyPacket = {
|
|
10
|
+
type: PacketType.connect,
|
|
11
|
+
protocolName: "MQTT",
|
|
12
|
+
protocolLevel: MQTTLevel.v4 as ProtocolLevel,
|
|
13
|
+
clientId: "testClient",
|
|
14
|
+
clean: true,
|
|
15
|
+
keepAlive: 0,
|
|
16
|
+
username: "IoTester_1",
|
|
17
|
+
password: txtEncoder.encode("strong_password"),
|
|
18
|
+
will: undefined,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const disconnectPacket: AnyPacket = {
|
|
22
|
+
type: PacketType.disconnect,
|
|
23
|
+
protocolLevel: MQTTLevel.v4,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
test("rejects MQTT 3.1 (protocolLevel 3) with unacceptableProtocol", async () => {
|
|
27
|
+
const { mqttConn } = startMockServer();
|
|
28
|
+
const packet = structuredClone(baseConnectPacket);
|
|
29
|
+
packet.protocolLevel = MQTTLevel.v3;
|
|
30
|
+
mqttConn.send(packet);
|
|
31
|
+
const { value: connack } = await mqttConn.next();
|
|
32
|
+
assert.deepStrictEqual(
|
|
33
|
+
connack.type,
|
|
34
|
+
PacketType.connack,
|
|
35
|
+
"Expect Connack packet",
|
|
36
|
+
);
|
|
37
|
+
if (connack.type === PacketType.connack) {
|
|
38
|
+
assert.deepStrictEqual(
|
|
39
|
+
connack.returnCode,
|
|
40
|
+
AuthenticationResult.unacceptableProtocol,
|
|
41
|
+
"Expected unacceptableProtocol for MQTT 3.1",
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
await mqttConn.next();
|
|
45
|
+
assert.deepStrictEqual(
|
|
46
|
+
mqttConn.isClosed,
|
|
47
|
+
true,
|
|
48
|
+
"Expected connection to be closed after protocol rejection",
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("accepts MQTT 3.1.1 (protocolLevel 4) connection", async () => {
|
|
53
|
+
const { mqttConn } = startMockServer();
|
|
54
|
+
const packet = structuredClone(baseConnectPacket);
|
|
55
|
+
packet.protocolLevel = MQTTLevel.v4;
|
|
56
|
+
mqttConn.send(packet);
|
|
57
|
+
const { value: connack } = await mqttConn.next();
|
|
58
|
+
assert.deepStrictEqual(
|
|
59
|
+
connack.type,
|
|
60
|
+
PacketType.connack,
|
|
61
|
+
"Expect Connack packet",
|
|
62
|
+
);
|
|
63
|
+
if (connack.type === PacketType.connack) {
|
|
64
|
+
assert.deepStrictEqual(
|
|
65
|
+
connack.returnCode,
|
|
66
|
+
AuthenticationResult.ok,
|
|
67
|
+
"Expected OK for MQTT 3.1.1",
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
mqttConn.send(disconnectPacket);
|
|
71
|
+
await mqttConn.next();
|
|
72
|
+
assert.deepStrictEqual(
|
|
73
|
+
mqttConn.isClosed,
|
|
74
|
+
true,
|
|
75
|
+
"Expected connection to be closed cleanly",
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("accepts MQTT 5.0 (protocolLevel 5) connection", async () => {
|
|
80
|
+
const { mqttConn } = startMockServer();
|
|
81
|
+
const packet = structuredClone(baseConnectPacket);
|
|
82
|
+
packet.protocolLevel = MQTTLevel.v5;
|
|
83
|
+
mqttConn.codecOpts.protocolLevel = MQTTLevel.v5;
|
|
84
|
+
mqttConn.send(packet);
|
|
85
|
+
const { value: connack } = await mqttConn.next();
|
|
86
|
+
assert.deepStrictEqual(
|
|
87
|
+
connack.type,
|
|
88
|
+
PacketType.connack,
|
|
89
|
+
"Expect Connack packet",
|
|
90
|
+
);
|
|
91
|
+
if (connack.type === PacketType.connack) {
|
|
92
|
+
assert.deepStrictEqual(
|
|
93
|
+
connack.reasonCode,
|
|
94
|
+
AuthenticationResult.ok,
|
|
95
|
+
"Expected Ok for MQTT 5.0",
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const disconnectV5 = structuredClone(disconnectPacket);
|
|
100
|
+
disconnectV5.protocolLevel = 5;
|
|
101
|
+
mqttConn.send(disconnectV5);
|
|
102
|
+
await mqttConn.next();
|
|
103
|
+
assert.deepStrictEqual(
|
|
104
|
+
mqttConn.isClosed,
|
|
105
|
+
true,
|
|
106
|
+
"Expected connection to be closed cleanly",
|
|
107
|
+
);
|
|
108
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import type { AnyPacket } from "../deps.ts";
|
|
4
|
+
import { PacketType } from "../deps.ts";
|
|
5
|
+
import {
|
|
6
|
+
addMockClient,
|
|
7
|
+
checkNoPacket,
|
|
8
|
+
connect,
|
|
9
|
+
disconnect,
|
|
10
|
+
startMockServer,
|
|
11
|
+
subscribe,
|
|
12
|
+
} from "../../dev_utils/mod.ts";
|
|
13
|
+
|
|
14
|
+
const txtEncoder = new TextEncoder();
|
|
15
|
+
|
|
16
|
+
test("DISCONNECT closes connection cleanly", async () => {
|
|
17
|
+
const { mqttConn } = startMockServer();
|
|
18
|
+
|
|
19
|
+
// Connect first
|
|
20
|
+
await connect(mqttConn);
|
|
21
|
+
// Send DISCONNECT
|
|
22
|
+
await disconnect(mqttConn);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("DISCONNECT clears will message", async () => {
|
|
26
|
+
const connectWithWill: AnyPacket = {
|
|
27
|
+
type: PacketType.connect,
|
|
28
|
+
protocolName: "MQTT",
|
|
29
|
+
protocolLevel: 4,
|
|
30
|
+
clientId: "testClientWithWill",
|
|
31
|
+
clean: true,
|
|
32
|
+
keepAlive: 0,
|
|
33
|
+
username: "IoTester_1",
|
|
34
|
+
password: txtEncoder.encode("strong_password"),
|
|
35
|
+
will: {
|
|
36
|
+
topic: "will/topic",
|
|
37
|
+
payload: txtEncoder.encode("goodbye"),
|
|
38
|
+
qos: 0,
|
|
39
|
+
retain: false,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const { mqttConn: mqttConn1, mqttServer } = startMockServer();
|
|
44
|
+
// Connect subscriber to catch any will message
|
|
45
|
+
await connect(mqttConn1);
|
|
46
|
+
await subscribe(mqttConn1, [{ topicFilter: "will/topic", qos: 0 }]);
|
|
47
|
+
|
|
48
|
+
// Connect with will message
|
|
49
|
+
const mqttConn2 = addMockClient(mqttServer);
|
|
50
|
+
mqttConn2.send(connectWithWill);
|
|
51
|
+
const { value: connack2 } = await mqttConn2.next();
|
|
52
|
+
assert.deepStrictEqual(connack2.type, PacketType.connack, "Expected CONNACK");
|
|
53
|
+
await disconnect(mqttConn2);
|
|
54
|
+
// Clean disconnect should clear will (will should not be published)
|
|
55
|
+
await checkNoPacket(mqttConn1);
|
|
56
|
+
});
|
|
@@ -5,7 +5,7 @@ import type { Context } from "../context.ts";
|
|
|
5
5
|
* @param {Context} ctx - The connection context object
|
|
6
6
|
* @returns {void}
|
|
7
7
|
*/
|
|
8
|
-
export function handleDisconnect(ctx: Context): void {
|
|
9
|
-
|
|
10
|
-
ctx.close();
|
|
8
|
+
export async function handleDisconnect(ctx: Context): Promise<void> {
|
|
9
|
+
// close the context without sending the will
|
|
10
|
+
await ctx.close(false);
|
|
11
11
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import type { AnyPacket } from "../deps.ts";
|
|
4
|
+
import { MQTTLevel, PacketType } from "../deps.ts";
|
|
5
|
+
import { startMockServer } from "../../dev_utils/mod.ts";
|
|
6
|
+
|
|
7
|
+
test("rejects packets before CONNECT", async () => {
|
|
8
|
+
const { mqttConn } = startMockServer();
|
|
9
|
+
|
|
10
|
+
// Try to send PINGREQ before CONNECT
|
|
11
|
+
const pingreqPacket: AnyPacket = {
|
|
12
|
+
type: PacketType.pingreq,
|
|
13
|
+
protocolLevel: MQTTLevel.v4,
|
|
14
|
+
};
|
|
15
|
+
mqttConn.send(pingreqPacket);
|
|
16
|
+
await mqttConn.next();
|
|
17
|
+
|
|
18
|
+
// Connection should be closed due to protocol violation
|
|
19
|
+
assert.deepStrictEqual(
|
|
20
|
+
mqttConn.isClosed,
|
|
21
|
+
true,
|
|
22
|
+
"Connection should be closed for packets before CONNECT",
|
|
23
|
+
);
|
|
24
|
+
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { SessionState } from "../context.ts";
|
|
1
2
|
import type { Context } from "../context.ts";
|
|
2
3
|
import { PacketNameByType, PacketType } from "../deps.ts";
|
|
3
4
|
import type {
|
|
4
5
|
AnyPacket,
|
|
6
|
+
AuthPacket,
|
|
5
7
|
PubackPacket,
|
|
6
8
|
PubcompPacket,
|
|
7
9
|
PublishPacket,
|
|
@@ -20,6 +22,7 @@ import { handlePubcomp } from "./handlePubcomp.ts";
|
|
|
20
22
|
import { handleSubscribe } from "./handleSubscribe.ts";
|
|
21
23
|
import { handleUnsubscribe } from "./handleUnsubscribe.ts";
|
|
22
24
|
import { handleDisconnect } from "./handleDisconnect.ts";
|
|
25
|
+
import { handleAuth } from "./handleAuth.ts";
|
|
23
26
|
import { logger } from "../deps.ts";
|
|
24
27
|
|
|
25
28
|
/**
|
|
@@ -33,16 +36,32 @@ export async function handlePacket(
|
|
|
33
36
|
ctx: Context,
|
|
34
37
|
packet: AnyPacket,
|
|
35
38
|
): Promise<void> {
|
|
36
|
-
logger.debug("
|
|
37
|
-
logger.debug(
|
|
38
|
-
|
|
39
|
+
logger.debug("server/handlePacket", PacketNameByType[packet.type]);
|
|
40
|
+
logger.debug(
|
|
41
|
+
"server/handlePacket",
|
|
42
|
+
() => JSON.stringify(packet, null, 2),
|
|
43
|
+
);
|
|
44
|
+
if (ctx.state === SessionState.disconnected) {
|
|
39
45
|
if (packet.type === PacketType.connect) {
|
|
40
|
-
handleConnect(ctx, packet);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
`Received ${PacketNameByType[packet.type]} packet before connect`,
|
|
44
|
-
);
|
|
46
|
+
await handleConnect(ctx, packet);
|
|
47
|
+
ctx.timer?.reset();
|
|
48
|
+
return;
|
|
45
49
|
}
|
|
50
|
+
throw new Error(
|
|
51
|
+
`Received ${PacketNameByType[packet.type]} packet before connect`,
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
if (ctx.state === SessionState.connecting) {
|
|
55
|
+
if (packet.type === PacketType.auth) {
|
|
56
|
+
await handleAuth(ctx, packet as AuthPacket);
|
|
57
|
+
ctx.timer?.reset();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
throw new Error(
|
|
61
|
+
`Received unexpected ${
|
|
62
|
+
PacketNameByType[packet.type]
|
|
63
|
+
} packet before connect completed`,
|
|
64
|
+
);
|
|
46
65
|
} else {
|
|
47
66
|
switch (packet.type) {
|
|
48
67
|
case PacketType.pingreq:
|
|
@@ -72,6 +91,9 @@ export async function handlePacket(
|
|
|
72
91
|
case PacketType.disconnect:
|
|
73
92
|
handleDisconnect(ctx);
|
|
74
93
|
break;
|
|
94
|
+
case PacketType.auth:
|
|
95
|
+
handleAuth(ctx, packet as AuthPacket);
|
|
96
|
+
break;
|
|
75
97
|
default:
|
|
76
98
|
throw new Error(
|
|
77
99
|
`Received unexpected ${
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import type { AnyPacket } from "../deps.ts";
|
|
4
|
+
import { MQTTLevel, PacketType } from "../deps.ts";
|
|
5
|
+
import { connect, disconnect, startMockServer } from "../../dev_utils/mod.ts";
|
|
6
|
+
|
|
7
|
+
const pingreqPacket: AnyPacket = {
|
|
8
|
+
type: PacketType.pingreq,
|
|
9
|
+
protocolLevel: MQTTLevel.v4,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
test("PINGREQ returns PINGRES", async () => {
|
|
13
|
+
const { mqttConn } = startMockServer();
|
|
14
|
+
|
|
15
|
+
// Connect first
|
|
16
|
+
await connect(mqttConn);
|
|
17
|
+
|
|
18
|
+
// Send PINGREQ
|
|
19
|
+
mqttConn.send(pingreqPacket);
|
|
20
|
+
const { value: pingres } = await mqttConn.next();
|
|
21
|
+
assert.deepStrictEqual(
|
|
22
|
+
pingres.type,
|
|
23
|
+
PacketType.pingres,
|
|
24
|
+
"Expected PINGRES response to PINGREQ",
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
// Disconnect
|
|
28
|
+
await disconnect(mqttConn);
|
|
29
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import type { AnyPacket } from "../deps.ts";
|
|
3
|
+
import { MQTTLevel, PacketType } from "../deps.ts";
|
|
4
|
+
import {
|
|
5
|
+
connect,
|
|
6
|
+
disconnect,
|
|
7
|
+
ping,
|
|
8
|
+
startMockServer,
|
|
9
|
+
} from "../../dev_utils/mod.ts";
|
|
10
|
+
|
|
11
|
+
test("PUBACK is handled without error", async () => {
|
|
12
|
+
const { mqttConn } = startMockServer();
|
|
13
|
+
|
|
14
|
+
await connect(mqttConn);
|
|
15
|
+
|
|
16
|
+
// Send PUBACK (simulating acknowledgment for outgoing QoS 1 message)
|
|
17
|
+
const pubackPacket: AnyPacket = {
|
|
18
|
+
type: PacketType.puback,
|
|
19
|
+
protocolLevel: MQTTLevel.v4,
|
|
20
|
+
id: 9999,
|
|
21
|
+
};
|
|
22
|
+
mqttConn.send(pubackPacket);
|
|
23
|
+
|
|
24
|
+
// Verify server is still responsive
|
|
25
|
+
await ping(mqttConn);
|
|
26
|
+
|
|
27
|
+
await disconnect(mqttConn);
|
|
28
|
+
});
|
|
@@ -7,13 +7,10 @@ import type { PubackPacket } from "../deps.ts";
|
|
|
7
7
|
* @param packet - The PUBACK packet received from the client
|
|
8
8
|
* @description
|
|
9
9
|
* PUBACK packets are sent in response to PUBLISH packets with QoS level 1.
|
|
10
|
-
* This function removes the original PUBLISH packet from the pending outgoing messages store
|
|
11
|
-
* once acknowledgment is received.
|
|
12
10
|
*/
|
|
13
|
-
export function handlePuback(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
11
|
+
export async function handlePuback(
|
|
12
|
+
ctx: Context,
|
|
13
|
+
packet: PubackPacket,
|
|
14
|
+
): Promise<void> {
|
|
15
|
+
await ctx.processAck(packet.id);
|
|
19
16
|
}
|