@seriousme/opifex 1.11.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +1 -1
- package/README.md +102 -43
- package/bin/conformanceServer.ts +45 -13
- package/bin/demoServer.ts +38 -13
- package/bin/mqtt.ts +52 -30
- package/client/ConnectionState.ts +2 -0
- package/client/client.ts +57 -47
- package/client/context.ts +75 -21
- package/client/deps.ts +5 -0
- package/client/handlers/handleAuth.test.ts +193 -0
- package/client/handlers/handleAuth.ts +89 -0
- package/client/handlers/handleConnack.test.ts +173 -0
- package/client/handlers/handleConnack.ts +16 -6
- package/client/handlers/handleDisconnect.test.ts +22 -0
- package/client/handlers/handleDisconnect.ts +17 -0
- package/client/handlers/handlePacket.test.ts +242 -0
- package/client/handlers/handlePacket.ts +19 -5
- package/client/handlers/handlePuback.test.ts +99 -0
- package/client/handlers/handlePuback.ts +6 -0
- package/client/handlers/handlePubcomp.test.ts +112 -0
- package/client/handlers/handlePubcomp.ts +5 -0
- package/client/handlers/handlePublish.test.ts +188 -0
- package/client/handlers/handlePubrec.test.ts +119 -0
- package/client/handlers/handlePubrec.ts +5 -1
- package/client/handlers/handlePubrel.test.ts +136 -0
- package/client/handlers/handleSuback.test.ts +122 -0
- package/client/handlers/handleSuback.ts +3 -0
- package/client/handlers/handleUnsuback.test.ts +101 -0
- package/client/mod.ts +2 -2
- package/client/store/memoryStore.ts +2 -2
- package/client/store/store.ts +3 -1
- package/deno/README.md +1 -2
- package/deno/tcpClient.test.ts +75 -0
- package/deno/tcpClient.ts +16 -11
- package/deno/tcpServer.test.ts +22 -21
- package/deno/tcpServer.ts +5 -0
- package/deno/tlsServer.test.ts +97 -0
- package/deno/tlsServer.ts +42 -0
- package/deno/wsServer.test.ts +93 -0
- package/deno/wsServer.ts +73 -0
- package/dev_utils/generateCert.ts +95 -0
- package/dev_utils/mockConn.ts +36 -0
- package/dev_utils/mockServer.ts +28 -0
- package/dev_utils/mod.ts +30 -2
- package/dev_utils/packetHelpers.ts +404 -0
- package/dev_utils/test-handlers.ts +98 -0
- package/dev_utils/timers.ts +14 -0
- package/dev_utils/webStreamPair.test.ts +171 -0
- package/dev_utils/webStreamPair.ts +143 -0
- package/dist/bin/conformanceServer.js +17 -12
- package/dist/bin/conformanceServer.js.map +1 -1
- package/dist/bin/demoServer.js +16 -12
- package/dist/bin/demoServer.js.map +1 -1
- package/dist/bin/mqtt.js +19 -16
- package/dist/bin/mqtt.js.map +1 -1
- package/dist/client/ConnectionState.d.ts +2 -0
- package/dist/client/ConnectionState.d.ts.map +1 -1
- package/dist/client/ConnectionState.js +2 -0
- package/dist/client/ConnectionState.js.map +1 -1
- package/dist/client/client.d.ts +19 -22
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +34 -20
- package/dist/client/client.js.map +1 -1
- package/dist/client/context.d.ts +11 -3
- package/dist/client/context.d.ts.map +1 -1
- package/dist/client/context.js +44 -12
- package/dist/client/context.js.map +1 -1
- package/dist/client/deps.d.ts +3 -2
- package/dist/client/deps.d.ts.map +1 -1
- package/dist/client/deps.js +1 -1
- package/dist/client/deps.js.map +1 -1
- package/dist/client/handlers/handleAuth.d.ts +9 -0
- package/dist/client/handlers/handleAuth.d.ts.map +1 -0
- package/dist/client/handlers/handleAuth.js +66 -0
- package/dist/client/handlers/handleAuth.js.map +1 -0
- package/dist/client/handlers/handleConnack.d.ts +2 -2
- package/dist/client/handlers/handleConnack.d.ts.map +1 -1
- package/dist/client/handlers/handleConnack.js +16 -6
- package/dist/client/handlers/handleConnack.js.map +1 -1
- package/dist/client/handlers/handleDisconnect.d.ts +11 -0
- package/dist/client/handlers/handleDisconnect.d.ts.map +1 -0
- package/dist/client/handlers/handleDisconnect.js +15 -0
- package/dist/client/handlers/handleDisconnect.js.map +1 -0
- package/dist/client/handlers/handlePacket.d.ts.map +1 -1
- package/dist/client/handlers/handlePacket.js +14 -3
- package/dist/client/handlers/handlePacket.js.map +1 -1
- package/dist/client/handlers/handlePuback.d.ts.map +1 -1
- package/dist/client/handlers/handlePuback.js +5 -0
- package/dist/client/handlers/handlePuback.js.map +1 -1
- package/dist/client/handlers/handlePubcomp.d.ts.map +1 -1
- package/dist/client/handlers/handlePubcomp.js +5 -0
- package/dist/client/handlers/handlePubcomp.js.map +1 -1
- package/dist/client/handlers/handlePubrec.d.ts.map +1 -1
- package/dist/client/handlers/handlePubrec.js +5 -1
- package/dist/client/handlers/handlePubrec.js.map +1 -1
- package/dist/client/handlers/handleSuback.d.ts +1 -0
- package/dist/client/handlers/handleSuback.d.ts.map +1 -1
- package/dist/client/handlers/handleSuback.js +3 -0
- package/dist/client/handlers/handleSuback.js.map +1 -1
- package/dist/client/mod.d.ts +2 -2
- package/dist/client/mod.d.ts.map +1 -1
- package/dist/client/mod.js +1 -1
- package/dist/client/mod.js.map +1 -1
- package/dist/client/store/memoryStore.d.ts.map +1 -1
- package/dist/client/store/memoryStore.js +2 -2
- package/dist/client/store/memoryStore.js.map +1 -1
- package/dist/client/store/store.d.ts +2 -1
- package/dist/client/store/store.d.ts.map +1 -1
- package/dist/client/store/store.js +1 -1
- package/dist/client/store/store.js.map +1 -1
- package/dist/dev_utils/generateCert.d.ts +11 -0
- package/dist/dev_utils/generateCert.d.ts.map +1 -0
- package/dist/dev_utils/generateCert.js +76 -0
- package/dist/dev_utils/generateCert.js.map +1 -0
- package/dist/examples/authHandler.test.d.ts +2 -0
- package/dist/examples/authHandler.test.d.ts.map +1 -0
- package/dist/examples/authHandler.test.js +123 -0
- package/dist/examples/authHandler.test.js.map +1 -0
- package/dist/examples/mqtt.test.d.ts +2 -0
- package/dist/examples/mqtt.test.d.ts.map +1 -0
- package/dist/examples/mqtt.test.js +70 -0
- package/dist/examples/mqtt.test.js.map +1 -0
- package/dist/examples/mqtts.test.d.ts +2 -0
- package/dist/examples/mqtts.test.d.ts.map +1 -0
- package/dist/examples/mqtts.test.js +81 -0
- package/dist/examples/mqtts.test.js.map +1 -0
- package/dist/mqttConn/mqttConn.d.ts +25 -16
- package/dist/mqttConn/mqttConn.d.ts.map +1 -1
- package/dist/mqttConn/mqttConn.js +69 -40
- package/dist/mqttConn/mqttConn.js.map +1 -1
- package/dist/mqttPacket/AuthenticationResult.d.ts.map +1 -1
- package/dist/mqttPacket/BitMask.d.ts +12 -11
- package/dist/mqttPacket/BitMask.d.ts.map +1 -1
- package/dist/mqttPacket/BitMask.js +10 -18
- package/dist/mqttPacket/BitMask.js.map +1 -1
- package/dist/mqttPacket/PacketType.d.ts.map +1 -1
- package/dist/mqttPacket/Properties.d.ts +2 -2
- package/dist/mqttPacket/Properties.d.ts.map +1 -1
- package/dist/mqttPacket/Properties.js.map +1 -1
- package/dist/mqttPacket/ReasonCode.d.ts +1 -0
- package/dist/mqttPacket/ReasonCode.d.ts.map +1 -1
- package/dist/mqttPacket/ReasonCode.js +1 -0
- package/dist/mqttPacket/ReasonCode.js.map +1 -1
- package/dist/mqttPacket/RetainHandling.d.ts.map +1 -1
- package/dist/mqttPacket/auth.d.ts +3 -5
- package/dist/mqttPacket/auth.d.ts.map +1 -1
- package/dist/mqttPacket/auth.js +31 -30
- package/dist/mqttPacket/auth.js.map +1 -1
- package/dist/mqttPacket/codec.d.ts +48 -0
- package/dist/mqttPacket/codec.d.ts.map +1 -0
- package/dist/mqttPacket/codec.js +93 -0
- package/dist/mqttPacket/codec.js.map +1 -0
- package/dist/mqttPacket/connack.d.ts +4 -5
- package/dist/mqttPacket/connack.d.ts.map +1 -1
- package/dist/mqttPacket/connack.js +43 -45
- package/dist/mqttPacket/connack.js.map +1 -1
- package/dist/mqttPacket/connect.d.ts +26 -27
- package/dist/mqttPacket/connect.d.ts.map +1 -1
- package/dist/mqttPacket/connect.js +156 -157
- package/dist/mqttPacket/connect.js.map +1 -1
- package/dist/mqttPacket/decoder.d.ts +1 -13
- package/dist/mqttPacket/decoder.d.ts.map +1 -1
- package/dist/mqttPacket/decoder.js +7 -28
- package/dist/mqttPacket/decoder.js.map +1 -1
- package/dist/mqttPacket/disconnect.d.ts +4 -5
- package/dist/mqttPacket/disconnect.d.ts.map +1 -1
- package/dist/mqttPacket/disconnect.js +41 -43
- package/dist/mqttPacket/disconnect.js.map +1 -1
- package/dist/mqttPacket/encoder.d.ts +1 -15
- package/dist/mqttPacket/encoder.d.ts.map +1 -1
- package/dist/mqttPacket/encoder.js +4 -27
- package/dist/mqttPacket/encoder.js.map +1 -1
- package/dist/mqttPacket/length.js +1 -1
- package/dist/mqttPacket/length.js.map +1 -1
- package/dist/mqttPacket/mod.d.ts +21 -103
- package/dist/mqttPacket/mod.d.ts.map +1 -1
- package/dist/mqttPacket/mod.js +5 -94
- package/dist/mqttPacket/mod.js.map +1 -1
- package/dist/mqttPacket/pingreq.d.ts +4 -5
- package/dist/mqttPacket/pingreq.d.ts.map +1 -1
- package/dist/mqttPacket/pingreq.js +11 -13
- package/dist/mqttPacket/pingreq.js.map +1 -1
- package/dist/mqttPacket/pingres.d.ts +4 -5
- package/dist/mqttPacket/pingres.d.ts.map +1 -1
- package/dist/mqttPacket/pingres.js +11 -13
- package/dist/mqttPacket/pingres.js.map +1 -1
- package/dist/mqttPacket/protocolLevels.d.ts +11 -6
- package/dist/mqttPacket/protocolLevels.d.ts.map +1 -1
- package/dist/mqttPacket/protocolLevels.js +5 -1
- package/dist/mqttPacket/protocolLevels.js.map +1 -1
- package/dist/mqttPacket/pubblishAcks.d.ts +9 -10
- package/dist/mqttPacket/pubblishAcks.d.ts.map +1 -1
- package/dist/mqttPacket/pubblishAcks.js +43 -45
- package/dist/mqttPacket/pubblishAcks.js.map +1 -1
- package/dist/mqttPacket/publish.d.ts +14 -14
- package/dist/mqttPacket/publish.d.ts.map +1 -1
- package/dist/mqttPacket/publish.js +53 -55
- package/dist/mqttPacket/publish.js.map +1 -1
- package/dist/mqttPacket/suback.d.ts +4 -5
- package/dist/mqttPacket/suback.d.ts.map +1 -1
- package/dist/mqttPacket/suback.js +38 -40
- package/dist/mqttPacket/suback.js.map +1 -1
- package/dist/mqttPacket/subscribe.d.ts +36 -7
- package/dist/mqttPacket/subscribe.d.ts.map +1 -1
- package/dist/mqttPacket/subscribe.js +90 -89
- package/dist/mqttPacket/subscribe.js.map +1 -1
- package/dist/mqttPacket/types.d.ts +1 -8
- package/dist/mqttPacket/types.d.ts.map +1 -1
- package/dist/mqttPacket/unsuback.d.ts +4 -5
- package/dist/mqttPacket/unsuback.d.ts.map +1 -1
- package/dist/mqttPacket/unsuback.js +32 -34
- package/dist/mqttPacket/unsuback.js.map +1 -1
- package/dist/mqttPacket/unsubscribe.d.ts +23 -6
- package/dist/mqttPacket/unsubscribe.d.ts.map +1 -1
- package/dist/mqttPacket/unsubscribe.js +45 -44
- package/dist/mqttPacket/unsubscribe.js.map +1 -1
- package/dist/mqttPacket/validators.d.ts +4 -16
- package/dist/mqttPacket/validators.d.ts.map +1 -1
- package/dist/mqttPacket/validators.js +5 -26
- package/dist/mqttPacket/validators.js.map +1 -1
- package/dist/node/tcpClient.d.ts +1 -1
- package/dist/node/tcpClient.d.ts.map +1 -1
- package/dist/node/tcpClient.js +12 -7
- package/dist/node/tcpClient.js.map +1 -1
- package/dist/node/tcpServer.d.ts.map +1 -1
- package/dist/node/tcpServer.js +4 -0
- package/dist/node/tcpServer.js.map +1 -1
- package/dist/node/tlsServer.d.ts +19 -0
- package/dist/node/tlsServer.d.ts.map +1 -0
- package/dist/node/tlsServer.js +58 -0
- package/dist/node/tlsServer.js.map +1 -0
- package/dist/node/wrapNodeSocket.d.ts.map +1 -1
- package/dist/node/wrapNodeSocket.js +6 -28
- package/dist/node/wrapNodeSocket.js.map +1 -1
- package/dist/persistence/basicPersistence.d.ts +36 -0
- package/dist/persistence/basicPersistence.d.ts.map +1 -0
- package/dist/persistence/basicPersistence.js +306 -0
- package/dist/persistence/basicPersistence.js.map +1 -0
- package/dist/persistence/deps.d.ts +3 -2
- package/dist/persistence/deps.d.ts.map +1 -1
- package/dist/persistence/deps.js +2 -1
- package/dist/persistence/deps.js.map +1 -1
- package/dist/persistence/memory/memoryPersistence.d.ts +6 -23
- package/dist/persistence/memory/memoryPersistence.d.ts.map +1 -1
- package/dist/persistence/memory/memoryPersistence.js +12 -115
- package/dist/persistence/memory/memoryPersistence.js.map +1 -1
- package/dist/persistence/memory/memoryStorage.d.ts +45 -0
- package/dist/persistence/memory/memoryStorage.d.ts.map +1 -0
- package/dist/persistence/memory/memoryStorage.js +143 -0
- package/dist/persistence/memory/memoryStorage.js.map +1 -0
- package/dist/persistence/mod.d.ts +3 -3
- package/dist/persistence/mod.d.ts.map +1 -1
- package/dist/persistence/mod.js +6 -1
- package/dist/persistence/mod.js.map +1 -1
- package/dist/persistence/persistence.d.ts +44 -69
- package/dist/persistence/persistence.d.ts.map +1 -1
- package/dist/persistence/persistence.js +1 -2
- package/dist/persistence/persistence.js.map +1 -1
- package/dist/persistence/sqlite/sqliteDatabase.d.ts +46 -0
- package/dist/persistence/sqlite/sqliteDatabase.d.ts.map +1 -0
- package/dist/persistence/sqlite/sqliteDatabase.js +215 -0
- package/dist/persistence/sqlite/sqliteDatabase.js.map +1 -0
- package/dist/persistence/sqlite/sqlitePersistence.d.ts +16 -0
- package/dist/persistence/sqlite/sqlitePersistence.d.ts.map +1 -0
- package/dist/persistence/sqlite/sqlitePersistence.js +29 -0
- package/dist/persistence/sqlite/sqlitePersistence.js.map +1 -0
- package/dist/persistence/sqlite/sqliteStorage.d.ts +36 -0
- package/dist/persistence/sqlite/sqliteStorage.d.ts.map +1 -0
- package/dist/persistence/sqlite/sqliteStorage.js +194 -0
- package/dist/persistence/sqlite/sqliteStorage.js.map +1 -0
- package/dist/persistence/storage.d.ts +38 -0
- package/dist/persistence/storage.d.ts.map +1 -0
- package/dist/persistence/storage.js +5 -0
- package/dist/persistence/storage.js.map +1 -0
- package/dist/server/config.d.ts +47 -0
- package/dist/server/config.d.ts.map +1 -0
- package/dist/server/config.js +41 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/context.d.ts +198 -24
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/context.js +432 -53
- package/dist/server/context.js.map +1 -1
- package/dist/server/deps.d.ts +5 -6
- package/dist/server/deps.d.ts.map +1 -1
- package/dist/server/deps.js +2 -2
- package/dist/server/deps.js.map +1 -1
- package/dist/server/handlers/completeConnect.d.ts +8 -0
- package/dist/server/handlers/completeConnect.d.ts.map +1 -0
- package/dist/server/handlers/completeConnect.js +74 -0
- package/dist/server/handlers/completeConnect.js.map +1 -0
- package/dist/server/handlers/handleAuth.d.ts +9 -0
- package/dist/server/handlers/handleAuth.d.ts.map +1 -0
- package/dist/server/handlers/handleAuth.js +69 -0
- package/dist/server/handlers/handleAuth.js.map +1 -0
- package/dist/server/handlers/handleConnect.d.ts +2 -4
- package/dist/server/handlers/handleConnect.d.ts.map +1 -1
- package/dist/server/handlers/handleConnect.js +140 -67
- package/dist/server/handlers/handleConnect.js.map +1 -1
- package/dist/server/handlers/handleDisconnect.d.ts +1 -1
- package/dist/server/handlers/handleDisconnect.d.ts.map +1 -1
- package/dist/server/handlers/handleDisconnect.js +3 -3
- package/dist/server/handlers/handleDisconnect.js.map +1 -1
- package/dist/server/handlers/handlePacket.d.ts.map +1 -1
- package/dist/server/handlers/handlePacket.js +19 -6
- package/dist/server/handlers/handlePacket.js.map +1 -1
- package/dist/server/handlers/handlePuback.d.ts +1 -3
- package/dist/server/handlers/handlePuback.d.ts.map +1 -1
- package/dist/server/handlers/handlePuback.js +2 -8
- package/dist/server/handlers/handlePuback.js.map +1 -1
- package/dist/server/handlers/handlePubcomp.d.ts +1 -1
- package/dist/server/handlers/handlePubcomp.d.ts.map +1 -1
- package/dist/server/handlers/handlePubcomp.js +2 -4
- package/dist/server/handlers/handlePubcomp.js.map +1 -1
- package/dist/server/handlers/handlePublish.d.ts +1 -1
- package/dist/server/handlers/handlePublish.d.ts.map +1 -1
- package/dist/server/handlers/handlePublish.js +149 -45
- package/dist/server/handlers/handlePublish.js.map +1 -1
- package/dist/server/handlers/handlePubrec.d.ts.map +1 -1
- package/dist/server/handlers/handlePubrec.js +2 -3
- package/dist/server/handlers/handlePubrec.js.map +1 -1
- package/dist/server/handlers/handlePubrel.d.ts.map +1 -1
- package/dist/server/handlers/handlePubrel.js +6 -2
- package/dist/server/handlers/handlePubrel.js.map +1 -1
- package/dist/server/handlers/handleSubscribe.d.ts +1 -6
- package/dist/server/handlers/handleSubscribe.d.ts.map +1 -1
- package/dist/server/handlers/handleSubscribe.js +99 -38
- package/dist/server/handlers/handleSubscribe.js.map +1 -1
- package/dist/server/handlers/handleUnsubscribe.d.ts.map +1 -1
- package/dist/server/handlers/handleUnsubscribe.js +19 -4
- package/dist/server/handlers/handleUnsubscribe.js.map +1 -1
- package/dist/server/mod.d.ts +3 -3
- package/dist/server/mod.d.ts.map +1 -1
- package/dist/server/mod.js +1 -1
- package/dist/server/mod.js.map +1 -1
- package/dist/server/server.d.ts +29 -6
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +84 -15
- package/dist/server/server.js.map +1 -1
- package/dist/socket/socket.d.ts +11 -9
- package/dist/socket/socket.d.ts.map +1 -1
- package/dist/socket/socket.js +67 -15
- package/dist/socket/socket.js.map +1 -1
- package/dist/timer/timer.d.ts +32 -0
- package/dist/timer/timer.d.ts.map +1 -1
- package/dist/timer/timer.js +32 -0
- package/dist/timer/timer.js.map +1 -1
- package/dist/trie/trie.d.ts +10 -5
- package/dist/trie/trie.d.ts.map +1 -1
- package/dist/trie/trie.js +47 -17
- package/dist/trie/trie.js.map +1 -1
- package/dist/utils/assert.d.ts.map +1 -1
- package/dist/utils/{BufferedAsyncIterable.d.ts → bufferedAsyncIterable.d.ts} +1 -1
- package/dist/utils/bufferedAsyncIterable.d.ts.map +1 -0
- package/dist/utils/{BufferedAsyncIterable.js → bufferedAsyncIterable.js} +1 -1
- package/dist/utils/bufferedAsyncIterable.js.map +1 -0
- package/dist/utils/deferred.d.ts.map +1 -1
- package/dist/utils/deferred.js.map +1 -1
- package/dist/utils/getOrInsertPolyFill.d.ts +2 -0
- package/dist/utils/getOrInsertPolyFill.d.ts.map +1 -0
- package/dist/utils/getOrInsertPolyFill.js +12 -0
- package/dist/utils/getOrInsertPolyFill.js.map +1 -0
- package/dist/utils/logger.d.ts +40 -3
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +53 -7
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/mod.d.ts +6 -1
- package/dist/utils/mod.d.ts.map +1 -1
- package/dist/utils/mod.js +5 -1
- package/dist/utils/mod.js.map +1 -1
- package/dist/utils/outboundTopicAliasManager.d.ts +52 -0
- package/dist/utils/outboundTopicAliasManager.d.ts.map +1 -0
- package/dist/utils/outboundTopicAliasManager.js +74 -0
- package/dist/utils/outboundTopicAliasManager.js.map +1 -0
- package/dist/utils/queue.d.ts.map +1 -1
- package/dist/utils/topicFilter.d.ts +32 -0
- package/dist/utils/topicFilter.d.ts.map +1 -0
- package/dist/utils/topicFilter.js +52 -0
- package/dist/utils/topicFilter.js.map +1 -0
- package/dist/utils/utils.d.ts +2 -0
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +2 -0
- package/dist/utils/utils.js.map +1 -1
- package/dist/utils/validators.d.ts +34 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +61 -0
- package/dist/utils/validators.js.map +1 -0
- package/dist/web/webSocketStream.d.ts +29 -0
- package/dist/web/webSocketStream.d.ts.map +1 -0
- package/dist/web/webSocketStream.js +69 -0
- package/dist/web/webSocketStream.js.map +1 -0
- package/dist/web/wrapWebSocket.d.ts +12 -0
- package/dist/web/wrapWebSocket.d.ts.map +1 -0
- package/dist/web/wrapWebSocket.js +41 -0
- package/dist/web/wrapWebSocket.js.map +1 -0
- package/dist/web/wsClient.d.ts +7 -0
- package/dist/web/wsClient.d.ts.map +1 -0
- package/dist/web/wsClient.js +22 -0
- package/dist/web/wsClient.js.map +1 -0
- package/dist/web/wsClient.test.d.ts +2 -0
- package/dist/web/wsClient.test.d.ts.map +1 -0
- package/dist/web/wsClient.test.js +20 -0
- package/dist/web/wsClient.test.js.map +1 -0
- package/examples/authHandler.test.ts +164 -0
- package/examples/mqtt.test.ts +89 -0
- package/examples/mqtts.test.ts +100 -0
- package/examples/webSocket.test.ts +94 -0
- package/mqttConn/mqttConn.test.ts +9 -9
- package/mqttConn/mqttConn.ts +91 -49
- package/mqttPacket/BitMask.ts +11 -19
- package/mqttPacket/Properties.ts +6 -3
- package/mqttPacket/ReasonCode.ts +2 -1
- package/mqttPacket/auth.test.ts +1 -1
- package/mqttPacket/auth.ts +41 -48
- package/mqttPacket/codec.ts +146 -0
- package/mqttPacket/connack.ts +57 -68
- package/mqttPacket/connect.test.ts +2 -2
- package/mqttPacket/connect.ts +197 -204
- package/mqttPacket/decoder.test.ts +0 -39
- package/mqttPacket/decoder.ts +9 -36
- package/mqttPacket/disconnect.ts +57 -68
- package/mqttPacket/encoder.ts +5 -40
- package/mqttPacket/length.ts +1 -1
- package/mqttPacket/mod.ts +48 -200
- package/mqttPacket/pingreq.ts +21 -27
- package/mqttPacket/pingres.ts +21 -27
- package/mqttPacket/protocolLevels.ts +12 -7
- package/mqttPacket/pubblishAcks.ts +68 -77
- package/mqttPacket/publish.ts +76 -83
- package/mqttPacket/suback.ts +48 -58
- package/mqttPacket/subscribe.ts +141 -117
- package/mqttPacket/types.ts +1 -9
- package/mqttPacket/unsuback.ts +46 -58
- package/mqttPacket/unsubscribe.ts +74 -63
- package/mqttPacket/validators.ts +5 -31
- package/node/socket-node-stream.test.ts +322 -0
- package/node/socket-node-stream.ts +174 -0
- package/node/tcpClient.test.ts +70 -0
- package/node/tcpClient.ts +13 -12
- package/node/tcpServer.test.ts +24 -20
- package/node/tcpServer.ts +6 -0
- package/node/tlsServer.test.ts +94 -0
- package/node/tlsServer.ts +81 -0
- package/node/wrapNodeSocket.ts +7 -30
- package/package.json +73 -45
- package/persistence/basicPersistence.ts +495 -0
- package/persistence/deps.ts +11 -1
- package/persistence/memory/memoryPersistence.ts +12 -152
- package/persistence/memory/memoryStorage.ts +232 -0
- package/persistence/mod.ts +4 -4
- package/persistence/persistence.test.ts +24 -0
- package/persistence/persistence.testing.ts +1324 -0
- package/persistence/persistence.ts +111 -67
- package/persistence/sqlite/sqliteDatabase.ts +294 -0
- package/persistence/sqlite/sqlitePersistence.test.ts +48 -0
- package/persistence/sqlite/sqlitePersistence.ts +36 -0
- package/persistence/sqlite/sqliteStorage.ts +324 -0
- package/persistence/storage.ts +84 -0
- package/server/config.ts +65 -0
- package/server/context.ts +658 -74
- package/server/deps.ts +25 -5
- package/server/handlers/completeConnect.ts +93 -0
- package/server/handlers/duplicate.test.ts +196 -0
- package/server/handlers/handleAuth.test.ts +225 -0
- package/server/handlers/handleAuth.ts +88 -0
- package/server/handlers/handleConnect.test.ts +589 -0
- package/server/handlers/handleConnect.ts +201 -86
- package/server/handlers/handleConnect.version.test.ts +108 -0
- package/server/handlers/handleDisconnect.test.ts +56 -0
- package/server/handlers/handleDisconnect.ts +3 -3
- package/server/handlers/handlePacket.test.ts +24 -0
- package/server/handlers/handlePacket.ts +30 -8
- package/server/handlers/handlePingreq.test.ts +29 -0
- package/server/handlers/handlePuback.test.ts +28 -0
- package/server/handlers/handlePuback.ts +5 -8
- package/server/handlers/handlePubcomp.test.ts +28 -0
- package/server/handlers/handlePubcomp.ts +5 -4
- package/server/handlers/handlePublish.test.ts +471 -0
- package/server/handlers/handlePublish.ts +189 -35
- package/server/handlers/handlePubrec.test.ts +28 -0
- package/server/handlers/handlePubrec.ts +2 -3
- package/server/handlers/handlePubrel.test.ts +74 -0
- package/server/handlers/handlePubrel.ts +12 -2
- package/server/handlers/handleSubscribe.test.ts +971 -0
- package/server/handlers/handleSubscribe.ts +158 -39
- package/server/handlers/handleUnsubscribe.test.ts +79 -0
- package/server/handlers/handleUnsubscribe.ts +29 -5
- package/server/handlers/keepalive.test.ts +132 -0
- package/server/handlers/session.persistence.test.ts +194 -0
- package/server/handlers/will.delivery.test.ts +221 -0
- package/server/mod.ts +4 -3
- package/server/preconnect.test.ts +151 -0
- package/server/server.ts +115 -17
- package/socket/socket.test.ts +91 -0
- package/socket/socket.ts +81 -31
- package/timer/timer.test.ts +4 -7
- package/timer/timer.ts +36 -0
- package/tools/benchmarks/receiver.ts +51 -0
- package/tools/benchmarks/sender.ts +48 -0
- package/tools/benchmarks/utils.ts +31 -0
- package/tools/mqtt-compat/README.md +130 -0
- package/tools/mqtt-compat/broker.ts +52 -0
- package/tools/mqtt-compat/paho-mqtt4.test.ts +379 -0
- package/tools/mqtt-compat/paho-mqtt5.tests.ts +887 -0
- package/trie/trie.test.ts +9 -1
- package/trie/trie.ts +57 -22
- package/utils/bufferedAsyncIterable.test.ts +92 -0
- package/utils/{BufferedAsyncIterable.ts → bufferedAsyncIterable.ts} +1 -1
- package/utils/deferred.test.ts +36 -0
- package/utils/deferred.ts +0 -1
- package/utils/getOrInsertPolyFill.ts +12 -0
- package/utils/logger.test.ts +189 -0
- package/utils/logger.ts +62 -7
- package/utils/mod.ts +15 -1
- package/utils/outboundTopicAliasManager.ts +100 -0
- package/utils/queue.test.ts +61 -0
- package/utils/topicFilter.test.ts +63 -0
- package/utils/topicFilter.ts +61 -0
- package/utils/utils.ts +3 -0
- package/utils/validators.ts +67 -0
- package/web/webSocketStream.ts +97 -0
- package/web/wrapWebSocket.ts +52 -0
- package/web/wsClient.test.ts +26 -0
- package/web/wsClient.ts +25 -0
- package/benchmarks/receiver.ts +0 -35
- package/benchmarks/sender.ts +0 -32
- package/benchmarks/utils.ts +0 -9
- package/dev_utils/dummyConn.ts +0 -110
- package/dist/persistence/store.d.ts +0 -13
- package/dist/persistence/store.d.ts.map +0 -1
- package/dist/persistence/store.js +0 -2
- package/dist/persistence/store.js.map +0 -1
- package/dist/utils/BufferedAsyncIterable.d.ts.map +0 -1
- package/dist/utils/BufferedAsyncIterable.js.map +0 -1
- package/examples/tcpServer.test.ts +0 -148
- package/persistence/memory/memoryPersistence.test.ts +0 -156
- package/persistence/store.ts +0 -15
- package/server/test/handleConnect.test.ts +0 -130
- package/server/test/test-handlers.ts +0 -53
package/mqttPacket/validators.ts
CHANGED
|
@@ -1,35 +1,9 @@
|
|
|
1
|
-
import type { Topic, TopicFilter } from "./types.ts";
|
|
2
|
-
|
|
3
|
-
// deno-lint-ignore no-control-regex
|
|
4
|
-
const invalidUTF8regEx = new RegExp(/\x00|\uFFFD/);
|
|
5
|
-
// deno-lint-ignore no-control-regex
|
|
6
|
-
const invalidTopicRegEx = new RegExp(/^$|\+|#|\x00|\uFFFD/);
|
|
7
|
-
// deno-lint-ignore no-control-regex
|
|
8
|
-
const invalidTopicFilterRegEx = new RegExp(/^$|#.|[^\/]\+|\+[^\/]|\x00|\uFFFD/);
|
|
9
|
-
|
|
10
1
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* @
|
|
2
|
+
* Checks for invalid UTF-8 characters or null bytes.
|
|
3
|
+
*
|
|
4
|
+
* @param value - The string to validate.
|
|
5
|
+
* @returns `true` if the string contains invalid UTF-8 sequences or a null byte, otherwise `false`.
|
|
14
6
|
*/
|
|
15
7
|
export function invalidUTF8(value: string): boolean {
|
|
16
|
-
return
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* check for invalid topic characters
|
|
21
|
-
* @param value
|
|
22
|
-
* @returns true if the topic is invalid
|
|
23
|
-
*/
|
|
24
|
-
export function invalidTopic(value: Topic): boolean {
|
|
25
|
-
return invalidTopicRegEx.test(value);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* check for invalid topic filter characters
|
|
30
|
-
* @param value topic filter to test
|
|
31
|
-
* @returns true if the topic filter is invalid
|
|
32
|
-
*/
|
|
33
|
-
export function invalidTopicFilter(value: TopicFilter): boolean {
|
|
34
|
-
return invalidTopicFilterRegEx.test(value);
|
|
8
|
+
return value.includes("\x00") || !value.isWellFormed();
|
|
35
9
|
}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { PassThrough } from "node:stream";
|
|
4
|
+
import { Conn, type SockConn } from "./socket-node-stream.ts";
|
|
5
|
+
|
|
6
|
+
// Helper to create a mock SockConn using a PassThrough duplex stream
|
|
7
|
+
function createMockConn(): {
|
|
8
|
+
conn: Conn;
|
|
9
|
+
stream: PassThrough;
|
|
10
|
+
closeCalled: { count: number };
|
|
11
|
+
} {
|
|
12
|
+
const stream = new PassThrough();
|
|
13
|
+
const closeCalled = { count: 0 };
|
|
14
|
+
|
|
15
|
+
const sockConn: SockConn = {
|
|
16
|
+
stream,
|
|
17
|
+
close: () => {
|
|
18
|
+
closeCalled.count++;
|
|
19
|
+
},
|
|
20
|
+
remoteAddr: {
|
|
21
|
+
transport: "tcp",
|
|
22
|
+
hostname: "127.0.0.1",
|
|
23
|
+
port: 1883,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const conn = new Conn(sockConn);
|
|
28
|
+
return { conn, stream, closeCalled };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
test("Conn.write - successfully writes data", async () => {
|
|
32
|
+
const { conn, stream } = createMockConn();
|
|
33
|
+
const data = new Uint8Array([0x01, 0x02, 0x03]);
|
|
34
|
+
|
|
35
|
+
const bytesWritten = await conn.write(data);
|
|
36
|
+
assert.equal(bytesWritten, data.length, "Number of written bytes matches");
|
|
37
|
+
|
|
38
|
+
const chunk = stream.read();
|
|
39
|
+
assert.deepStrictEqual(
|
|
40
|
+
new Uint8Array(chunk),
|
|
41
|
+
data,
|
|
42
|
+
"The stream received the correct data",
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
conn.close();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("Conn.write - respects backpressure and waits for drain event", async () => {
|
|
49
|
+
const { conn, stream } = createMockConn();
|
|
50
|
+
const data = new Uint8Array([0x01, 0x02, 0x03]);
|
|
51
|
+
|
|
52
|
+
// Force stream.write to return false to simulate a full internal buffer (backpressure)
|
|
53
|
+
stream.write = () => false;
|
|
54
|
+
|
|
55
|
+
let writeResolved = false;
|
|
56
|
+
const writePromise = conn.write(data).then((bytes) => {
|
|
57
|
+
writeResolved = true;
|
|
58
|
+
return bytes;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Yield execution shortly to ensure the promise hasn't resolved prematurely
|
|
62
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
63
|
+
assert.equal(
|
|
64
|
+
writeResolved,
|
|
65
|
+
false,
|
|
66
|
+
"Write promise should pend while backpressure is active",
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
// Emit the drain event to signal the buffer has cleared
|
|
70
|
+
stream.emit("drain");
|
|
71
|
+
|
|
72
|
+
const bytesWritten = await writePromise;
|
|
73
|
+
assert.equal(bytesWritten, data.length, "Resolves after drain event fires");
|
|
74
|
+
assert.equal(writeResolved, true);
|
|
75
|
+
|
|
76
|
+
conn.close();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("Conn.read - reads exact number of bytes", async () => {
|
|
80
|
+
const { conn, stream } = createMockConn();
|
|
81
|
+
const data = new Uint8Array([10, 20, 30, 40, 50]);
|
|
82
|
+
|
|
83
|
+
stream.write(data);
|
|
84
|
+
|
|
85
|
+
const result = await conn.read(3);
|
|
86
|
+
assert.deepStrictEqual(
|
|
87
|
+
result,
|
|
88
|
+
new Uint8Array([10, 20, 30]),
|
|
89
|
+
"First 3 bytes match",
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const restResult = await conn.read(2);
|
|
93
|
+
assert.deepStrictEqual(
|
|
94
|
+
restResult,
|
|
95
|
+
new Uint8Array([40, 50]),
|
|
96
|
+
"Remaining bytes match via the leftover buffer",
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
conn.close();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("Conn.read - waits for async data (readable event)", async () => {
|
|
103
|
+
const { conn, stream } = createMockConn();
|
|
104
|
+
|
|
105
|
+
const readPromise = conn.read(2);
|
|
106
|
+
|
|
107
|
+
// Simulate network latency using setImmediate or setTimeout
|
|
108
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
109
|
+
stream.write(new Uint8Array([0xAA, 0xBB]));
|
|
110
|
+
|
|
111
|
+
const result = await readPromise;
|
|
112
|
+
assert.deepStrictEqual(
|
|
113
|
+
result,
|
|
114
|
+
new Uint8Array([0xAA, 0xBB]),
|
|
115
|
+
"Data correctly received after async wait",
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
conn.close();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("Conn.close - gracefully closes the connection and streams", async () => {
|
|
122
|
+
const { conn, stream, closeCalled } = createMockConn();
|
|
123
|
+
|
|
124
|
+
assert.equal(closeCalled.count, 0, "Closer has not been called yet");
|
|
125
|
+
|
|
126
|
+
conn.close();
|
|
127
|
+
|
|
128
|
+
assert.equal(closeCalled.count, 1, "Closer is called exactly once");
|
|
129
|
+
assert.equal(stream.destroyed, true, "The underlying stream is destroyed");
|
|
130
|
+
|
|
131
|
+
await assert.rejects(
|
|
132
|
+
conn.write(new Uint8Array([1])),
|
|
133
|
+
/Stream is closed or not writable/,
|
|
134
|
+
"Writing to a closed connection throws an error",
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const readResult = await conn.read(1);
|
|
138
|
+
assert.equal(
|
|
139
|
+
readResult,
|
|
140
|
+
null,
|
|
141
|
+
"Reading from a closed connection returns null",
|
|
142
|
+
);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("Conn.read - length less than 0 returns null", async () => {
|
|
146
|
+
const { conn } = createMockConn();
|
|
147
|
+
|
|
148
|
+
const result = await conn.read(-5);
|
|
149
|
+
assert.equal(result, null, "Reading with a negative length returns null");
|
|
150
|
+
|
|
151
|
+
conn.close();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
test("Conn.read - length equal to 0 returns empty Uint8Array", async () => {
|
|
155
|
+
const { conn } = createMockConn();
|
|
156
|
+
|
|
157
|
+
const result = await conn.read(0);
|
|
158
|
+
assert.deepStrictEqual(
|
|
159
|
+
result,
|
|
160
|
+
new Uint8Array(0),
|
|
161
|
+
"Reading 0 bytes returns an empty Uint8Array",
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
conn.close();
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test("Conn.read - stream errors while waiting for data (returns null)", async () => {
|
|
168
|
+
const { conn, stream } = createMockConn();
|
|
169
|
+
|
|
170
|
+
// Prevent Node.js from crashing due to an unhandled stream error during test execution
|
|
171
|
+
stream.on("error", () => {});
|
|
172
|
+
|
|
173
|
+
const readPromise = conn.read(5);
|
|
174
|
+
|
|
175
|
+
// Emit error event to invoke internal error tracking state
|
|
176
|
+
stream.emit("error", new Error("Network failure"));
|
|
177
|
+
|
|
178
|
+
const result = await readPromise;
|
|
179
|
+
assert.equal(
|
|
180
|
+
result,
|
|
181
|
+
null,
|
|
182
|
+
"Returns null when the stream errors out during an active read",
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
conn.close();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test("Conn.read - chunk is larger than requested (populates leftover)", async () => {
|
|
189
|
+
const { conn, stream } = createMockConn();
|
|
190
|
+
const largeChunk = new Uint8Array([1, 2, 3, 4, 5]);
|
|
191
|
+
|
|
192
|
+
stream.write(largeChunk);
|
|
193
|
+
|
|
194
|
+
const result1 = await conn.read(2);
|
|
195
|
+
assert.deepStrictEqual(
|
|
196
|
+
result1,
|
|
197
|
+
new Uint8Array([1, 2]),
|
|
198
|
+
"Returns the exact requested chunk size",
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
const result2 = await conn.read(2);
|
|
202
|
+
assert.deepStrictEqual(
|
|
203
|
+
result2,
|
|
204
|
+
new Uint8Array([3, 4]),
|
|
205
|
+
"Returns the next bytes from the leftover buffer",
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
const result3 = await conn.read(1);
|
|
209
|
+
assert.deepStrictEqual(
|
|
210
|
+
result3,
|
|
211
|
+
new Uint8Array([5]),
|
|
212
|
+
"Returns the last remaining byte from leftover",
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
conn.close();
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
test("Conn.read - partial leftover is not enough (combines leftover and new stream chunk)", async () => {
|
|
219
|
+
const { conn, stream } = createMockConn();
|
|
220
|
+
|
|
221
|
+
// 1. Write 3 bytes and read 2 (leaving 1 byte [0x03] in leftover)
|
|
222
|
+
stream.write(new Uint8Array([0x01, 0x02, 0x03]));
|
|
223
|
+
await conn.read(2);
|
|
224
|
+
|
|
225
|
+
// 2. Write new data to the stream
|
|
226
|
+
stream.write(new Uint8Array([0x04, 0x05]));
|
|
227
|
+
|
|
228
|
+
// 3. Request 3 bytes (needs 1 from leftover + 2 from stream)
|
|
229
|
+
const result = await conn.read(3);
|
|
230
|
+
assert.deepStrictEqual(
|
|
231
|
+
result,
|
|
232
|
+
new Uint8Array([0x03, 0x04, 0x05]),
|
|
233
|
+
"Combines leftover data with newly arrived stream data",
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
conn.close();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test("Conn.write - rejects immediately if stream.writable is false", async () => {
|
|
240
|
+
const { conn, stream } = createMockConn();
|
|
241
|
+
|
|
242
|
+
Object.defineProperty(stream, "writable", { value: false });
|
|
243
|
+
|
|
244
|
+
await assert.rejects(
|
|
245
|
+
conn.write(new Uint8Array([1, 2, 3])),
|
|
246
|
+
/Stream is closed or not writable/,
|
|
247
|
+
"Rejects immediately when stream.writable is false",
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
conn.close();
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
test("Conn.read - fulfilled entirely from leftover buffer (skips while loop)", async () => {
|
|
254
|
+
const { conn, stream } = createMockConn();
|
|
255
|
+
const data = new Uint8Array([10, 20, 30, 40, 50]);
|
|
256
|
+
|
|
257
|
+
// 1. Populate the leftover buffer by reading less than what was written
|
|
258
|
+
stream.write(data);
|
|
259
|
+
await conn.read(2); // Leaves [30, 40, 50] in leftover
|
|
260
|
+
|
|
261
|
+
// 2. Request an amount that can be fully satisfied by the leftover buffer
|
|
262
|
+
const result = await conn.read(2);
|
|
263
|
+
assert.deepStrictEqual(
|
|
264
|
+
result,
|
|
265
|
+
new Uint8Array([30, 40]),
|
|
266
|
+
"Successfully fulfilled entirely from the leftover buffer",
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
// 3. Verify the remaining byte is still preserved
|
|
270
|
+
const finalResult = await conn.read(1);
|
|
271
|
+
assert.deepStrictEqual(
|
|
272
|
+
finalResult,
|
|
273
|
+
new Uint8Array([50]),
|
|
274
|
+
"The remaining byte in leftover is still accessible",
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
conn.close();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
test("Conn - handles unexpected stream close event from underlying resource", () => {
|
|
281
|
+
const { conn, stream } = createMockConn();
|
|
282
|
+
|
|
283
|
+
// Initially, the connection should not be marked as closed
|
|
284
|
+
assert.equal(conn["closed"], false, "Connection is open initially");
|
|
285
|
+
|
|
286
|
+
// Simulate the underlying socket/stream closing unexpectedly from the remote side
|
|
287
|
+
stream.emit("close");
|
|
288
|
+
|
|
289
|
+
// Verify that the permanent 'close' listener was triggered and updated the internal state
|
|
290
|
+
assert.equal(
|
|
291
|
+
conn["closed"],
|
|
292
|
+
true,
|
|
293
|
+
"Connection internally updates to closed when stream emits close",
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
// Clean up to ensure resources are disposed
|
|
297
|
+
conn.close();
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
test("Conn.write - rejects the promise if stream.write invokes the callback with an error", async () => {
|
|
301
|
+
const { conn, stream } = createMockConn();
|
|
302
|
+
const data = new Uint8Array([1, 2, 3]);
|
|
303
|
+
|
|
304
|
+
// Simulate a write error by overriding stream.write
|
|
305
|
+
// It forces the callback to be invoked with an Error object
|
|
306
|
+
stream.write = (_chunk, callback) => {
|
|
307
|
+
if (typeof callback === "function") {
|
|
308
|
+
// Execute the callback with an error asynchronously, mimicking Node.js behavior
|
|
309
|
+
setImmediate(() => callback(new Error("Write pipeline failure")));
|
|
310
|
+
}
|
|
311
|
+
return false;
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// Verify that the conn.write Promise rejects with the exact error
|
|
315
|
+
await assert.rejects(
|
|
316
|
+
conn.write(data),
|
|
317
|
+
/Write pipeline failure/,
|
|
318
|
+
"The write promise should reject when the stream callback receives an error",
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
conn.close();
|
|
322
|
+
});
|
|
@@ -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);
|