@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
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import type { Duplex } from "node:stream";
|
|
2
|
+
|
|
3
|
+
export type SockAddr = NetAddr | UnixAddr | VsockAddr;
|
|
4
|
+
export interface NetAddr {
|
|
5
|
+
transport: "tcp" | "udp";
|
|
6
|
+
hostname: string;
|
|
7
|
+
port: number;
|
|
8
|
+
}
|
|
9
|
+
export interface UnixAddr {
|
|
10
|
+
transport: "unix" | "unixpacket";
|
|
11
|
+
path: string;
|
|
12
|
+
}
|
|
13
|
+
export interface VsockAddr {
|
|
14
|
+
transport: "vsock";
|
|
15
|
+
cid: number;
|
|
16
|
+
port: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type SockConn = {
|
|
20
|
+
stream: Duplex;
|
|
21
|
+
close: () => void;
|
|
22
|
+
localAddr?: SockAddr;
|
|
23
|
+
remoteAddr?: SockAddr;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export class Conn {
|
|
27
|
+
private stream: Duplex;
|
|
28
|
+
private closed: boolean;
|
|
29
|
+
private closer: () => void;
|
|
30
|
+
public remoteAddr: SockAddr | undefined;
|
|
31
|
+
private leftover: Uint8Array = new Uint8Array(0);
|
|
32
|
+
|
|
33
|
+
// Store bound event listeners so we can cleanly remove them later
|
|
34
|
+
private onStreamClose = () => {
|
|
35
|
+
this.closed = true;
|
|
36
|
+
};
|
|
37
|
+
private onStreamError = () => {
|
|
38
|
+
this.closed = true;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
constructor(sockConn: SockConn) {
|
|
42
|
+
this.stream = sockConn.stream;
|
|
43
|
+
this.closed = false;
|
|
44
|
+
this.closer = sockConn.close;
|
|
45
|
+
this.remoteAddr = sockConn.remoteAddr;
|
|
46
|
+
|
|
47
|
+
// Attach listeners to update internal state on stream termination
|
|
48
|
+
this.stream.on("close", this.onStreamClose);
|
|
49
|
+
this.stream.on("error", this.onStreamError);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async read(length: number): Promise<Uint8Array | null> {
|
|
53
|
+
if (this.closed || length < 0) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (length === 0) {
|
|
58
|
+
return new Uint8Array(0);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const result = new Uint8Array(length);
|
|
62
|
+
let bytesAccumulated = 0;
|
|
63
|
+
|
|
64
|
+
// 1. Process leftover data from the previous read operation
|
|
65
|
+
if (this.leftover.byteLength > 0) {
|
|
66
|
+
const take = Math.min(this.leftover.byteLength, length);
|
|
67
|
+
result.set(this.leftover.subarray(0, take), bytesAccumulated);
|
|
68
|
+
bytesAccumulated += take;
|
|
69
|
+
this.leftover = this.leftover.subarray(take);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 2. Loop until the requested number of bytes is accumulated
|
|
73
|
+
while (bytesAccumulated < length) {
|
|
74
|
+
if (this.closed || !this.stream.readable) {
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const chunk = this.stream.read();
|
|
79
|
+
if (chunk === null) {
|
|
80
|
+
await new Promise<void>((resolve) => {
|
|
81
|
+
const cleanup = () => {
|
|
82
|
+
this.stream.off("readable", onEvent);
|
|
83
|
+
this.stream.off("end", onEvent);
|
|
84
|
+
this.stream.off("error", onEvent);
|
|
85
|
+
this.stream.off("close", onEvent);
|
|
86
|
+
};
|
|
87
|
+
const onEvent = () => {
|
|
88
|
+
cleanup();
|
|
89
|
+
resolve();
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
this.stream.on("readable", onEvent);
|
|
93
|
+
this.stream.on("end", onEvent);
|
|
94
|
+
this.stream.on("error", onEvent);
|
|
95
|
+
this.stream.on("close", onEvent);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// 3. Process the retrieved chunk
|
|
102
|
+
const chunkLength = chunk.byteLength;
|
|
103
|
+
const needed = length - bytesAccumulated;
|
|
104
|
+
|
|
105
|
+
if (chunkLength <= needed) {
|
|
106
|
+
result.set(chunk, bytesAccumulated);
|
|
107
|
+
bytesAccumulated += chunkLength;
|
|
108
|
+
} else {
|
|
109
|
+
result.set(chunk.subarray(0, needed), bytesAccumulated);
|
|
110
|
+
bytesAccumulated += needed;
|
|
111
|
+
this.leftover = chunk.subarray(needed);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (bytesAccumulated < length) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
write(data: Uint8Array): Promise<number> {
|
|
123
|
+
if (this.closed || !this.stream.writable) {
|
|
124
|
+
return Promise.reject(new Error("Stream is closed or not writable"));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return new Promise((resolve, reject) => {
|
|
128
|
+
// 1. Fire the write command and catch any immediate/async errors via the callback
|
|
129
|
+
const canWriteMore = this.stream.write(data, (err) => {
|
|
130
|
+
if (err) {
|
|
131
|
+
reject(err);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// 2. Determine when to resolve based on the return value of write()
|
|
136
|
+
if (canWriteMore) {
|
|
137
|
+
// If the buffer is not full, we can resolve immediately
|
|
138
|
+
resolve(data.length);
|
|
139
|
+
} else {
|
|
140
|
+
// If backpressure is triggered, we must wait for the 'drain' event
|
|
141
|
+
this.stream.once("drain", () => {
|
|
142
|
+
resolve(data.length);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
close() {
|
|
149
|
+
if (!this.closed) {
|
|
150
|
+
this.closed = true;
|
|
151
|
+
|
|
152
|
+
// Clean up permanent event listeners to prevent memory leaks
|
|
153
|
+
this.stream.off("close", this.onStreamClose);
|
|
154
|
+
this.stream.off("error", this.onStreamError);
|
|
155
|
+
|
|
156
|
+
// Safely destroy the stream first, then trigger the closer callback
|
|
157
|
+
try {
|
|
158
|
+
this.stream.destroy();
|
|
159
|
+
// deno-coverage-ignore
|
|
160
|
+
} catch (_) {
|
|
161
|
+
// Suppress stream destruction errors
|
|
162
|
+
// deno-coverage-ignore
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
this.closer();
|
|
167
|
+
// deno-coverage-ignore
|
|
168
|
+
} catch (_) {
|
|
169
|
+
// Prevent closer failures from crashing the thread
|
|
170
|
+
// deno-coverage-ignore
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { getFileData, TcpClient } from "./tcpClient.ts";
|
|
7
|
+
|
|
8
|
+
// most client testing is already done in tcpServer.test.ts
|
|
9
|
+
|
|
10
|
+
test("Test getFileData - valid file, empty file and undefined", async () => {
|
|
11
|
+
// Create a unique temporary directory using native NodeJS path/fs utilities
|
|
12
|
+
const tempDir = await mkdtemp(join(tmpdir(), "mqtt-client-test-"));
|
|
13
|
+
|
|
14
|
+
const validFilePath = join(tempDir, "valid.txt");
|
|
15
|
+
const emptyFilePath = join(tempDir, "empty.txt");
|
|
16
|
+
const testContent = "Hello MQTT World!";
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
// 1. Test with a valid file containing data
|
|
20
|
+
await writeFile(validFilePath, testContent, "utf-8");
|
|
21
|
+
const result = await getFileData(validFilePath);
|
|
22
|
+
assert.strictEqual(
|
|
23
|
+
result,
|
|
24
|
+
testContent,
|
|
25
|
+
"Should return the correct content of the file",
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// 2. Test with an empty file
|
|
29
|
+
await writeFile(emptyFilePath, "", "utf-8");
|
|
30
|
+
const emptyResult = await getFileData(emptyFilePath);
|
|
31
|
+
assert.strictEqual(
|
|
32
|
+
emptyResult,
|
|
33
|
+
undefined,
|
|
34
|
+
"Should return undefined if the file is empty",
|
|
35
|
+
);
|
|
36
|
+
} finally {
|
|
37
|
+
// Clean up the temporary directory and all its contents
|
|
38
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 3. Test with undefined filename
|
|
42
|
+
const undefinedResult = await getFileData(undefined);
|
|
43
|
+
assert.strictEqual(
|
|
44
|
+
undefinedResult,
|
|
45
|
+
undefined,
|
|
46
|
+
"Should return undefined immediately if filename is undefined",
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("Test createConn - unsupported protocol", async () => {
|
|
51
|
+
const client = new TcpClient();
|
|
52
|
+
|
|
53
|
+
// Use an unsupported protocol like 'ftp://' to trigger the throw in createConn
|
|
54
|
+
const invalidParams = {
|
|
55
|
+
url: new URL("ftp://localhost:1883"),
|
|
56
|
+
numberOfRetries: 0,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Assert that connect rejects with the specific "Unsupported protocol" error
|
|
60
|
+
await assert.rejects(
|
|
61
|
+
async () => {
|
|
62
|
+
await client.connect(invalidParams);
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "Error",
|
|
66
|
+
message: "Unsupported protocol: ftp:",
|
|
67
|
+
},
|
|
68
|
+
"Should throw an error when an unsupported protocol is provided",
|
|
69
|
+
);
|
|
70
|
+
});
|
package/node/tcpClient.ts
CHANGED
|
@@ -65,9 +65,10 @@ export class TcpClient extends Client {
|
|
|
65
65
|
const opts = {
|
|
66
66
|
host: hostname,
|
|
67
67
|
port,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
ca,
|
|
69
|
+
key,
|
|
70
|
+
cert,
|
|
71
|
+
minVersion: "TLSv1.3" as const,
|
|
71
72
|
};
|
|
72
73
|
logger.debug({ hostname, port, ca, cert });
|
|
73
74
|
return new Promise((resolve, reject) => {
|
|
@@ -82,16 +83,16 @@ export class TcpClient extends Client {
|
|
|
82
83
|
});
|
|
83
84
|
}
|
|
84
85
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
hostname:
|
|
88
|
-
port
|
|
89
|
-
caCerts
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
86
|
+
// overload createConn from the base client class
|
|
87
|
+
protected override createConn(): Promise<SockConn> {
|
|
88
|
+
const { protocol, hostname, port: portStr } = this.connectUrl;
|
|
89
|
+
const port = Number(portStr);
|
|
90
|
+
const caCerts = this.caCerts;
|
|
91
|
+
const cert = this.cert;
|
|
92
|
+
const key = this.key;
|
|
93
|
+
|
|
93
94
|
if (protocol === "mqtts:") {
|
|
94
|
-
return this.connectMQTTS(hostname, port, caCerts);
|
|
95
|
+
return this.connectMQTTS(hostname, port, caCerts, cert, key);
|
|
95
96
|
}
|
|
96
97
|
if (protocol === "mqtt:") {
|
|
97
98
|
return this.connectMQTT(hostname, port);
|
package/node/tcpServer.test.ts
CHANGED
|
@@ -3,14 +3,12 @@ import assert from "node:assert/strict";
|
|
|
3
3
|
import { TcpClient } from "./tcpClient.ts";
|
|
4
4
|
import { TcpServer } from "./tcpServer.ts";
|
|
5
5
|
import { logger, LogLevel } from "../utils/mod.ts";
|
|
6
|
-
import
|
|
6
|
+
import { delay } from "../dev_utils/mod.ts";
|
|
7
|
+
import type { ProtocolLevel, PublishPacket, QoS } from "../mqttPacket/mod.ts";
|
|
7
8
|
|
|
8
9
|
logger.level(LogLevel.info);
|
|
9
|
-
export function sleep(ms: number): Promise<unknown> {
|
|
10
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
11
|
-
}
|
|
12
10
|
|
|
13
|
-
test("Test pubSub using client and server", async
|
|
11
|
+
test("Test pubSub using client and server", async () => {
|
|
14
12
|
const server = new TcpServer({ port: 0 }, {});
|
|
15
13
|
server.start();
|
|
16
14
|
|
|
@@ -52,17 +50,17 @@ test("Test pubSub using client and server", async function () {
|
|
|
52
50
|
});
|
|
53
51
|
|
|
54
52
|
// the IIFE ensures message reception runs in parallel
|
|
55
|
-
logger.verbose(
|
|
53
|
+
logger.verbose("Start receiving");
|
|
56
54
|
const received: PublishPacket[] = [];
|
|
57
|
-
(async
|
|
55
|
+
(async () => {
|
|
58
56
|
for await (const item of client.messages()) {
|
|
59
|
-
logger.verbose(
|
|
57
|
+
logger.verbose("Receiving:", item.topic, "--", item.qos);
|
|
60
58
|
received.push(item);
|
|
61
59
|
}
|
|
62
60
|
})();
|
|
63
61
|
// end of IIFE
|
|
64
62
|
for (const item of publishSet) {
|
|
65
|
-
logger.verbose(
|
|
63
|
+
logger.verbose("Publishing:", item.topic, "--", item.qos);
|
|
66
64
|
await client.publish({
|
|
67
65
|
topic: item.topic,
|
|
68
66
|
qos: item.qos,
|
|
@@ -70,24 +68,24 @@ test("Test pubSub using client and server", async function () {
|
|
|
70
68
|
});
|
|
71
69
|
}
|
|
72
70
|
|
|
73
|
-
await
|
|
74
|
-
logger.verbose(
|
|
71
|
+
await delay(100);
|
|
72
|
+
logger.verbose("Disconnect client");
|
|
75
73
|
await client.disconnect();
|
|
76
74
|
|
|
77
|
-
logger.verbose(
|
|
75
|
+
logger.verbose("Check completeness");
|
|
78
76
|
for (const item of publishSet) {
|
|
79
77
|
const found = received.find((f) =>
|
|
80
78
|
f.topic == item.topic && f.qos === item.qos
|
|
81
79
|
);
|
|
82
|
-
logger.verbose(
|
|
80
|
+
logger.verbose("Found:", item.topic, "--", item.qos);
|
|
83
81
|
assert(found, `${item.topic} -- ${item.qos}`);
|
|
84
82
|
}
|
|
85
83
|
|
|
86
|
-
logger.verbose(
|
|
84
|
+
logger.verbose("Stop server");
|
|
87
85
|
server.stop();
|
|
88
86
|
});
|
|
89
87
|
|
|
90
|
-
test("Test subscription persistence after reconnect", async
|
|
88
|
+
test("Test subscription persistence after reconnect", async () => {
|
|
91
89
|
// Start server
|
|
92
90
|
const server = new TcpServer({ port: 0 }, {});
|
|
93
91
|
server.start();
|
|
@@ -95,8 +93,14 @@ test("Test subscription persistence after reconnect", async function () {
|
|
|
95
93
|
const params = {
|
|
96
94
|
url: new URL(`mqtt://${server.address}:${server.port}`),
|
|
97
95
|
numberOfRetries: 0,
|
|
96
|
+
options: {
|
|
97
|
+
protocolLevel: 4 as ProtocolLevel,
|
|
98
|
+
clean: false,
|
|
99
|
+
},
|
|
98
100
|
};
|
|
99
101
|
|
|
102
|
+
logger.verbose("client parameters: ", params);
|
|
103
|
+
|
|
100
104
|
const client = new TcpClient();
|
|
101
105
|
const testTopic = "test/topic";
|
|
102
106
|
const received: PublishPacket[] = [];
|
|
@@ -111,7 +115,7 @@ test("Test subscription persistence after reconnect", async function () {
|
|
|
111
115
|
});
|
|
112
116
|
|
|
113
117
|
// Start receiving messages
|
|
114
|
-
(async
|
|
118
|
+
(async () => {
|
|
115
119
|
for await (const item of client.messages()) {
|
|
116
120
|
received.push(item);
|
|
117
121
|
}
|
|
@@ -119,11 +123,11 @@ test("Test subscription persistence after reconnect", async function () {
|
|
|
119
123
|
|
|
120
124
|
// Disconnect client
|
|
121
125
|
await client.disconnect();
|
|
122
|
-
await
|
|
126
|
+
await delay(100);
|
|
123
127
|
|
|
124
128
|
// Reconnect client
|
|
125
129
|
await client.connect(params);
|
|
126
|
-
await
|
|
130
|
+
await delay(100);
|
|
127
131
|
|
|
128
132
|
// Publish test message
|
|
129
133
|
await client.publish({
|
|
@@ -132,8 +136,8 @@ test("Test subscription persistence after reconnect", async function () {
|
|
|
132
136
|
payload: new Uint8Array([0x01]),
|
|
133
137
|
});
|
|
134
138
|
|
|
135
|
-
await
|
|
136
|
-
logger.verbose(
|
|
139
|
+
await delay(100);
|
|
140
|
+
logger.verbose("Disconnect client");
|
|
137
141
|
await client.disconnect();
|
|
138
142
|
|
|
139
143
|
// Verify message was received
|
package/node/tcpServer.ts
CHANGED
|
@@ -40,21 +40,26 @@ export class TcpServer {
|
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
stop() {
|
|
43
|
+
this.mqttServer.close();
|
|
43
44
|
this.server?.close();
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
get port() {
|
|
47
48
|
const address = this.server?.address();
|
|
49
|
+
// deno-coverage-ignore-start
|
|
48
50
|
if (typeof address === "object" && address !== null) {
|
|
49
51
|
return address?.port;
|
|
50
52
|
}
|
|
51
53
|
return this.serverOptions?.port;
|
|
54
|
+
// deno-coverage-ignore-stop
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
get address() {
|
|
55
58
|
const addressResult = this.server?.address();
|
|
59
|
+
// deno-coverage-ignore-start
|
|
56
60
|
if (typeof addressResult === "object") {
|
|
57
61
|
const address = addressResult?.address;
|
|
62
|
+
|
|
58
63
|
if (address === "::") {
|
|
59
64
|
return "localhost";
|
|
60
65
|
}
|
|
@@ -65,4 +70,5 @@ export class TcpServer {
|
|
|
65
70
|
}
|
|
66
71
|
return addressResult;
|
|
67
72
|
}
|
|
73
|
+
// deno-coverage-ignore-stop
|
|
68
74
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { TcpClient } from "./tcpClient.ts";
|
|
4
|
+
import { TlsServer } from "./tlsServer.ts";
|
|
5
|
+
import { logger, LogLevel } from "../utils/mod.ts";
|
|
6
|
+
import type { PublishPacket, QoS } from "../mqttPacket/mod.ts";
|
|
7
|
+
import { delay, generateLocalhostCerts } from "../dev_utils/mod.ts";
|
|
8
|
+
|
|
9
|
+
logger.level(LogLevel.info);
|
|
10
|
+
|
|
11
|
+
const { key, cert, caCert } = generateLocalhostCerts();
|
|
12
|
+
|
|
13
|
+
test("Test pubSub using client and server", async () => {
|
|
14
|
+
const server = new TlsServer({ port: 0, key, cert }, {});
|
|
15
|
+
server.start();
|
|
16
|
+
|
|
17
|
+
assert.deepStrictEqual(
|
|
18
|
+
server.port !== undefined,
|
|
19
|
+
true,
|
|
20
|
+
"server runs a a random port",
|
|
21
|
+
);
|
|
22
|
+
logger.verbose("server running on: ", {
|
|
23
|
+
port: server.port,
|
|
24
|
+
address: server.address,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const params = {
|
|
28
|
+
url: new URL(`mqtts://${server.address}:${server.port}`),
|
|
29
|
+
numberOfRetries: 0,
|
|
30
|
+
caCerts: [caCert],
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
logger.verbose("client parameters: ", params);
|
|
34
|
+
|
|
35
|
+
const client = new TcpClient();
|
|
36
|
+
|
|
37
|
+
await client.connect(params);
|
|
38
|
+
assert(true, "Client connected to server");
|
|
39
|
+
|
|
40
|
+
const publishSet: { topic: string; qos: QoS }[] = [
|
|
41
|
+
{ topic: "t0@q0", qos: 0 },
|
|
42
|
+
{ topic: "t1@q0", qos: 0 },
|
|
43
|
+
{ topic: "t2@q0", qos: 0 },
|
|
44
|
+
{ topic: "t0@q1", qos: 1 },
|
|
45
|
+
{ topic: "t1@q1", qos: 1 },
|
|
46
|
+
{ topic: "t2@q1", qos: 1 },
|
|
47
|
+
{ topic: "t0@q2", qos: 2 },
|
|
48
|
+
{ topic: "t1@q2", qos: 2 },
|
|
49
|
+
{ topic: "t2@q2", qos: 2 },
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
const subscriptions = publishSet.map((item) => ({
|
|
53
|
+
topicFilter: item.topic,
|
|
54
|
+
qos: item.qos,
|
|
55
|
+
}));
|
|
56
|
+
await client.subscribe({
|
|
57
|
+
subscriptions,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// the IIFE ensures message reception runs in parallel
|
|
61
|
+
logger.verbose("Start receiving");
|
|
62
|
+
const received: PublishPacket[] = [];
|
|
63
|
+
(async () => {
|
|
64
|
+
for await (const item of client.messages()) {
|
|
65
|
+
logger.verbose("Receiving:", item.topic, "--", item.qos);
|
|
66
|
+
received.push(item);
|
|
67
|
+
}
|
|
68
|
+
})();
|
|
69
|
+
// end of IIFE
|
|
70
|
+
for (const item of publishSet) {
|
|
71
|
+
logger.verbose("Publishing:", item.topic, "--", item.qos);
|
|
72
|
+
await client.publish({
|
|
73
|
+
topic: item.topic,
|
|
74
|
+
qos: item.qos,
|
|
75
|
+
payload: new Uint8Array([0x01]),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await delay(100);
|
|
80
|
+
logger.verbose("Disconnect client");
|
|
81
|
+
await client.disconnect();
|
|
82
|
+
|
|
83
|
+
logger.verbose("Check completeness");
|
|
84
|
+
for (const item of publishSet) {
|
|
85
|
+
const found = received.find((f) =>
|
|
86
|
+
f.topic == item.topic && f.qos === item.qos
|
|
87
|
+
);
|
|
88
|
+
logger.verbose("Found:", item.topic, "--", item.qos);
|
|
89
|
+
assert(found, `${item.topic} -- ${item.qos}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
logger.verbose("Stop server");
|
|
93
|
+
server.stop();
|
|
94
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This module provides a NodeJS specific implementation of a tls socket listener
|
|
3
|
+
* it uses the platform agnostic MqttServer class
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { Server } from "node:net";
|
|
7
|
+
import { createServer } from "node:tls";
|
|
8
|
+
import type { MqttServerOptions } from "../server/mod.ts";
|
|
9
|
+
import { MqttServer } from "../server/mod.ts";
|
|
10
|
+
import { wrapNodeSocket } from "./wrapNodeSocket.ts";
|
|
11
|
+
|
|
12
|
+
type ServerOptions = {
|
|
13
|
+
hostname?: string;
|
|
14
|
+
port?: number;
|
|
15
|
+
key: string;
|
|
16
|
+
cert: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
* TCP server that wraps a MqttServer, see demoServer.ts in the /bin folder
|
|
21
|
+
*/
|
|
22
|
+
export class TlsServer {
|
|
23
|
+
private mqttServer: MqttServer;
|
|
24
|
+
private server?: Server;
|
|
25
|
+
private serverOptions;
|
|
26
|
+
|
|
27
|
+
constructor(serverOptions: ServerOptions, mqttOptions: MqttServerOptions) {
|
|
28
|
+
this.mqttServer = new MqttServer(mqttOptions);
|
|
29
|
+
this.serverOptions = serverOptions;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async start() {
|
|
33
|
+
const tlsOptions = {
|
|
34
|
+
minVersion: "TLSv1.3" as const,
|
|
35
|
+
key: this.serverOptions.key,
|
|
36
|
+
cert: this.serverOptions.cert,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
this.server = createServer(
|
|
40
|
+
tlsOptions,
|
|
41
|
+
(sock) => this.mqttServer.serve(wrapNodeSocket(sock)),
|
|
42
|
+
);
|
|
43
|
+
const isListening = new Promise((resolve) => {
|
|
44
|
+
this.server?.on("listening", () => {
|
|
45
|
+
resolve(true);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
this.server.listen(this.serverOptions.port, this.serverOptions.hostname);
|
|
49
|
+
await isListening;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
stop() {
|
|
53
|
+
this.mqttServer.close();
|
|
54
|
+
this.server?.close();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get port() {
|
|
58
|
+
const address = this.server?.address();
|
|
59
|
+
if (typeof address === "object" && address !== null) {
|
|
60
|
+
return address?.port;
|
|
61
|
+
}
|
|
62
|
+
return this.serverOptions?.port;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get address() {
|
|
66
|
+
const addressResult = this.server?.address();
|
|
67
|
+
// deno-coverage-ignore-start
|
|
68
|
+
if (typeof addressResult === "object") {
|
|
69
|
+
const address = addressResult?.address;
|
|
70
|
+
if (address === "::") {
|
|
71
|
+
return "localhost";
|
|
72
|
+
}
|
|
73
|
+
if (address?.includes(":")) {
|
|
74
|
+
return `[${address}]`;
|
|
75
|
+
}
|
|
76
|
+
return address;
|
|
77
|
+
}
|
|
78
|
+
return addressResult;
|
|
79
|
+
}
|
|
80
|
+
// deno-coverage-ignore-stop
|
|
81
|
+
}
|
package/node/wrapNodeSocket.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Utility functions for wrapping Node.js sockets into standard web streams.
|
|
3
3
|
*/
|
|
4
4
|
import type { Socket } from "node:net";
|
|
5
|
-
import { Writable } from "node:stream";
|
|
5
|
+
import { Readable, Writable } from "node:stream";
|
|
6
6
|
import type { NetAddr, SockConn } from "../socket/socket.ts";
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -10,9 +10,11 @@ import type { NetAddr, SockConn } from "../socket/socket.ts";
|
|
|
10
10
|
* @param sock - The Node.js socket to close
|
|
11
11
|
*/
|
|
12
12
|
function closer(sock: Socket): void {
|
|
13
|
+
// deno-coverage-ignore-start
|
|
13
14
|
if (!sock.closed) {
|
|
14
15
|
sock.end();
|
|
15
16
|
}
|
|
17
|
+
// deno-coverage-ignore-stop
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
/**
|
|
@@ -21,41 +23,16 @@ function closer(sock: Socket): void {
|
|
|
21
23
|
* @returns A socket connection object with readable/writable streams and close method
|
|
22
24
|
*/
|
|
23
25
|
export function wrapNodeSocket(socket: Socket): SockConn {
|
|
24
|
-
const readable =
|
|
25
|
-
{
|
|
26
|
-
type: "bytes",
|
|
27
|
-
start(controller) {
|
|
28
|
-
socket.on("data", (data: Uint8Array<ArrayBuffer>) => {
|
|
29
|
-
controller.enqueue(data);
|
|
30
|
-
const desiredSize = controller.desiredSize ?? 0;
|
|
31
|
-
if (desiredSize <= 0) {
|
|
32
|
-
// The internal queue is full, so propagate
|
|
33
|
-
// the backpressure signal to the underlying source.
|
|
34
|
-
socket.pause();
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
socket.on("error", (err: unknown) => controller.error(err));
|
|
38
|
-
socket.on("end", () => {
|
|
39
|
-
// close the controller
|
|
40
|
-
controller.close();
|
|
41
|
-
// and unlock the last BYOB read request
|
|
42
|
-
controller.byobRequest?.respond(0);
|
|
43
|
-
});
|
|
44
|
-
},
|
|
45
|
-
pull: () => {
|
|
46
|
-
socket.resume();
|
|
47
|
-
},
|
|
48
|
-
cancel: () => {
|
|
49
|
-
socket.end();
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
);
|
|
26
|
+
const readable = Readable.toWeb(socket);
|
|
53
27
|
const writable = Writable.toWeb(socket);
|
|
28
|
+
|
|
29
|
+
// deno-coverage-ignore-start
|
|
54
30
|
const remoteAddr: NetAddr = {
|
|
55
31
|
hostname: socket.remoteAddress || "",
|
|
56
32
|
port: socket.remotePort || 0,
|
|
57
33
|
transport: "tcp",
|
|
58
34
|
};
|
|
35
|
+
// deno-coverage-ignore-stop
|
|
59
36
|
|
|
60
37
|
const conn: SockConn = {
|
|
61
38
|
readable: readable as ReadableStream<Uint8Array>,
|