@seriousme/opifex 1.11.3 → 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/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 +2 -0
- package/client/client.ts +51 -41
- package/client/context.ts +75 -21
- package/client/deps.ts +4 -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 +1 -1
- 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 -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 +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 +13 -16
- 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 +1 -1
- 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 +23 -15
- package/dist/mqttConn/mqttConn.d.ts.map +1 -1
- package/dist/mqttConn/mqttConn.js +56 -35
- package/dist/mqttConn/mqttConn.js.map +1 -1
- package/dist/mqttPacket/AuthenticationResult.d.ts.map +1 -1
- package/dist/mqttPacket/BitMask.d.ts.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 +4 -5
- 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 +6 -27
- 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/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 +4 -5
- 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 +5 -5
- 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 +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 +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 +76 -44
- 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 +175 -182
- package/mqttPacket/decoder.test.ts +0 -39
- package/mqttPacket/decoder.ts +8 -35
- package/mqttPacket/disconnect.ts +57 -68
- package/mqttPacket/encoder.ts +5 -40
- 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 +56 -70
- package/mqttPacket/publish.ts +67 -74
- 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 +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 +4 -9
- 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 -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 +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/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
package/client/context.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import type {
|
|
10
10
|
AnyPacket,
|
|
11
11
|
ConnectPacket,
|
|
12
|
-
|
|
12
|
+
IStore,
|
|
13
13
|
PacketId,
|
|
14
14
|
ProtocolLevel,
|
|
15
15
|
PublishPacket,
|
|
@@ -17,6 +17,8 @@ import type {
|
|
|
17
17
|
SockConn,
|
|
18
18
|
SubscribePacket,
|
|
19
19
|
TAuthenticationResult,
|
|
20
|
+
TPacketType,
|
|
21
|
+
TReasonCode,
|
|
20
22
|
UnsubscribePacket,
|
|
21
23
|
} from "./deps.ts";
|
|
22
24
|
|
|
@@ -26,6 +28,24 @@ import { ConnectionState } from "./ConnectionState.ts";
|
|
|
26
28
|
import type { Client } from "./client.ts";
|
|
27
29
|
import { assert } from "../utils/assert.ts";
|
|
28
30
|
|
|
31
|
+
/**
|
|
32
|
+
* packets not allowed during authentication
|
|
33
|
+
*/
|
|
34
|
+
function blockedDuringAuthentication(pktType: TPacketType) {
|
|
35
|
+
return (
|
|
36
|
+
pktType === PacketType.publish ||
|
|
37
|
+
pktType === PacketType.subscribe ||
|
|
38
|
+
pktType === PacketType.unsubscribe
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Possible results from authHandler */
|
|
43
|
+
export type AuthenticatedResult = {
|
|
44
|
+
reasonCode: TReasonCode;
|
|
45
|
+
reasonString?: string;
|
|
46
|
+
authData?: Uint8Array;
|
|
47
|
+
};
|
|
48
|
+
|
|
29
49
|
export class Context {
|
|
30
50
|
mqttConn?: MqttConn;
|
|
31
51
|
#connectionState: TConnectionState;
|
|
@@ -35,10 +55,10 @@ export class Context {
|
|
|
35
55
|
unresolvedPublish: Map<PacketId, Deferred<void>>;
|
|
36
56
|
unresolvedSubscribe: Map<PacketId, Deferred<ReturnCodes>>;
|
|
37
57
|
unresolvedUnSubscribe: Map<PacketId, Deferred<void>>;
|
|
38
|
-
store:
|
|
58
|
+
store: IStore;
|
|
39
59
|
#client: Client;
|
|
40
60
|
|
|
41
|
-
constructor(store:
|
|
61
|
+
constructor(store: IStore, client: Client) {
|
|
42
62
|
this.#client = client;
|
|
43
63
|
this.store = store;
|
|
44
64
|
this.#connectionState = ConnectionState.offline;
|
|
@@ -64,6 +84,25 @@ export class Context {
|
|
|
64
84
|
}
|
|
65
85
|
}
|
|
66
86
|
|
|
87
|
+
authHandler(
|
|
88
|
+
_ctx: Context,
|
|
89
|
+
authMethod: string,
|
|
90
|
+
authData: Uint8Array,
|
|
91
|
+
): AuthenticatedResult | Promise<AuthenticatedResult> {
|
|
92
|
+
return this.#client.onAuth(authMethod, authData);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
setPingTimer(interval: number) {
|
|
96
|
+
if (this.pingTimer) {
|
|
97
|
+
this.pingTimer.clear();
|
|
98
|
+
}
|
|
99
|
+
this.pingTimer = new Timer(
|
|
100
|
+
this.sendPing.bind(this),
|
|
101
|
+
interval * 1000,
|
|
102
|
+
true,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
67
106
|
async connect(packet: ConnectPacket) {
|
|
68
107
|
this.connectionState = ConnectionState.connecting;
|
|
69
108
|
if (packet.protocolLevel === MQTTLevel.unknown) {
|
|
@@ -73,16 +112,15 @@ export class Context {
|
|
|
73
112
|
await this.mqttConn?.send(packet);
|
|
74
113
|
const keepAlive = packet.keepAlive || 0;
|
|
75
114
|
if (keepAlive > 0) {
|
|
76
|
-
this.
|
|
77
|
-
this.sendPing.bind(this),
|
|
78
|
-
keepAlive * 1000,
|
|
79
|
-
true,
|
|
80
|
-
);
|
|
115
|
+
this.setPingTimer(keepAlive);
|
|
81
116
|
}
|
|
82
117
|
}
|
|
83
118
|
|
|
84
119
|
async disconnect() {
|
|
85
|
-
if (
|
|
120
|
+
if (
|
|
121
|
+
this.connectionState !== ConnectionState.connected &&
|
|
122
|
+
this.connectionState !== ConnectionState.authenticating
|
|
123
|
+
) {
|
|
86
124
|
throw "Not connected";
|
|
87
125
|
}
|
|
88
126
|
if (this.mqttConn) {
|
|
@@ -97,14 +135,29 @@ export class Context {
|
|
|
97
135
|
}
|
|
98
136
|
|
|
99
137
|
async send(packet: AnyPacket) {
|
|
100
|
-
logger.debug({
|
|
101
|
-
if (
|
|
102
|
-
this.connectionState === ConnectionState.connected
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
138
|
+
logger.debug("client.ctx.send", this.#connectionState, { packet });
|
|
139
|
+
if (!this.mqttConn?.isClosed) {
|
|
140
|
+
if (this.connectionState === ConnectionState.connected) {
|
|
141
|
+
await this.mqttConn?.send(packet);
|
|
142
|
+
this.pingTimer?.reset();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (
|
|
146
|
+
this.connectionState === ConnectionState.connecting &&
|
|
147
|
+
packet.type === PacketType.auth
|
|
148
|
+
) {
|
|
149
|
+
await this.mqttConn?.send(packet);
|
|
150
|
+
this.pingTimer?.reset();
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (
|
|
154
|
+
this.connectionState === ConnectionState.authenticating &&
|
|
155
|
+
!blockedDuringAuthentication(packet.type)
|
|
156
|
+
) {
|
|
157
|
+
await this.mqttConn?.send(packet);
|
|
158
|
+
this.pingTimer?.reset();
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
108
161
|
}
|
|
109
162
|
logger.debug("not connected");
|
|
110
163
|
this.pingTimer?.clear();
|
|
@@ -122,6 +175,7 @@ export class Context {
|
|
|
122
175
|
connectPacket: ConnectPacket,
|
|
123
176
|
): Promise<boolean> {
|
|
124
177
|
this.mqttConn = new MqttConn({ conn });
|
|
178
|
+
this.mqttConn.codecOpts.protocolLevel = connectPacket.protocolLevel;
|
|
125
179
|
try {
|
|
126
180
|
logger.debug("Send connect packet", connectPacket);
|
|
127
181
|
await this.connect(connectPacket);
|
|
@@ -136,7 +190,7 @@ export class Context {
|
|
|
136
190
|
`Caught something that is not an instance of Error: ${err}`,
|
|
137
191
|
);
|
|
138
192
|
queueMicrotask(() => this.#client.onError(err));
|
|
139
|
-
logger.debug(
|
|
193
|
+
logger.debug("error", err);
|
|
140
194
|
if (!this.mqttConn.isClosed) {
|
|
141
195
|
this.mqttConn.close();
|
|
142
196
|
}
|
|
@@ -164,7 +218,7 @@ export class Context {
|
|
|
164
218
|
await this.send(packet);
|
|
165
219
|
return;
|
|
166
220
|
}
|
|
167
|
-
packet.id = this.store.nextId();
|
|
221
|
+
packet.id = await this.store.nextId();
|
|
168
222
|
this.store.pendingOutgoing.set(packet.id, packet);
|
|
169
223
|
const deferred = new Deferred<void>();
|
|
170
224
|
this.unresolvedPublish.set(packet.id, deferred);
|
|
@@ -173,7 +227,7 @@ export class Context {
|
|
|
173
227
|
}
|
|
174
228
|
|
|
175
229
|
async subscribe(packet: SubscribePacket): Promise<ReturnCodes> {
|
|
176
|
-
packet.id = this.store.nextId();
|
|
230
|
+
packet.id = await this.store.nextId();
|
|
177
231
|
this.store.pendingOutgoing.set(packet.id, packet);
|
|
178
232
|
const deferred = new Deferred<ReturnCodes>();
|
|
179
233
|
this.unresolvedSubscribe.set(packet.id, deferred);
|
|
@@ -182,7 +236,7 @@ export class Context {
|
|
|
182
236
|
}
|
|
183
237
|
|
|
184
238
|
async unsubscribe(packet: UnsubscribePacket): Promise<void> {
|
|
185
|
-
packet.id = this.store.nextId();
|
|
239
|
+
packet.id = await this.store.nextId();
|
|
186
240
|
this.store.pendingOutgoing.set(packet.id, packet);
|
|
187
241
|
const deferred = new Deferred<void>();
|
|
188
242
|
this.unresolvedUnSubscribe.set(packet.id, deferred);
|
package/client/deps.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type {
|
|
2
2
|
AnyPacket,
|
|
3
|
+
AuthPacket,
|
|
3
4
|
ConnackPacket,
|
|
4
5
|
ConnectPacket,
|
|
5
6
|
DisconnectPacket,
|
|
@@ -18,6 +19,7 @@ export type {
|
|
|
18
19
|
SubscribePacket,
|
|
19
20
|
TAuthenticationResult,
|
|
20
21
|
Topic,
|
|
22
|
+
TPacketType,
|
|
21
23
|
TReasonCode,
|
|
22
24
|
UnsubackPacket,
|
|
23
25
|
UnsubscribePacket,
|
|
@@ -31,6 +33,7 @@ export {
|
|
|
31
33
|
MQTTLevel,
|
|
32
34
|
PacketNameByType,
|
|
33
35
|
PacketType,
|
|
36
|
+
ReasonCode,
|
|
34
37
|
ReasonCodeByNumber,
|
|
35
38
|
} from "../mqttPacket/mod.ts";
|
|
36
39
|
|
|
@@ -39,3 +42,4 @@ export type { SockConn } from "../socket/socket.ts";
|
|
|
39
42
|
export { Timer } from "../timer/timer.ts";
|
|
40
43
|
export { BufferedAsyncIterable, Deferred, logger } from "../utils/mod.ts";
|
|
41
44
|
export { MemoryStore } from "./store/memoryStore.ts";
|
|
45
|
+
export type { IStore } from "./store/store.ts";
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import { handleAuth } from "./handleAuth.ts";
|
|
4
|
+
import { ConnectionState } from "../ConnectionState.ts";
|
|
5
|
+
import { PacketType, ReasonCode } from "../deps.ts";
|
|
6
|
+
import type { AuthPacket } from "../deps.ts";
|
|
7
|
+
import type { AuthenticatedResult } from "../context.ts";
|
|
8
|
+
import { Deferred } from "../../utils/mod.ts";
|
|
9
|
+
|
|
10
|
+
function createMockContext() {
|
|
11
|
+
const sentPackets: unknown[] = [];
|
|
12
|
+
return {
|
|
13
|
+
connectionState: ConnectionState.connecting as string,
|
|
14
|
+
pingTimer: { clear: () => {} },
|
|
15
|
+
unresolvedConnect: new Deferred<number>(),
|
|
16
|
+
authHandler: (
|
|
17
|
+
_ctx: unknown,
|
|
18
|
+
_authMethod: string,
|
|
19
|
+
_authData: Uint8Array,
|
|
20
|
+
): Promise<AuthenticatedResult> => {
|
|
21
|
+
return Promise.resolve({
|
|
22
|
+
reasonCode: ReasonCode.continueAuthentication,
|
|
23
|
+
authData: new Uint8Array([1, 2, 3]),
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
send: (packet: unknown) => {
|
|
27
|
+
sentPackets.push(packet);
|
|
28
|
+
},
|
|
29
|
+
sentPackets,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
test("handleAuth sets connected state on ReasonCode.success", async () => {
|
|
34
|
+
const ctx = createMockContext();
|
|
35
|
+
const packet: AuthPacket = {
|
|
36
|
+
type: PacketType.auth,
|
|
37
|
+
protocolLevel: 5 as const,
|
|
38
|
+
reasonCode: ReasonCode.success,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
await handleAuth(ctx as never, packet);
|
|
42
|
+
|
|
43
|
+
assert.deepStrictEqual(
|
|
44
|
+
ctx.connectionState,
|
|
45
|
+
ConnectionState.connected,
|
|
46
|
+
"Should set connection state to connected when reasonCode is success",
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("handleAuth handles authentication failure when connecting", async () => {
|
|
51
|
+
const ctx = createMockContext();
|
|
52
|
+
ctx.connectionState = ConnectionState.connecting;
|
|
53
|
+
|
|
54
|
+
const packet: AuthPacket = {
|
|
55
|
+
type: PacketType.auth,
|
|
56
|
+
protocolLevel: 5 as const,
|
|
57
|
+
reasonCode: ReasonCode.badAuthenticationMethod,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
await handleAuth(ctx as never, packet);
|
|
61
|
+
|
|
62
|
+
assert.deepStrictEqual(
|
|
63
|
+
ctx.connectionState,
|
|
64
|
+
ConnectionState.disconnecting,
|
|
65
|
+
"Should transition state to disconnecting on failure during connect",
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
await assert.rejects(
|
|
69
|
+
ctx.unresolvedConnect.promise,
|
|
70
|
+
/Connect failed/,
|
|
71
|
+
"Should reject unresolvedConnect with connect failed error",
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("handleAuth throws error on authentication failure when connected", async () => {
|
|
76
|
+
const ctx = createMockContext();
|
|
77
|
+
ctx.connectionState = ConnectionState.connected;
|
|
78
|
+
|
|
79
|
+
const packet: AuthPacket = {
|
|
80
|
+
type: PacketType.auth,
|
|
81
|
+
protocolLevel: 5 as const,
|
|
82
|
+
reasonCode: ReasonCode.badAuthenticationMethod,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
await assert.rejects(
|
|
86
|
+
async () => {
|
|
87
|
+
await handleAuth(ctx as never, packet);
|
|
88
|
+
},
|
|
89
|
+
Error,
|
|
90
|
+
"Should throw an error if reasonCode indicates failure after already connected",
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("handleAuth throws error if authMethod or authData is missing", async () => {
|
|
95
|
+
const ctx = createMockContext();
|
|
96
|
+
const packet: AuthPacket = {
|
|
97
|
+
type: PacketType.auth,
|
|
98
|
+
protocolLevel: 5 as const,
|
|
99
|
+
reasonCode: ReasonCode.continueAuthentication,
|
|
100
|
+
properties: {
|
|
101
|
+
authenticationMethod: "SCRAM-SHA-256",
|
|
102
|
+
// authenticationData missing
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
await assert.rejects(
|
|
107
|
+
async () => {
|
|
108
|
+
await handleAuth(ctx as never, packet);
|
|
109
|
+
},
|
|
110
|
+
/Auth method and\/or Auth data missing/,
|
|
111
|
+
"Should throw when missing required auth properties",
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("handleAuth transitions state and sends response packet on continueAuthentication success", async () => {
|
|
116
|
+
const ctx = createMockContext();
|
|
117
|
+
ctx.connectionState = ConnectionState.connected;
|
|
118
|
+
|
|
119
|
+
ctx.authHandler = () =>
|
|
120
|
+
Promise.resolve({
|
|
121
|
+
reasonCode: ReasonCode.continueAuthentication,
|
|
122
|
+
authData: new Uint8Array([4, 5, 6]),
|
|
123
|
+
reasonString: "Continue",
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const packet: AuthPacket = {
|
|
127
|
+
type: PacketType.auth,
|
|
128
|
+
protocolLevel: 5 as const,
|
|
129
|
+
reasonCode: ReasonCode.continueAuthentication,
|
|
130
|
+
properties: {
|
|
131
|
+
authenticationMethod: "SCRAM-SHA-256",
|
|
132
|
+
authenticationData: new Uint8Array([1, 2, 3]),
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
await handleAuth(ctx as never, packet);
|
|
137
|
+
|
|
138
|
+
assert.deepStrictEqual(
|
|
139
|
+
ctx.connectionState,
|
|
140
|
+
ConnectionState.authenticating,
|
|
141
|
+
"Should transition connection state to authenticating",
|
|
142
|
+
);
|
|
143
|
+
assert.deepStrictEqual(
|
|
144
|
+
ctx.sentPackets.length,
|
|
145
|
+
1,
|
|
146
|
+
"Should send a response auth packet",
|
|
147
|
+
);
|
|
148
|
+
assert.deepStrictEqual(ctx.sentPackets[0], {
|
|
149
|
+
type: PacketType.auth,
|
|
150
|
+
protocolLevel: 5,
|
|
151
|
+
reasonCode: ReasonCode.continueAuthentication,
|
|
152
|
+
properties: {
|
|
153
|
+
authenticationMethod: "SCRAM-SHA-256",
|
|
154
|
+
authenticationData: new Uint8Array([4, 5, 6]),
|
|
155
|
+
reasonString: "Continue",
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test("handleAuth handles failure result from authHandler", async () => {
|
|
161
|
+
const ctx = createMockContext();
|
|
162
|
+
ctx.connectionState = ConnectionState.connecting;
|
|
163
|
+
|
|
164
|
+
ctx.authHandler = () =>
|
|
165
|
+
Promise.resolve({
|
|
166
|
+
reasonCode: ReasonCode.notAuthorized,
|
|
167
|
+
reasonString: "Not authorized to proceed",
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const packet: AuthPacket = {
|
|
171
|
+
type: PacketType.auth,
|
|
172
|
+
protocolLevel: 5 as const,
|
|
173
|
+
reasonCode: ReasonCode.continueAuthentication,
|
|
174
|
+
properties: {
|
|
175
|
+
authenticationMethod: "SCRAM-SHA-256",
|
|
176
|
+
authenticationData: new Uint8Array([1, 2, 3]),
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
await handleAuth(ctx as never, packet);
|
|
181
|
+
|
|
182
|
+
assert.deepStrictEqual(
|
|
183
|
+
ctx.connectionState,
|
|
184
|
+
ConnectionState.disconnecting,
|
|
185
|
+
"Should set state to disconnecting on authHandler failure",
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
await assert.rejects(
|
|
189
|
+
ctx.unresolvedConnect.promise,
|
|
190
|
+
/Connect failed: Not authorized to proceed/,
|
|
191
|
+
"Should reject unresolvedConnect with the reasonString provided by authHandler",
|
|
192
|
+
);
|
|
193
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { AuthenticatedResult, Context } from "../context.ts";
|
|
2
|
+
import { ConnectionState } from "../ConnectionState.ts";
|
|
3
|
+
import { PacketType, ReasonCode, ReasonCodeByNumber } from "../deps.ts";
|
|
4
|
+
import type { AuthPacket } from "../deps.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Handle error
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
function handleError(ctx: Context, errMsg: string) {
|
|
11
|
+
if (ctx.connectionState === ConnectionState.connecting) {
|
|
12
|
+
const err = new Error(
|
|
13
|
+
`Connect failed: ${errMsg}`,
|
|
14
|
+
);
|
|
15
|
+
ctx.connectionState = ConnectionState.disconnecting;
|
|
16
|
+
ctx.pingTimer?.clear();
|
|
17
|
+
ctx.unresolvedConnect?.reject(err);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
throw new Error(errMsg);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Handle success
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
async function handleResult(
|
|
28
|
+
ctx: Context,
|
|
29
|
+
authMethod: string,
|
|
30
|
+
result: AuthenticatedResult,
|
|
31
|
+
) {
|
|
32
|
+
await ctx.send({
|
|
33
|
+
type: PacketType.auth,
|
|
34
|
+
protocolLevel: 5,
|
|
35
|
+
reasonCode: result.reasonCode,
|
|
36
|
+
properties: result.authData
|
|
37
|
+
? {
|
|
38
|
+
authenticationMethod: authMethod,
|
|
39
|
+
authenticationData: result.authData,
|
|
40
|
+
reasonString: result.reasonString,
|
|
41
|
+
}
|
|
42
|
+
: {},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Handles v5 Auth packet
|
|
48
|
+
* @param ctx - The connection context containing send method
|
|
49
|
+
* @returns Promise that resolves
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
export async function handleAuth(
|
|
53
|
+
ctx: Context,
|
|
54
|
+
authPacket: AuthPacket,
|
|
55
|
+
): Promise<void> {
|
|
56
|
+
const reasonCode = authPacket.reasonCode;
|
|
57
|
+
if (reasonCode === ReasonCode.success) {
|
|
58
|
+
// we are connected again
|
|
59
|
+
ctx.connectionState = ConnectionState.connected;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (reasonCode !== ReasonCode.continueAuthentication) {
|
|
64
|
+
// something went wrong
|
|
65
|
+
handleError(ctx, ReasonCodeByNumber[reasonCode]);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// we need to send something back
|
|
70
|
+
if (ctx.connectionState === ConnectionState.connected) {
|
|
71
|
+
// pauze auther activities
|
|
72
|
+
ctx.connectionState = ConnectionState.authenticating;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const authMethod = authPacket.properties?.authenticationMethod;
|
|
76
|
+
const authData = authPacket.properties?.authenticationData;
|
|
77
|
+
if (!(authMethod && authData)) {
|
|
78
|
+
throw new Error("Auth method and/or Auth data missing");
|
|
79
|
+
}
|
|
80
|
+
const result = await ctx.authHandler(
|
|
81
|
+
ctx,
|
|
82
|
+
authMethod,
|
|
83
|
+
authData,
|
|
84
|
+
);
|
|
85
|
+
if (result.reasonCode === ReasonCode.continueAuthentication) {
|
|
86
|
+
return handleResult(ctx, authMethod, result);
|
|
87
|
+
}
|
|
88
|
+
return handleError(ctx, result.reasonString || "Error during authentication");
|
|
89
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import { handleConnack } from "./handleConnack.ts";
|
|
4
|
+
import { ConnectionState } from "../ConnectionState.ts";
|
|
5
|
+
import { AuthenticationResult, MQTTLevel } from "../deps.ts";
|
|
6
|
+
import type { ConnackPacket } from "../deps.ts";
|
|
7
|
+
import { Deferred } from "../../utils/mod.ts";
|
|
8
|
+
|
|
9
|
+
function createMockContext() {
|
|
10
|
+
const sentPackets: unknown[] = [];
|
|
11
|
+
return {
|
|
12
|
+
connectionState: ConnectionState.connecting as string,
|
|
13
|
+
protocolLevel: 4 as const,
|
|
14
|
+
mqttConn: { codecOpts: { protocolLevel: MQTTLevel.unknown } },
|
|
15
|
+
pingTimer: { reset: () => {}, clear: () => {} },
|
|
16
|
+
unresolvedConnect: new Deferred<number>(),
|
|
17
|
+
store: {
|
|
18
|
+
pendingOutgoing: new Map(),
|
|
19
|
+
pendingIncoming: new Map(),
|
|
20
|
+
pendingAckOutgoing: new Map(),
|
|
21
|
+
async *pendingOutgoingPackets() {},
|
|
22
|
+
},
|
|
23
|
+
send: (packet: unknown) => {
|
|
24
|
+
sentPackets.push(packet);
|
|
25
|
+
},
|
|
26
|
+
sentPackets,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
test("handleConnack sets connected state on success", async () => {
|
|
31
|
+
const ctx = createMockContext();
|
|
32
|
+
const packet = {
|
|
33
|
+
type: 2,
|
|
34
|
+
protocolLevel: 4 as const,
|
|
35
|
+
sessionPresent: false,
|
|
36
|
+
returnCode: AuthenticationResult.ok,
|
|
37
|
+
} as ConnackPacket;
|
|
38
|
+
|
|
39
|
+
await handleConnack(ctx as never, packet);
|
|
40
|
+
|
|
41
|
+
assert.deepStrictEqual(
|
|
42
|
+
ctx.connectionState,
|
|
43
|
+
ConnectionState.connected,
|
|
44
|
+
"Should be connected after successful CONNACK",
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("handleConnack resolves connect promise on success", async () => {
|
|
49
|
+
const ctx = createMockContext();
|
|
50
|
+
const packet = {
|
|
51
|
+
type: 2,
|
|
52
|
+
protocolLevel: 4 as const,
|
|
53
|
+
sessionPresent: false,
|
|
54
|
+
returnCode: AuthenticationResult.ok,
|
|
55
|
+
} as ConnackPacket;
|
|
56
|
+
|
|
57
|
+
await handleConnack(ctx as never, packet);
|
|
58
|
+
|
|
59
|
+
const result = await ctx.unresolvedConnect.promise;
|
|
60
|
+
assert.deepStrictEqual(result, 0, "Should resolve with success code 0");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("handleConnack rejects on bad username/password", async () => {
|
|
64
|
+
const ctx = createMockContext();
|
|
65
|
+
const packet = {
|
|
66
|
+
type: 2,
|
|
67
|
+
protocolLevel: 4 as const,
|
|
68
|
+
sessionPresent: false,
|
|
69
|
+
returnCode: AuthenticationResult.badUsernameOrPassword,
|
|
70
|
+
} as ConnackPacket;
|
|
71
|
+
|
|
72
|
+
await handleConnack(ctx as never, packet);
|
|
73
|
+
|
|
74
|
+
assert.deepStrictEqual(
|
|
75
|
+
ctx.connectionState,
|
|
76
|
+
ConnectionState.disconnecting,
|
|
77
|
+
"Should be disconnecting on auth failure",
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
await assert.rejects(
|
|
81
|
+
ctx.unresolvedConnect.promise,
|
|
82
|
+
/Connect failed/,
|
|
83
|
+
"Should reject with connect failed error",
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("handleConnack rejects on not authorized", async () => {
|
|
88
|
+
const ctx = createMockContext();
|
|
89
|
+
const packet = {
|
|
90
|
+
type: 2,
|
|
91
|
+
protocolLevel: 4 as const,
|
|
92
|
+
sessionPresent: false,
|
|
93
|
+
returnCode: AuthenticationResult.notAuthorized,
|
|
94
|
+
} as ConnackPacket;
|
|
95
|
+
|
|
96
|
+
await handleConnack(ctx as never, packet);
|
|
97
|
+
|
|
98
|
+
assert.deepStrictEqual(
|
|
99
|
+
ctx.connectionState,
|
|
100
|
+
ConnectionState.disconnecting,
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
await assert.rejects(
|
|
104
|
+
ctx.unresolvedConnect.promise,
|
|
105
|
+
/Connect failed/,
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("handleConnack handles MQTT v5 reason codes", async () => {
|
|
110
|
+
const ctx = createMockContext();
|
|
111
|
+
(ctx as { protocolLevel: number }).protocolLevel = 5;
|
|
112
|
+
const packet = {
|
|
113
|
+
type: 2,
|
|
114
|
+
protocolLevel: 5 as const,
|
|
115
|
+
sessionPresent: false,
|
|
116
|
+
reasonCode: 0,
|
|
117
|
+
} as ConnackPacket;
|
|
118
|
+
|
|
119
|
+
await handleConnack(ctx as never, packet);
|
|
120
|
+
|
|
121
|
+
assert.deepStrictEqual(
|
|
122
|
+
ctx.connectionState,
|
|
123
|
+
ConnectionState.connected,
|
|
124
|
+
"Should be connected with v5 success reason code",
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("handleConnack resets ping timer on success", async () => {
|
|
129
|
+
let timerReset = false;
|
|
130
|
+
const ctx = createMockContext();
|
|
131
|
+
ctx.pingTimer = {
|
|
132
|
+
reset: () => {
|
|
133
|
+
timerReset = true;
|
|
134
|
+
},
|
|
135
|
+
clear: () => {},
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const packet = {
|
|
139
|
+
type: 2,
|
|
140
|
+
protocolLevel: 4 as const,
|
|
141
|
+
sessionPresent: false,
|
|
142
|
+
returnCode: AuthenticationResult.ok,
|
|
143
|
+
} as ConnackPacket;
|
|
144
|
+
|
|
145
|
+
await handleConnack(ctx as never, packet);
|
|
146
|
+
|
|
147
|
+
assert.deepStrictEqual(timerReset, true, "Ping timer should be reset");
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test("handleConnack clears ping timer on failure", async () => {
|
|
151
|
+
let timerCleared = false;
|
|
152
|
+
const ctx = createMockContext();
|
|
153
|
+
ctx.pingTimer = {
|
|
154
|
+
reset: () => {},
|
|
155
|
+
clear: () => {
|
|
156
|
+
timerCleared = true;
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const packet = {
|
|
161
|
+
type: 2,
|
|
162
|
+
protocolLevel: 4 as const,
|
|
163
|
+
sessionPresent: false,
|
|
164
|
+
returnCode: AuthenticationResult.badUsernameOrPassword,
|
|
165
|
+
} as ConnackPacket;
|
|
166
|
+
|
|
167
|
+
await handleConnack(ctx as never, packet);
|
|
168
|
+
assert.deepStrictEqual(timerCleared, true, "Ping timer should be cleared");
|
|
169
|
+
await assert.rejects(
|
|
170
|
+
ctx.unresolvedConnect.promise,
|
|
171
|
+
/Connect failed/,
|
|
172
|
+
);
|
|
173
|
+
});
|
|
@@ -5,20 +5,30 @@ import type { ConnackPacket, TReasonCode } from "../deps.ts";
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Handles the CONNACK packet received from the MQTT broker
|
|
8
|
-
* @param packet - The CONNACK packet containing the connection acknowledgment
|
|
9
8
|
* @param ctx - The connection context
|
|
9
|
+
* @param packet - The CONNACK packet containing the connection acknowledgment
|
|
10
10
|
* @returns Promise that resolves when handling is complete
|
|
11
11
|
*/
|
|
12
|
-
export async function handleConnack(
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
: packet.returnCode;
|
|
12
|
+
export async function handleConnack(ctx: Context, packet: ConnackPacket) {
|
|
13
|
+
const isVersion5 = packet.protocolLevel === 5;
|
|
14
|
+
const result = isVersion5 ? packet.reasonCode : packet.returnCode;
|
|
16
15
|
if (result === 0) {
|
|
17
16
|
ctx.connectionState = ConnectionState.connected;
|
|
18
17
|
if (ctx.mqttConn) {
|
|
19
18
|
ctx.mqttConn.codecOpts.protocolLevel = ctx.protocolLevel;
|
|
20
19
|
}
|
|
21
|
-
|
|
20
|
+
|
|
21
|
+
const serverKeepAlive = isVersion5
|
|
22
|
+
? packet.properties?.serverKeepAlive
|
|
23
|
+
: undefined;
|
|
24
|
+
|
|
25
|
+
if (serverKeepAlive === 0) {
|
|
26
|
+
ctx.pingTimer?.clear(); // Server disabled keepalive
|
|
27
|
+
} else if (serverKeepAlive !== undefined) {
|
|
28
|
+
ctx.setPingTimer(serverKeepAlive); // Server set a new interval
|
|
29
|
+
} else {
|
|
30
|
+
ctx.pingTimer?.reset(); // Default fallback for V4 or V5 without override
|
|
31
|
+
}
|
|
22
32
|
ctx.unresolvedConnect?.resolve(result);
|
|
23
33
|
// start transmitting packets that were queued before
|
|
24
34
|
for await (const packet of ctx.store.pendingOutgoingPackets()) {
|