@seriousme/opifex 1.11.3 โ 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -40
- package/bin/conformanceServer.ts +45 -13
- package/bin/demoServer.ts +38 -13
- package/bin/mqtt.ts +2 -2
- package/client/ConnectionState.ts +3 -1
- package/client/client.ts +88 -47
- package/client/context.ts +79 -27
- package/client/deps.ts +10 -3
- package/client/handlers/handleAuth.test.ts +193 -0
- package/client/handlers/handleAuth.ts +89 -0
- package/client/handlers/handleConnack.test.ts +173 -0
- package/client/handlers/handleConnack.ts +18 -8
- package/client/handlers/handleDisconnect.test.ts +22 -0
- package/client/handlers/handleDisconnect.ts +17 -0
- package/client/handlers/handlePacket.test.ts +242 -0
- package/client/handlers/handlePacket.ts +19 -5
- package/client/handlers/handlePuback.test.ts +99 -0
- package/client/handlers/handlePuback.ts +6 -0
- package/client/handlers/handlePubcomp.test.ts +112 -0
- package/client/handlers/handlePubcomp.ts +5 -0
- package/client/handlers/handlePublish.test.ts +188 -0
- package/client/handlers/handlePubrec.test.ts +119 -0
- package/client/handlers/handlePubrec.ts +5 -1
- package/client/handlers/handlePubrel.test.ts +136 -0
- package/client/handlers/handleSuback.test.ts +122 -0
- package/client/handlers/handleSuback.ts +3 -0
- package/client/handlers/handleUnsuback.test.ts +101 -0
- package/client/mod.ts +13 -2
- package/client/store/memoryStore.ts +12 -11
- package/client/store/store.ts +4 -2
- package/deno/README.md +1 -2
- package/deno/tcpClient.test.ts +75 -0
- package/deno/tcpClient.ts +36 -18
- package/deno/tcpServer.test.ts +22 -21
- package/deno/tcpServer.ts +26 -4
- package/deno/tlsServer.test.ts +97 -0
- package/deno/tlsServer.ts +58 -0
- package/deno/wsServer.test.ts +93 -0
- package/deno/wsServer.ts +96 -0
- package/dev_utils/generateCert.ts +95 -0
- package/dev_utils/mockConn.ts +36 -0
- package/dev_utils/mockServer.ts +28 -0
- package/dev_utils/mod.ts +30 -3
- package/dev_utils/packetHelpers.ts +404 -0
- package/dev_utils/test-handlers.ts +98 -0
- package/dev_utils/timers.ts +14 -0
- package/dev_utils/webStreamPair.test.ts +171 -0
- package/dev_utils/webStreamPair.ts +143 -0
- package/dist/bin/conformanceServer.js +17 -12
- package/dist/bin/conformanceServer.js.map +1 -1
- package/dist/bin/demoServer.js +16 -12
- package/dist/bin/demoServer.js.map +1 -1
- package/dist/bin/mqtt.js +2 -2
- package/dist/bin/mqtt.js.map +1 -1
- package/dist/client/ConnectionState.d.ts +3 -1
- package/dist/client/ConnectionState.d.ts.map +1 -1
- package/dist/client/ConnectionState.js +2 -0
- package/dist/client/ConnectionState.js.map +1 -1
- package/dist/client/client.d.ts +47 -21
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +57 -20
- package/dist/client/client.js.map +1 -1
- package/dist/client/context.d.ts +15 -7
- package/dist/client/context.d.ts.map +1 -1
- package/dist/client/context.js +44 -12
- package/dist/client/context.js.map +1 -1
- package/dist/client/deps.d.ts +4 -3
- package/dist/client/deps.d.ts.map +1 -1
- package/dist/client/deps.js +1 -1
- package/dist/client/deps.js.map +1 -1
- package/dist/client/handlers/handleAuth.d.ts +9 -0
- package/dist/client/handlers/handleAuth.d.ts.map +1 -0
- package/dist/client/handlers/handleAuth.js +66 -0
- package/dist/client/handlers/handleAuth.js.map +1 -0
- package/dist/client/handlers/handleConnack.d.ts +2 -2
- package/dist/client/handlers/handleConnack.d.ts.map +1 -1
- package/dist/client/handlers/handleConnack.js +16 -6
- package/dist/client/handlers/handleConnack.js.map +1 -1
- package/dist/client/handlers/handleDisconnect.d.ts +11 -0
- package/dist/client/handlers/handleDisconnect.d.ts.map +1 -0
- package/dist/client/handlers/handleDisconnect.js +15 -0
- package/dist/client/handlers/handleDisconnect.js.map +1 -0
- package/dist/client/handlers/handlePacket.d.ts.map +1 -1
- package/dist/client/handlers/handlePacket.js +14 -3
- package/dist/client/handlers/handlePacket.js.map +1 -1
- package/dist/client/handlers/handlePuback.d.ts.map +1 -1
- package/dist/client/handlers/handlePuback.js +5 -0
- package/dist/client/handlers/handlePuback.js.map +1 -1
- package/dist/client/handlers/handlePubcomp.d.ts.map +1 -1
- package/dist/client/handlers/handlePubcomp.js +5 -0
- package/dist/client/handlers/handlePubcomp.js.map +1 -1
- package/dist/client/handlers/handlePubrec.d.ts.map +1 -1
- package/dist/client/handlers/handlePubrec.js +5 -1
- package/dist/client/handlers/handlePubrec.js.map +1 -1
- package/dist/client/handlers/handleSuback.d.ts +1 -0
- package/dist/client/handlers/handleSuback.d.ts.map +1 -1
- package/dist/client/handlers/handleSuback.js +3 -0
- package/dist/client/handlers/handleSuback.js.map +1 -1
- package/dist/client/mod.d.ts +3 -2
- package/dist/client/mod.d.ts.map +1 -1
- package/dist/client/mod.js +1 -1
- package/dist/client/mod.js.map +1 -1
- package/dist/client/store/memoryStore.d.ts +3 -3
- package/dist/client/store/memoryStore.d.ts.map +1 -1
- package/dist/client/store/memoryStore.js +3 -3
- package/dist/client/store/memoryStore.js.map +1 -1
- package/dist/client/store/store.d.ts +3 -2
- package/dist/client/store/store.d.ts.map +1 -1
- package/dist/client/store/store.js +1 -1
- package/dist/client/store/store.js.map +1 -1
- package/dist/dev_utils/generateCert.d.ts +11 -0
- package/dist/dev_utils/generateCert.d.ts.map +1 -0
- package/dist/dev_utils/generateCert.js +76 -0
- package/dist/dev_utils/generateCert.js.map +1 -0
- package/dist/examples/authHandler.test.d.ts +2 -0
- package/dist/examples/authHandler.test.d.ts.map +1 -0
- package/dist/examples/authHandler.test.js +123 -0
- package/dist/examples/authHandler.test.js.map +1 -0
- package/dist/examples/mqtt.test.d.ts +2 -0
- package/dist/examples/mqtt.test.d.ts.map +1 -0
- package/dist/examples/mqtt.test.js +70 -0
- package/dist/examples/mqtt.test.js.map +1 -0
- package/dist/examples/mqtts.test.d.ts +2 -0
- package/dist/examples/mqtts.test.d.ts.map +1 -0
- package/dist/examples/mqtts.test.js +81 -0
- package/dist/examples/mqtts.test.js.map +1 -0
- package/dist/mqttConn/mqttConn.d.ts +24 -31
- package/dist/mqttConn/mqttConn.d.ts.map +1 -1
- package/dist/mqttConn/mqttConn.js +57 -36
- package/dist/mqttConn/mqttConn.js.map +1 -1
- package/dist/mqttPacket/AuthenticationResult.d.ts +4 -0
- package/dist/mqttPacket/AuthenticationResult.d.ts.map +1 -1
- package/dist/mqttPacket/AuthenticationResult.js.map +1 -1
- package/dist/mqttPacket/BitMask.d.ts.map +1 -1
- package/dist/mqttPacket/PacketType.d.ts +4 -0
- package/dist/mqttPacket/PacketType.d.ts.map +1 -1
- package/dist/mqttPacket/Properties.d.ts +4 -4
- package/dist/mqttPacket/Properties.d.ts.map +1 -1
- package/dist/mqttPacket/Properties.js.map +1 -1
- package/dist/mqttPacket/ReasonCode.d.ts +4 -5
- package/dist/mqttPacket/ReasonCode.d.ts.map +1 -1
- package/dist/mqttPacket/ReasonCode.js +1 -0
- package/dist/mqttPacket/ReasonCode.js.map +1 -1
- package/dist/mqttPacket/RetainHandling.d.ts +4 -0
- package/dist/mqttPacket/RetainHandling.d.ts.map +1 -1
- package/dist/mqttPacket/auth.d.ts +7 -8
- package/dist/mqttPacket/auth.d.ts.map +1 -1
- package/dist/mqttPacket/auth.js +31 -30
- package/dist/mqttPacket/auth.js.map +1 -1
- package/dist/mqttPacket/codec.d.ts +48 -0
- package/dist/mqttPacket/codec.d.ts.map +1 -0
- package/dist/mqttPacket/codec.js +93 -0
- package/dist/mqttPacket/codec.js.map +1 -0
- package/dist/mqttPacket/connack.d.ts +11 -10
- package/dist/mqttPacket/connack.d.ts.map +1 -1
- package/dist/mqttPacket/connack.js +43 -45
- package/dist/mqttPacket/connack.js.map +1 -1
- package/dist/mqttPacket/connect.d.ts +7 -7
- package/dist/mqttPacket/connect.d.ts.map +1 -1
- package/dist/mqttPacket/connect.js +156 -157
- package/dist/mqttPacket/connect.js.map +1 -1
- package/dist/mqttPacket/decoder.d.ts +6 -16
- package/dist/mqttPacket/decoder.d.ts.map +1 -1
- package/dist/mqttPacket/decoder.js +7 -28
- package/dist/mqttPacket/decoder.js.map +1 -1
- package/dist/mqttPacket/disconnect.d.ts +9 -8
- package/dist/mqttPacket/disconnect.d.ts.map +1 -1
- package/dist/mqttPacket/disconnect.js +41 -43
- package/dist/mqttPacket/disconnect.js.map +1 -1
- package/dist/mqttPacket/encoder.d.ts +7 -19
- package/dist/mqttPacket/encoder.d.ts.map +1 -1
- package/dist/mqttPacket/encoder.js +5 -28
- package/dist/mqttPacket/encoder.js.map +1 -1
- package/dist/mqttPacket/mod.d.ts +21 -103
- package/dist/mqttPacket/mod.d.ts.map +1 -1
- package/dist/mqttPacket/mod.js +5 -94
- package/dist/mqttPacket/mod.js.map +1 -1
- package/dist/mqttPacket/pingreq.d.ts +6 -6
- package/dist/mqttPacket/pingreq.d.ts.map +1 -1
- package/dist/mqttPacket/pingreq.js +11 -13
- package/dist/mqttPacket/pingreq.js.map +1 -1
- package/dist/mqttPacket/pingres.d.ts +6 -6
- package/dist/mqttPacket/pingres.d.ts.map +1 -1
- package/dist/mqttPacket/pingres.js +11 -13
- package/dist/mqttPacket/pingres.js.map +1 -1
- package/dist/mqttPacket/protocolLevels.d.ts +11 -6
- package/dist/mqttPacket/protocolLevels.d.ts.map +1 -1
- package/dist/mqttPacket/protocolLevels.js +5 -1
- package/dist/mqttPacket/protocolLevels.js.map +1 -1
- package/dist/mqttPacket/pubblishAcks.d.ts +9 -10
- package/dist/mqttPacket/pubblishAcks.d.ts.map +1 -1
- package/dist/mqttPacket/pubblishAcks.js +43 -45
- package/dist/mqttPacket/pubblishAcks.js.map +1 -1
- package/dist/mqttPacket/publish.d.ts +8 -7
- package/dist/mqttPacket/publish.d.ts.map +1 -1
- package/dist/mqttPacket/publish.js +53 -55
- package/dist/mqttPacket/publish.js.map +1 -1
- package/dist/mqttPacket/suback.d.ts +9 -8
- package/dist/mqttPacket/suback.d.ts.map +1 -1
- package/dist/mqttPacket/suback.js +38 -40
- package/dist/mqttPacket/suback.js.map +1 -1
- package/dist/mqttPacket/subscribe.d.ts +41 -10
- package/dist/mqttPacket/subscribe.d.ts.map +1 -1
- package/dist/mqttPacket/subscribe.js +90 -89
- package/dist/mqttPacket/subscribe.js.map +1 -1
- package/dist/mqttPacket/types.d.ts +2 -29
- package/dist/mqttPacket/types.d.ts.map +1 -1
- package/dist/mqttPacket/unsuback.d.ts +9 -8
- package/dist/mqttPacket/unsuback.d.ts.map +1 -1
- package/dist/mqttPacket/unsuback.js +32 -34
- package/dist/mqttPacket/unsuback.js.map +1 -1
- package/dist/mqttPacket/unsubscribe.d.ts +26 -8
- package/dist/mqttPacket/unsubscribe.d.ts.map +1 -1
- package/dist/mqttPacket/unsubscribe.js +45 -44
- package/dist/mqttPacket/unsubscribe.js.map +1 -1
- package/dist/mqttPacket/validators.d.ts +4 -16
- package/dist/mqttPacket/validators.d.ts.map +1 -1
- package/dist/mqttPacket/validators.js +5 -26
- package/dist/mqttPacket/validators.js.map +1 -1
- package/dist/node/tcpClient.d.ts +22 -2
- package/dist/node/tcpClient.d.ts.map +1 -1
- package/dist/node/tcpClient.js +29 -10
- package/dist/node/tcpClient.js.map +1 -1
- package/dist/node/tcpServer.d.ts +18 -0
- package/dist/node/tcpServer.d.ts.map +1 -1
- package/dist/node/tcpServer.js +21 -2
- package/dist/node/tcpServer.js.map +1 -1
- package/dist/node/tlsServer.d.ts +37 -0
- package/dist/node/tlsServer.d.ts.map +1 -0
- package/dist/node/tlsServer.js +73 -0
- package/dist/node/tlsServer.js.map +1 -0
- package/dist/node/wrapNodeSocket.d.ts.map +1 -1
- package/dist/node/wrapNodeSocket.js +6 -28
- package/dist/node/wrapNodeSocket.js.map +1 -1
- package/dist/persistence/basicPersistence.d.ts +36 -0
- package/dist/persistence/basicPersistence.d.ts.map +1 -0
- package/dist/persistence/basicPersistence.js +306 -0
- package/dist/persistence/basicPersistence.js.map +1 -0
- package/dist/persistence/deps.d.ts +3 -2
- package/dist/persistence/deps.d.ts.map +1 -1
- package/dist/persistence/deps.js +2 -1
- package/dist/persistence/deps.js.map +1 -1
- package/dist/persistence/memory/memoryPersistence.d.ts +6 -23
- package/dist/persistence/memory/memoryPersistence.d.ts.map +1 -1
- package/dist/persistence/memory/memoryPersistence.js +12 -115
- package/dist/persistence/memory/memoryPersistence.js.map +1 -1
- package/dist/persistence/memory/memoryStorage.d.ts +45 -0
- package/dist/persistence/memory/memoryStorage.d.ts.map +1 -0
- package/dist/persistence/memory/memoryStorage.js +143 -0
- package/dist/persistence/memory/memoryStorage.js.map +1 -0
- package/dist/persistence/mod.d.ts +3 -3
- package/dist/persistence/mod.d.ts.map +1 -1
- package/dist/persistence/mod.js +6 -1
- package/dist/persistence/mod.js.map +1 -1
- package/dist/persistence/persistence.d.ts +45 -70
- package/dist/persistence/persistence.d.ts.map +1 -1
- package/dist/persistence/persistence.js +1 -2
- package/dist/persistence/persistence.js.map +1 -1
- package/dist/persistence/sqlite/sqliteDatabase.d.ts +46 -0
- package/dist/persistence/sqlite/sqliteDatabase.d.ts.map +1 -0
- package/dist/persistence/sqlite/sqliteDatabase.js +215 -0
- package/dist/persistence/sqlite/sqliteDatabase.js.map +1 -0
- package/dist/persistence/sqlite/sqlitePersistence.d.ts +16 -0
- package/dist/persistence/sqlite/sqlitePersistence.d.ts.map +1 -0
- package/dist/persistence/sqlite/sqlitePersistence.js +29 -0
- package/dist/persistence/sqlite/sqlitePersistence.js.map +1 -0
- package/dist/persistence/sqlite/sqliteStorage.d.ts +36 -0
- package/dist/persistence/sqlite/sqliteStorage.d.ts.map +1 -0
- package/dist/persistence/sqlite/sqliteStorage.js +194 -0
- package/dist/persistence/sqlite/sqliteStorage.js.map +1 -0
- package/dist/persistence/storage.d.ts +38 -0
- package/dist/persistence/storage.d.ts.map +1 -0
- package/dist/persistence/storage.js +5 -0
- package/dist/persistence/storage.js.map +1 -0
- package/dist/server/config.d.ts +47 -0
- package/dist/server/config.d.ts.map +1 -0
- package/dist/server/config.js +41 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/context.d.ts +199 -25
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/context.js +432 -53
- package/dist/server/context.js.map +1 -1
- package/dist/server/deps.d.ts +5 -6
- package/dist/server/deps.d.ts.map +1 -1
- package/dist/server/deps.js +2 -2
- package/dist/server/deps.js.map +1 -1
- package/dist/server/handlers/completeConnect.d.ts +9 -0
- package/dist/server/handlers/completeConnect.d.ts.map +1 -0
- package/dist/server/handlers/completeConnect.js +74 -0
- package/dist/server/handlers/completeConnect.js.map +1 -0
- package/dist/server/handlers/handleAuth.d.ts +9 -0
- package/dist/server/handlers/handleAuth.d.ts.map +1 -0
- package/dist/server/handlers/handleAuth.js +69 -0
- package/dist/server/handlers/handleAuth.js.map +1 -0
- package/dist/server/handlers/handleConnect.d.ts +2 -4
- package/dist/server/handlers/handleConnect.d.ts.map +1 -1
- package/dist/server/handlers/handleConnect.js +140 -67
- package/dist/server/handlers/handleConnect.js.map +1 -1
- package/dist/server/handlers/handleDisconnect.d.ts +1 -1
- package/dist/server/handlers/handleDisconnect.d.ts.map +1 -1
- package/dist/server/handlers/handleDisconnect.js +3 -3
- package/dist/server/handlers/handleDisconnect.js.map +1 -1
- package/dist/server/handlers/handlePacket.d.ts.map +1 -1
- package/dist/server/handlers/handlePacket.js +19 -6
- package/dist/server/handlers/handlePacket.js.map +1 -1
- package/dist/server/handlers/handlePuback.d.ts +1 -3
- package/dist/server/handlers/handlePuback.d.ts.map +1 -1
- package/dist/server/handlers/handlePuback.js +2 -8
- package/dist/server/handlers/handlePuback.js.map +1 -1
- package/dist/server/handlers/handlePubcomp.d.ts +1 -1
- package/dist/server/handlers/handlePubcomp.d.ts.map +1 -1
- package/dist/server/handlers/handlePubcomp.js +2 -4
- package/dist/server/handlers/handlePubcomp.js.map +1 -1
- package/dist/server/handlers/handlePublish.d.ts +1 -1
- package/dist/server/handlers/handlePublish.d.ts.map +1 -1
- package/dist/server/handlers/handlePublish.js +149 -45
- package/dist/server/handlers/handlePublish.js.map +1 -1
- package/dist/server/handlers/handlePubrec.d.ts.map +1 -1
- package/dist/server/handlers/handlePubrec.js +2 -3
- package/dist/server/handlers/handlePubrec.js.map +1 -1
- package/dist/server/handlers/handlePubrel.d.ts.map +1 -1
- package/dist/server/handlers/handlePubrel.js +6 -2
- package/dist/server/handlers/handlePubrel.js.map +1 -1
- package/dist/server/handlers/handleSubscribe.d.ts +1 -6
- package/dist/server/handlers/handleSubscribe.d.ts.map +1 -1
- package/dist/server/handlers/handleSubscribe.js +99 -38
- package/dist/server/handlers/handleSubscribe.js.map +1 -1
- package/dist/server/handlers/handleUnsubscribe.d.ts.map +1 -1
- package/dist/server/handlers/handleUnsubscribe.js +19 -4
- package/dist/server/handlers/handleUnsubscribe.js.map +1 -1
- package/dist/server/mod.d.ts +3 -3
- package/dist/server/mod.d.ts.map +1 -1
- package/dist/server/mod.js +1 -1
- package/dist/server/mod.js.map +1 -1
- package/dist/server/server.d.ts +32 -9
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +84 -15
- package/dist/server/server.js.map +1 -1
- package/dist/socket/socket.d.ts +15 -9
- package/dist/socket/socket.d.ts.map +1 -1
- package/dist/socket/socket.js +66 -18
- package/dist/socket/socket.js.map +1 -1
- package/dist/timer/timer.d.ts +32 -0
- package/dist/timer/timer.d.ts.map +1 -1
- package/dist/timer/timer.js +32 -0
- package/dist/timer/timer.js.map +1 -1
- package/dist/trie/trie.d.ts +10 -5
- package/dist/trie/trie.d.ts.map +1 -1
- package/dist/trie/trie.js +61 -41
- package/dist/trie/trie.js.map +1 -1
- package/dist/utils/assert.d.ts.map +1 -1
- package/dist/utils/{BufferedAsyncIterable.d.ts โ bufferedAsyncIterable.d.ts} +1 -1
- package/dist/utils/bufferedAsyncIterable.d.ts.map +1 -0
- package/dist/utils/{BufferedAsyncIterable.js โ bufferedAsyncIterable.js} +1 -1
- package/dist/utils/bufferedAsyncIterable.js.map +1 -0
- package/dist/utils/deferred.d.ts.map +1 -1
- package/dist/utils/deferred.js.map +1 -1
- package/dist/utils/getOrInsertPolyFill.d.ts +2 -0
- package/dist/utils/getOrInsertPolyFill.d.ts.map +1 -0
- package/dist/utils/getOrInsertPolyFill.js +12 -0
- package/dist/utils/getOrInsertPolyFill.js.map +1 -0
- package/dist/utils/logger.d.ts +42 -5
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +53 -7
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/mod.d.ts +6 -1
- package/dist/utils/mod.d.ts.map +1 -1
- package/dist/utils/mod.js +5 -1
- package/dist/utils/mod.js.map +1 -1
- package/dist/utils/outboundTopicAliasManager.d.ts +52 -0
- package/dist/utils/outboundTopicAliasManager.d.ts.map +1 -0
- package/dist/utils/outboundTopicAliasManager.js +74 -0
- package/dist/utils/outboundTopicAliasManager.js.map +1 -0
- package/dist/utils/queue.d.ts.map +1 -1
- package/dist/utils/topicFilter.d.ts +32 -0
- package/dist/utils/topicFilter.d.ts.map +1 -0
- package/dist/utils/topicFilter.js +52 -0
- package/dist/utils/topicFilter.js.map +1 -0
- package/dist/utils/utils.d.ts +2 -0
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +2 -0
- package/dist/utils/utils.js.map +1 -1
- package/dist/utils/validators.d.ts +34 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +61 -0
- package/dist/utils/validators.js.map +1 -0
- package/dist/web/webSocketStream.d.ts +29 -0
- package/dist/web/webSocketStream.d.ts.map +1 -0
- package/dist/web/webSocketStream.js +69 -0
- package/dist/web/webSocketStream.js.map +1 -0
- package/dist/web/wrapWebSocket.d.ts +12 -0
- package/dist/web/wrapWebSocket.d.ts.map +1 -0
- package/dist/web/wrapWebSocket.js +41 -0
- package/dist/web/wrapWebSocket.js.map +1 -0
- package/dist/web/wsClient.d.ts +14 -0
- package/dist/web/wsClient.d.ts.map +1 -0
- package/dist/web/wsClient.js +33 -0
- package/dist/web/wsClient.js.map +1 -0
- package/dist/web/wsClient.test.d.ts +2 -0
- package/dist/web/wsClient.test.d.ts.map +1 -0
- package/dist/web/wsClient.test.js +20 -0
- package/dist/web/wsClient.test.js.map +1 -0
- package/examples/authHandler.test.ts +164 -0
- package/examples/mqtt.test.ts +89 -0
- package/examples/mqtts.test.ts +100 -0
- package/examples/webSocket.test.ts +94 -0
- package/mqttConn/mqttConn.test.ts +9 -9
- package/mqttConn/mqttConn.ts +76 -60
- package/mqttPacket/AuthenticationResult.ts +6 -0
- package/mqttPacket/PacketType.ts +5 -0
- package/mqttPacket/Properties.ts +8 -5
- package/mqttPacket/ReasonCode.ts +8 -9
- package/mqttPacket/RetainHandling.ts +5 -0
- package/mqttPacket/auth.test.ts +1 -1
- package/mqttPacket/auth.ts +44 -51
- package/mqttPacket/codec.ts +147 -0
- package/mqttPacket/connack.ts +63 -73
- package/mqttPacket/connect.test.ts +2 -2
- package/mqttPacket/connect.ts +178 -192
- package/mqttPacket/decoder.test.ts +0 -39
- package/mqttPacket/decoder.ts +17 -46
- package/mqttPacket/disconnect.ts +60 -71
- package/mqttPacket/encoder.test.ts +2 -2
- package/mqttPacket/encoder.ts +13 -46
- package/mqttPacket/mod.ts +48 -204
- package/mqttPacket/pingreq.ts +22 -28
- package/mqttPacket/pingres.ts +22 -28
- package/mqttPacket/protocolLevels.ts +12 -7
- package/mqttPacket/pubblishAcks.ts +61 -75
- package/mqttPacket/publish.ts +70 -84
- package/mqttPacket/publishAcks.test.ts +3 -3
- package/mqttPacket/suback.ts +53 -68
- package/mqttPacket/subscribe.ts +146 -128
- package/mqttPacket/types.ts +2 -35
- package/mqttPacket/unsuback.ts +50 -61
- package/mqttPacket/unsubscribe.ts +77 -72
- package/mqttPacket/validators.ts +5 -31
- package/node/socket-node-stream.test.ts +322 -0
- package/node/socket-node-stream.ts +174 -0
- package/node/tcpClient.test.ts +70 -0
- package/node/tcpClient.ts +33 -17
- package/node/tcpServer.test.ts +24 -20
- package/node/tcpServer.ts +29 -6
- package/node/tlsServer.test.ts +94 -0
- package/node/tlsServer.ts +97 -0
- package/node/wrapNodeSocket.ts +7 -30
- package/package.json +72 -44
- package/persistence/basicPersistence.ts +495 -0
- package/persistence/deps.ts +11 -1
- package/persistence/memory/memoryPersistence.ts +12 -153
- package/persistence/memory/memoryStorage.ts +232 -0
- package/persistence/mod.ts +5 -10
- package/persistence/persistence.test.ts +24 -0
- package/persistence/persistence.testing.ts +1324 -0
- package/persistence/persistence.ts +112 -68
- package/persistence/sqlite/sqliteDatabase.ts +294 -0
- package/persistence/sqlite/sqlitePersistence.test.ts +48 -0
- package/persistence/sqlite/sqlitePersistence.ts +36 -0
- package/persistence/sqlite/sqliteStorage.ts +324 -0
- package/persistence/storage.ts +84 -0
- package/server/config.ts +65 -0
- package/server/context.ts +660 -76
- package/server/deps.ts +24 -5
- package/server/handlers/completeConnect.ts +93 -0
- package/server/handlers/duplicate.test.ts +196 -0
- package/server/handlers/handleAuth.test.ts +225 -0
- package/server/handlers/handleAuth.ts +88 -0
- package/server/handlers/handleConnect.test.ts +589 -0
- package/server/handlers/handleConnect.ts +201 -86
- package/server/handlers/handleConnect.version.test.ts +108 -0
- package/server/handlers/handleDisconnect.test.ts +56 -0
- package/server/handlers/handleDisconnect.ts +3 -3
- package/server/handlers/handlePacket.test.ts +24 -0
- package/server/handlers/handlePacket.ts +30 -8
- package/server/handlers/handlePingreq.test.ts +29 -0
- package/server/handlers/handlePuback.test.ts +28 -0
- package/server/handlers/handlePuback.ts +5 -8
- package/server/handlers/handlePubcomp.test.ts +28 -0
- package/server/handlers/handlePubcomp.ts +5 -4
- package/server/handlers/handlePublish.test.ts +471 -0
- package/server/handlers/handlePublish.ts +188 -35
- package/server/handlers/handlePubrec.test.ts +28 -0
- package/server/handlers/handlePubrec.ts +2 -3
- package/server/handlers/handlePubrel.test.ts +74 -0
- package/server/handlers/handlePubrel.ts +12 -2
- package/server/handlers/handleSubscribe.test.ts +971 -0
- package/server/handlers/handleSubscribe.ts +157 -39
- package/server/handlers/handleUnsubscribe.test.ts +79 -0
- package/server/handlers/handleUnsubscribe.ts +28 -4
- package/server/handlers/keepalive.test.ts +132 -0
- package/server/handlers/session.persistence.test.ts +194 -0
- package/server/handlers/will.delivery.test.ts +221 -0
- package/server/mod.ts +5 -4
- package/server/preconnect.test.ts +151 -0
- package/server/server.ts +117 -19
- package/socket/socket.test.ts +91 -0
- package/socket/socket.ts +85 -34
- package/timer/timer.test.ts +4 -7
- package/timer/timer.ts +36 -0
- package/tools/benchmarks/receiver.ts +51 -0
- package/tools/benchmarks/sender.ts +48 -0
- package/tools/benchmarks/utils.ts +31 -0
- package/tools/mqtt-compat/README.md +130 -0
- package/tools/mqtt-compat/broker.ts +52 -0
- package/tools/mqtt-compat/paho-mqtt4.test.ts +379 -0
- package/tools/mqtt-compat/paho-mqtt5.tests.ts +887 -0
- package/trie/trie.test.ts +9 -1
- package/trie/trie.ts +70 -45
- package/utils/bufferedAsyncIterable.test.ts +92 -0
- package/utils/deferred.test.ts +36 -0
- package/utils/deferred.ts +0 -1
- package/utils/getOrInsertPolyFill.ts +12 -0
- package/utils/logger.test.ts +189 -0
- package/utils/logger.ts +64 -9
- package/utils/mod.ts +15 -1
- package/utils/outboundTopicAliasManager.ts +100 -0
- package/utils/queue.test.ts +61 -0
- package/utils/topicFilter.test.ts +63 -0
- package/utils/topicFilter.ts +61 -0
- package/utils/utils.ts +3 -0
- package/utils/validators.ts +67 -0
- package/web/webSocketStream.ts +97 -0
- package/web/wrapWebSocket.ts +52 -0
- package/web/wsClient.test.ts +26 -0
- package/web/wsClient.ts +37 -0
- package/benchmarks/receiver.ts +0 -35
- package/benchmarks/sender.ts +0 -32
- package/benchmarks/utils.ts +0 -9
- package/dev_utils/dummyConn.ts +0 -110
- package/dev_utils/socketPair.ts +0 -85
- package/dist/persistence/store.d.ts +0 -14
- package/dist/persistence/store.d.ts.map +0 -1
- package/dist/persistence/store.js +0 -2
- package/dist/persistence/store.js.map +0 -1
- package/dist/utils/BufferedAsyncIterable.d.ts.map +0 -1
- package/dist/utils/BufferedAsyncIterable.js.map +0 -1
- package/examples/tcpServer.test.ts +0 -148
- package/persistence/memory/memoryPersistence.test.ts +0 -156
- package/persistence/store.ts +0 -16
- package/server/test/handleConnect.test.ts +0 -122
- package/server/test/test-handlers.ts +0 -53
- /package/utils/{BufferedAsyncIterable.ts โ bufferedAsyncIterable.ts} +0 -0
package/socket/socket.ts
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
/** Net adresses */
|
|
2
|
+
export type NetAddr = {
|
|
3
3
|
transport: "tcp" | "udp";
|
|
4
4
|
hostname: string;
|
|
5
5
|
port: number;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
transport: "vsock";
|
|
15
|
-
cid: number;
|
|
16
|
-
port: number;
|
|
17
|
-
}
|
|
18
|
-
|
|
6
|
+
};
|
|
7
|
+
/** Unix adresses */
|
|
8
|
+
export type UnixAddr = { transport: "unix" | "unixpacket"; path: string };
|
|
9
|
+
/** vSock adresses */
|
|
10
|
+
export type VsockAddr = { transport: "vsock"; cid: number; port: number };
|
|
11
|
+
/** Socket adresses */
|
|
12
|
+
export type SockAddr = NetAddr | UnixAddr | VsockAddr;
|
|
13
|
+
/** Socket connection descriptor. */
|
|
19
14
|
export type SockConn = {
|
|
20
15
|
readable: ReadableStream<Uint8Array>;
|
|
21
16
|
writable: WritableStream<Uint8Array>;
|
|
@@ -25,49 +20,105 @@ export type SockConn = {
|
|
|
25
20
|
};
|
|
26
21
|
|
|
27
22
|
export class Conn {
|
|
28
|
-
reader:
|
|
23
|
+
reader: ReadableStreamDefaultReader<Uint8Array>;
|
|
29
24
|
writer: WritableStreamDefaultWriter<Uint8Array>;
|
|
30
25
|
closed: boolean;
|
|
31
26
|
remoteAddr: SockAddr | undefined;
|
|
32
27
|
closer: () => void;
|
|
33
28
|
|
|
29
|
+
private leftover: Uint8Array = new Uint8Array(0);
|
|
30
|
+
|
|
34
31
|
constructor(sockConn: SockConn) {
|
|
35
32
|
this.closed = false;
|
|
36
|
-
this.reader = sockConn.readable.getReader(
|
|
33
|
+
this.reader = sockConn.readable.getReader();
|
|
37
34
|
this.writer = sockConn.writable.getWriter();
|
|
38
|
-
// this.writer.closed.then(() => this.closed = true);
|
|
39
35
|
this.closer = sockConn.close.bind(sockConn);
|
|
36
|
+
this.reader.closed.catch(() => {});
|
|
37
|
+
this.writer.closed.catch(() => {});
|
|
40
38
|
this.remoteAddr = sockConn.remoteAddr;
|
|
41
39
|
}
|
|
42
40
|
|
|
43
|
-
async read(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
async read(length: number): Promise<Uint8Array | null> {
|
|
42
|
+
if (this.closed || length < 0) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (length === 0) {
|
|
47
|
+
return new Uint8Array(0);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const result = new Uint8Array(length);
|
|
51
|
+
let bytesAccumulated = 0;
|
|
52
|
+
|
|
53
|
+
// Do we have data from the previous read()
|
|
54
|
+
if (this.leftover.length > 0) {
|
|
55
|
+
const take = Math.min(this.leftover.length, length);
|
|
56
|
+
result.set(this.leftover.subarray(0, take), bytesAccumulated);
|
|
57
|
+
bytesAccumulated += take;
|
|
58
|
+
this.leftover = this.leftover.subarray(take);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Keep readin until we have enough data
|
|
62
|
+
while (bytesAccumulated < length) {
|
|
63
|
+
const { value, done } = await this.reader.read();
|
|
64
|
+
|
|
65
|
+
if (value) {
|
|
66
|
+
const needed = length - bytesAccumulated;
|
|
67
|
+
|
|
68
|
+
if (value.length <= needed) {
|
|
69
|
+
// We need the whole chunk
|
|
70
|
+
result.set(value, bytesAccumulated);
|
|
71
|
+
bytesAccumulated += value.length;
|
|
72
|
+
} else {
|
|
73
|
+
// Chunk is bigger than what we need
|
|
74
|
+
result.set(value.subarray(0, needed), bytesAccumulated);
|
|
75
|
+
bytesAccumulated += needed;
|
|
76
|
+
// Save the rest for the next read() call
|
|
77
|
+
this.leftover = value.subarray(needed);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (done) {
|
|
81
|
+
// if the stream closed and not enough data was returned, return null
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
48
84
|
}
|
|
49
|
-
return result
|
|
85
|
+
return result;
|
|
50
86
|
}
|
|
51
87
|
|
|
52
|
-
write(data: Uint8Array): Promise<number> {
|
|
88
|
+
async write(data: Uint8Array): Promise<number> {
|
|
53
89
|
if (this.closed) {
|
|
54
|
-
return Promise.reject();
|
|
90
|
+
return Promise.reject(new Error("Connection closed"));
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
await this.writer.write(data);
|
|
94
|
+
return data.length;
|
|
95
|
+
} catch (err) {
|
|
96
|
+
this.closed = true;
|
|
97
|
+
throw err;
|
|
55
98
|
}
|
|
56
|
-
this.writer.write(data);
|
|
57
|
-
return new Promise((resolve) => resolve(data.length));
|
|
58
99
|
}
|
|
59
100
|
|
|
60
101
|
close() {
|
|
61
102
|
if (!this.closed) {
|
|
62
|
-
try {
|
|
63
|
-
this.writer.close();
|
|
64
|
-
} catch (_err) { /* swallow any errors on close */ }
|
|
65
103
|
this.closed = true;
|
|
104
|
+
|
|
105
|
+
// deno-coverage-ignore-start
|
|
106
|
+
void this.writer.close().catch(() => {
|
|
107
|
+
// ignore duplicate/late close attempts; the stream may already be closed
|
|
108
|
+
});
|
|
109
|
+
// deno-coverage-ignore-stop
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
void this.reader.cancel().catch(() => {
|
|
113
|
+
// ignore duplicate/late cancel attempts; the stream may already be closed
|
|
114
|
+
});
|
|
115
|
+
this.reader?.releaseLock();
|
|
116
|
+
// deno-coverage-ignore
|
|
117
|
+
} catch (_err) { /* swallow */ }
|
|
118
|
+
|
|
66
119
|
try {
|
|
67
120
|
this.closer();
|
|
68
|
-
} catch (_err) {
|
|
69
|
-
// swallow any errors on close
|
|
70
|
-
}
|
|
121
|
+
} catch (_err) { /* swallow */ }
|
|
71
122
|
}
|
|
72
123
|
}
|
|
73
124
|
}
|
package/timer/timer.test.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { Timer } from "./timer.ts";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
3
|
import { test } from "node:test";
|
|
4
|
+
import { delay } from "../dev_utils/mod.ts";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
test("timer should ring", async () => {
|
|
6
|
+
test("timer should ring", { concurrency: false }, async () => {
|
|
10
7
|
const wait = 50;
|
|
11
8
|
const start = Date.now();
|
|
12
9
|
let end = Date.now();
|
|
@@ -18,7 +15,7 @@ test("timer should ring", async () => {
|
|
|
18
15
|
assert.deepStrictEqual(timeDiff < 10, true);
|
|
19
16
|
});
|
|
20
17
|
|
|
21
|
-
test("snooze should work", async () => {
|
|
18
|
+
test("snooze should work", { concurrency: false }, async () => {
|
|
22
19
|
const wait = 50;
|
|
23
20
|
const quarterWait = Math.floor(wait / 4);
|
|
24
21
|
const halfWait = quarterWait * 2;
|
|
@@ -37,7 +34,7 @@ test("snooze should work", async () => {
|
|
|
37
34
|
assert.deepStrictEqual(timeDiff < 15, true, `TimeDiff of ${timeDiff} < 15`);
|
|
38
35
|
});
|
|
39
36
|
|
|
40
|
-
test("clear should work", () => {
|
|
37
|
+
test("clear should work", { concurrency: false }, () => {
|
|
41
38
|
const wait = 50;
|
|
42
39
|
let end = 0;
|
|
43
40
|
const timer = new Timer(() => {
|
package/timer/timer.ts
CHANGED
|
@@ -1,11 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A reusable timer class that executes a callback function after a specified delay.
|
|
3
|
+
* It handles potential drifts or early triggers by checking the actual remaining time
|
|
4
|
+
* before executing the action.
|
|
5
|
+
*/
|
|
1
6
|
export class Timer {
|
|
7
|
+
/** The delay duration in milliseconds before the timer expires. */
|
|
2
8
|
readonly delay: number; // delay in microseconds
|
|
9
|
+
|
|
10
|
+
/** The callback function to perform when the timer expires. */
|
|
3
11
|
// deno-lint-ignore ban-types
|
|
4
12
|
private action: Function; // function to perform when timer expires
|
|
13
|
+
|
|
14
|
+
/** The internal timeout identifier reference, if a timer is active. */
|
|
5
15
|
private timer?: ReturnType<typeof setTimeout>;
|
|
16
|
+
|
|
17
|
+
/** The timestamp (in milliseconds) indicating when the timer is scheduled to end. */
|
|
6
18
|
private end = 0;
|
|
19
|
+
|
|
20
|
+
/** Indicates whether the timer is currently active and running. */
|
|
7
21
|
private running = false;
|
|
8
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Initializes a new instance of the Timer.
|
|
25
|
+
* @param {Function} action - The callback function to execute upon expiration.
|
|
26
|
+
* @param {number} delay - The delay duration in milliseconds.
|
|
27
|
+
* @param {boolean} [wait=false] - If true, the timer will not start automatically until reset() is called.
|
|
28
|
+
*/
|
|
9
29
|
// deno-lint-ignore ban-types
|
|
10
30
|
constructor(action: Function, delay: number, wait = false) {
|
|
11
31
|
this.delay = delay;
|
|
@@ -15,11 +35,20 @@ export class Timer {
|
|
|
15
35
|
}
|
|
16
36
|
}
|
|
17
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Starts the internal setTimeout with the specified delay.
|
|
40
|
+
* @param {number} delay - The duration in milliseconds for the timeout.
|
|
41
|
+
*/
|
|
18
42
|
private startTimer(delay: number): void {
|
|
19
43
|
this.running = true;
|
|
20
44
|
this.timer = setTimeout(() => this.ring(), delay);
|
|
21
45
|
}
|
|
22
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Internal handler triggered when the timeout fires.
|
|
49
|
+
* Verifies if the target end time has genuinely passed, rescheduling if necessary,
|
|
50
|
+
* or executes the action.
|
|
51
|
+
*/
|
|
23
52
|
private ring(): void {
|
|
24
53
|
const timeLeft = this.end - Date.now();
|
|
25
54
|
// check if delay has passed, else execute action
|
|
@@ -31,6 +60,10 @@ export class Timer {
|
|
|
31
60
|
this.action();
|
|
32
61
|
}
|
|
33
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Resets the timer, recalculating the end time and restarting the countdown.
|
|
65
|
+
* If the timer is already running, it updates the target end time.
|
|
66
|
+
*/
|
|
34
67
|
reset(): void {
|
|
35
68
|
this.end = Date.now() + this.delay;
|
|
36
69
|
if (!this.running) {
|
|
@@ -38,6 +71,9 @@ export class Timer {
|
|
|
38
71
|
}
|
|
39
72
|
}
|
|
40
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Cancels the active timeout and stops the timer from running.
|
|
76
|
+
*/
|
|
41
77
|
clear(): void {
|
|
42
78
|
clearTimeout(this.timer);
|
|
43
79
|
this.running = false;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { exit } from "node:process";
|
|
2
|
+
import { getArgs, importClientClass } from "./utils.ts";
|
|
3
|
+
import { logger } from "../../utils/mod.ts";
|
|
4
|
+
import type { LogLevel } from "../../utils/logger.ts";
|
|
5
|
+
import type { QoS } from "../../client/deps.ts";
|
|
6
|
+
|
|
7
|
+
export async function runReceiver(
|
|
8
|
+
level: LogLevel,
|
|
9
|
+
url: string,
|
|
10
|
+
topic: string,
|
|
11
|
+
qos: QoS,
|
|
12
|
+
) {
|
|
13
|
+
logger.level(level);
|
|
14
|
+
const { TcpClient } = await importClientClass();
|
|
15
|
+
const client = new TcpClient();
|
|
16
|
+
client.onError = (err: Error) => {
|
|
17
|
+
console.log("client error", err);
|
|
18
|
+
exit(1);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
await client.connect({
|
|
22
|
+
url: new URL(url),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
await client.subscribe({ subscriptions: [{ topicFilter: topic, qos }] });
|
|
26
|
+
|
|
27
|
+
let counter = 0;
|
|
28
|
+
const interval = 5000;
|
|
29
|
+
|
|
30
|
+
function count() {
|
|
31
|
+
console.log("received/s", (counter / interval) * 1000);
|
|
32
|
+
counter = 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setInterval(count, interval);
|
|
36
|
+
|
|
37
|
+
// // Consume using a callback
|
|
38
|
+
// client.onPacket = async (packet) => {
|
|
39
|
+
// counter++;
|
|
40
|
+
// };
|
|
41
|
+
|
|
42
|
+
// Consume using an AsyncIterator
|
|
43
|
+
for await (const _ of client.messages()) {
|
|
44
|
+
counter++;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (import.meta.main) {
|
|
49
|
+
const { level, url, topic, qos } = getArgs();
|
|
50
|
+
runReceiver(level, url, topic, qos);
|
|
51
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { exit } from "node:process";
|
|
2
|
+
import { runAsap } from "../../dev_utils/timers.ts";
|
|
3
|
+
import { getArgs, importClientClass } from "./utils.ts";
|
|
4
|
+
import { logger } from "../../utils/mod.ts";
|
|
5
|
+
import type { LogLevel } from "../../utils/logger.ts";
|
|
6
|
+
import type { QoS } from "../../client/deps.ts";
|
|
7
|
+
|
|
8
|
+
const { TcpClient } = await importClientClass();
|
|
9
|
+
const client = new TcpClient();
|
|
10
|
+
client.onError = (err: Error) => {
|
|
11
|
+
console.log("client error", err);
|
|
12
|
+
exit(1);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export async function runSender(
|
|
16
|
+
level: LogLevel,
|
|
17
|
+
url: string,
|
|
18
|
+
topic: string,
|
|
19
|
+
qos: QoS,
|
|
20
|
+
) {
|
|
21
|
+
logger.level(level);
|
|
22
|
+
await client.connect({
|
|
23
|
+
url: new URL(url),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const payload = new TextEncoder().encode("payload");
|
|
27
|
+
let sent = 0;
|
|
28
|
+
const interval = 5000;
|
|
29
|
+
|
|
30
|
+
const loop = () => {
|
|
31
|
+
sent++;
|
|
32
|
+
client.publish({ topic, qos, payload })
|
|
33
|
+
.then(() => runAsap(loop));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function count() {
|
|
37
|
+
console.log("sent/s", (sent / interval) * 1000);
|
|
38
|
+
sent = 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
setInterval(count, interval);
|
|
42
|
+
loop();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (import.meta.main) {
|
|
46
|
+
const { level, url, topic, qos } = getArgs();
|
|
47
|
+
runSender(level, url, topic, qos);
|
|
48
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
import { LogLevel } from "../../utils/mod.ts";
|
|
3
|
+
import type { QoS } from "../../client/mod.ts";
|
|
4
|
+
|
|
5
|
+
export async function importClientClass() {
|
|
6
|
+
// @ts-ignore: the Deno global variable is not defined in @types/node,
|
|
7
|
+
// therefore we need to ignore this error because this file
|
|
8
|
+
// is meant to be used in both environments.
|
|
9
|
+
const isDeno = typeof Deno !== "undefined";
|
|
10
|
+
return isDeno
|
|
11
|
+
? (await import("../../deno/tcpClient.ts"))
|
|
12
|
+
: (await import("../../node/tcpClient.ts"));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getArgs() {
|
|
16
|
+
const benchMarkOpts = {
|
|
17
|
+
url: { type: "string", short: "u", default: "mqtt://localhost:1883" },
|
|
18
|
+
topic: { type: "string", short: "t", default: "benchmark" },
|
|
19
|
+
qos: { type: "string", short: "q", default: "0" },
|
|
20
|
+
logLevel: { type: "string", short: "l", default: "error" },
|
|
21
|
+
} as const;
|
|
22
|
+
|
|
23
|
+
const { values } = parseArgs({ options: benchMarkOpts });
|
|
24
|
+
const url = values.url as string;
|
|
25
|
+
const topic = values.topic as string;
|
|
26
|
+
const qos = Number(values.qos ?? 0) as QoS;
|
|
27
|
+
const logLevelKey = (values.logLevel ?? "error") as keyof typeof LogLevel;
|
|
28
|
+
const level = LogLevel[logLevelKey] ?? LogLevel.error;
|
|
29
|
+
|
|
30
|
+
return { url, topic, qos, level };
|
|
31
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# MQTT compatibility tests
|
|
2
|
+
|
|
3
|
+
Measures Opifex's **actual** MQTT 5.0 and 3.1.1 protocol compatibility by
|
|
4
|
+
running the vendor-neutral [Eclipse Paho interoperability suite][paho] against a
|
|
5
|
+
broker booted from this repo, and reports an honest pass percentage. Wired into
|
|
6
|
+
CI by
|
|
7
|
+
[`.github/workflows/mqtt-compat.yml`](../../.github/workflows/mqtt-compat.yml),
|
|
8
|
+
which posts the result as a sticky PR comment and a job summary.
|
|
9
|
+
|
|
10
|
+
## Files
|
|
11
|
+
|
|
12
|
+
| File | Purpose |
|
|
13
|
+
| --------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
14
|
+
| `broker.js` | Boots Opifex on a plain-TCP port (`MQTT_PORT`, default 1883) with the v5 capabilities the suite exercises enabled. |
|
|
15
|
+
| `run_compat.py` | Runs each Paho test in an isolated subprocess against the broker, emits `report.md` + `result.json`. Pure stdlib. |
|
|
16
|
+
|
|
17
|
+
## Running locally
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# 1. Fetch the Paho suite, pinned to the same commit CI uses so local results
|
|
21
|
+
# match. The pin (PAHO_REF) lives in .github/workflows/mqtt-compat.yml.
|
|
22
|
+
git clone https://github.com/eclipse-paho/paho.mqtt.testing /tmp/paho
|
|
23
|
+
git -C /tmp/paho checkout "$(grep -oP 'PAHO_REF:\s*\K\S+' ../../.github/workflows/mqtt-compat.yml)"
|
|
24
|
+
|
|
25
|
+
# 2. Start the broker
|
|
26
|
+
node ./broker.ts &
|
|
27
|
+
|
|
28
|
+
# 3. Run the suites
|
|
29
|
+
python3 ./run_compat.py --paho /tmp/paho/interoperability --host localhost --port 1883 --out report.md --json result.json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`--protocols v5,v3` selects the suites; `--timeout` bounds each test (default
|
|
33
|
+
45s).
|
|
34
|
+
|
|
35
|
+
### Individual test
|
|
36
|
+
|
|
37
|
+
Version 3.11:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
python3 /tmp/paho/interoperability/client_test.py Test.test_retained_messages
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Version 5:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
python3 /tmp/paho/interoperability/client_test5.py Test.test_retained_messages
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## How the score is computed
|
|
50
|
+
|
|
51
|
+
Each Paho `Test` method runs in its **own subprocess** with a hard timeout. This
|
|
52
|
+
matters because the Paho clients do blocking waits with no internal timeout: a
|
|
53
|
+
case where the broker never sends an expected packet would otherwise hang the
|
|
54
|
+
whole run, and a hung test would corrupt the class-level shared clients later
|
|
55
|
+
tests reuse. A timed-out test is recorded as a bounded failure.
|
|
56
|
+
|
|
57
|
+
The percentage is the raw pass rate (`passed / evaluated`). Two categories are
|
|
58
|
+
handled specially:
|
|
59
|
+
|
|
60
|
+
- **Expected gaps** (`EXPECTED_GAPS` in `run_compat.py`) โ features Opifex
|
|
61
|
+
intentionally does not implement yet (e.g. shared subscriptions, which the
|
|
62
|
+
broker advertises as `sharedSubscriptionAvailable=false`). These still count
|
|
63
|
+
as failures; they are only annotated with the reason so the table is readable.
|
|
64
|
+
Because v5 is a work in progress, the harness also detects the reverse: when
|
|
65
|
+
an `EXPECTED_GAPS` test starts **passing** (the feature got implemented), the
|
|
66
|
+
report highlights it with a ๐ banner and the workflow emits a CI warning,
|
|
67
|
+
prompting you to remove the now-stale entry from `EXPECTED_GAPS`.
|
|
68
|
+
- **Harness-limited** (`HARNESS_LIMITED`) โ tests that cannot be evaluated under
|
|
69
|
+
per-test isolation against _any_ broker (currently only `test_flow_control2`,
|
|
70
|
+
which depends on the persistent client the suite sets up only in
|
|
71
|
+
single-process mode). These are **excluded** from the denominator. The
|
|
72
|
+
capability they probe is still measured elsewhere (`test_flow_control1` for
|
|
73
|
+
receive-maximum).
|
|
74
|
+
|
|
75
|
+
### Adding or moving a test category
|
|
76
|
+
|
|
77
|
+
Both lists in `run_compat.py` are keyed
|
|
78
|
+
`protocol -> exact Paho method name ->
|
|
79
|
+
reason string`. Pick the dict by what the
|
|
80
|
+
failure _means_:
|
|
81
|
+
|
|
82
|
+
- A genuine Opifex gap that should drag the score down โ **`EXPECTED_GAPS`**. It
|
|
83
|
+
still runs and counts as a failure; when Opifex later implements it the
|
|
84
|
+
harness flags the ๐ xpass so you remove the entry.
|
|
85
|
+
- A test the harness can't fairly evaluate against _any_ broker โ
|
|
86
|
+
**`HARNESS_LIMITED`**. It is skipped before the gap logic and excluded from
|
|
87
|
+
the denominator. A method must live in **exactly one** list (`HARNESS_LIMITED`
|
|
88
|
+
is checked first, so a duplicate `EXPECTED_GAPS` entry would be dead code).
|
|
89
|
+
|
|
90
|
+
## Coverage scope โ read the percentage correctly
|
|
91
|
+
|
|
92
|
+
The percentage is **"% of the Paho functional suite that passes"**, not "%
|
|
93
|
+
MQTT-5.0-compliant". The Paho suite is a third-party **happy-path functional**
|
|
94
|
+
test: it exercises the user-facing v5 features well (session expiry, will + will
|
|
95
|
+
delay, message expiry, RH/RAP/NL, request/response, payload format, assigned
|
|
96
|
+
client id, server keep alive, inbound topic aliases, max-packet-size rejection,
|
|
97
|
+
PUBLISH user properties), but it touches only 5 reason codes and deliberately
|
|
98
|
+
omits large parts of the spec:
|
|
99
|
+
|
|
100
|
+
- **Error / negative paths** โ most of Opifex's reason codes
|
|
101
|
+
(`lib/constants.js`): `0x87` not-authorized acks, `0x8E` session takeover,
|
|
102
|
+
`0x82` protocol errors, `0x8C` bad auth method, `0x9E`, the CONNACK reject
|
|
103
|
+
codes, broker-initiated DISCONNECT with ReasonString, the oversized-frame read
|
|
104
|
+
latch, wildcard ResponseTopic rejection. These are covered by
|
|
105
|
+
**`test/mqtt5.js`**, which is the authoritative place Opifex's v5 error
|
|
106
|
+
semantics are pinned.
|
|
107
|
+
- **Whole spec chapters** โ AUTH / enhanced auth (ยง4.12), Server Reference
|
|
108
|
+
(`0x9C`/`0x9D`), CONNACK capability flags, ReasonString round-trips, and
|
|
109
|
+
UserProperty on non-PUBLISH packets. Some of these Opifex does not implement;
|
|
110
|
+
the test gap left by _both_ suites is tracked in
|
|
111
|
+
[#1096](https://github.com/moscajs/Opifex/issues/1096).
|
|
112
|
+
|
|
113
|
+
So treat this workflow as the **cross-implementation functional gauge** and
|
|
114
|
+
`test/mqtt5.js` as the **gap-filler** โ they are complementary, not redundant.
|
|
115
|
+
|
|
116
|
+
Some Paho failures are intentional Opifex design decisions rather than bugs (see
|
|
117
|
+
`EXPECTED_GAPS`), and at least one is a genuine spec bug found by this suite:
|
|
118
|
+
[#1095](https://github.com/moscajs/Opifex/issues/1095) (zero-length ClientId +
|
|
119
|
+
CleanSession=0 must be rejected on v3.1.1).
|
|
120
|
+
|
|
121
|
+
## Harness validation
|
|
122
|
+
|
|
123
|
+
The harness was validated against the Paho project's own fully-compliant
|
|
124
|
+
reference broker (`startbroker.py`): it scores **100%** of evaluated v5 tests
|
|
125
|
+
(with `test_flow_control2` excluded as above). Every test Opifex fails, the
|
|
126
|
+
reference broker passes under the identical harness โ so a failure here reflects
|
|
127
|
+
a real difference between Opifex and a spec-compliant broker, not a harness
|
|
128
|
+
artifact.
|
|
129
|
+
|
|
130
|
+
[paho]: https://github.com/eclipse-paho/paho.mqtt.testing
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Standalone aedes broker used by the MQTT compatibility workflow.
|
|
2
|
+
//
|
|
3
|
+
// It boots the broker from *this branch* on a plain-TCP port so the Eclipse Paho
|
|
4
|
+
// interoperability suite (tools/mqtt-compat/run_compat.py) can drive it as an
|
|
5
|
+
// external broker. v5 capabilities the suite exercises are enabled here so the
|
|
6
|
+
// reported score reflects real broker ability, not a broker started with features
|
|
7
|
+
// switched off (e.g. inbound topic aliases are a no-op when topicAliasMaximum: 0).
|
|
8
|
+
//
|
|
9
|
+
// Usage: MQTT_PORT=1883 node tools/mqtt-compat/broker.js
|
|
10
|
+
import { TcpServer } from "../../node/tcpServer.ts";
|
|
11
|
+
import type { Context, ShareName, Topic } from "../../server/mod.ts";
|
|
12
|
+
import { logger } from "../../utils/mod.ts";
|
|
13
|
+
import { isAuthenticatedBroker as isAuthenticated } from "../../dev_utils/mod.ts";
|
|
14
|
+
import { SqlitePersistence } from "../../persistence/sqlite/sqlitePersistence.ts";
|
|
15
|
+
|
|
16
|
+
const port = Number(process.env.MQTT_PORT) || 1883;
|
|
17
|
+
const persistence = new SqlitePersistence();
|
|
18
|
+
|
|
19
|
+
// The Paho `test_subscribe_failure` (v3.1.1 and v5) subscribes to a topic that is
|
|
20
|
+
// "not allowed to be subscribed to" and asserts the broker answers with SUBACK
|
|
21
|
+
// reason code 0x80.
|
|
22
|
+
|
|
23
|
+
const NO_SUBSCRIBE_TOPIC = "test/nosubscribe";
|
|
24
|
+
|
|
25
|
+
function isAuthorizedToSubscribe(
|
|
26
|
+
ctx: Context,
|
|
27
|
+
topic: Topic,
|
|
28
|
+
_shareName: ShareName,
|
|
29
|
+
): boolean {
|
|
30
|
+
logger.debug(
|
|
31
|
+
`Checking authorization of client '${ctx.clientId}' to subscribe to topic '${topic}'`,
|
|
32
|
+
);
|
|
33
|
+
return topic !== NO_SUBSCRIBE_TOPIC;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const tcpServer = new TcpServer({ port }, {
|
|
37
|
+
persistence,
|
|
38
|
+
handlers: {
|
|
39
|
+
isAuthenticated,
|
|
40
|
+
isAuthorizedToSubscribe,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
tcpServer.start();
|
|
44
|
+
logger.info("Server started on port", tcpServer.port);
|
|
45
|
+
|
|
46
|
+
function shutdown() {
|
|
47
|
+
tcpServer.stop();
|
|
48
|
+
process.exit(0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
process.on("SIGTERM", shutdown);
|
|
52
|
+
process.on("SIGINT", shutdown);
|