@seriousme/opifex 1.11.3 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (531) hide show
  1. package/README.md +99 -40
  2. package/bin/conformanceServer.ts +45 -13
  3. package/bin/demoServer.ts +38 -13
  4. package/bin/mqtt.ts +2 -2
  5. package/client/ConnectionState.ts +2 -0
  6. package/client/client.ts +51 -41
  7. package/client/context.ts +75 -21
  8. package/client/deps.ts +4 -0
  9. package/client/handlers/handleAuth.test.ts +193 -0
  10. package/client/handlers/handleAuth.ts +89 -0
  11. package/client/handlers/handleConnack.test.ts +173 -0
  12. package/client/handlers/handleConnack.ts +16 -6
  13. package/client/handlers/handleDisconnect.test.ts +22 -0
  14. package/client/handlers/handleDisconnect.ts +17 -0
  15. package/client/handlers/handlePacket.test.ts +242 -0
  16. package/client/handlers/handlePacket.ts +19 -5
  17. package/client/handlers/handlePuback.test.ts +99 -0
  18. package/client/handlers/handlePuback.ts +6 -0
  19. package/client/handlers/handlePubcomp.test.ts +112 -0
  20. package/client/handlers/handlePubcomp.ts +5 -0
  21. package/client/handlers/handlePublish.test.ts +188 -0
  22. package/client/handlers/handlePubrec.test.ts +119 -0
  23. package/client/handlers/handlePubrec.ts +5 -1
  24. package/client/handlers/handlePubrel.test.ts +136 -0
  25. package/client/handlers/handleSuback.test.ts +122 -0
  26. package/client/handlers/handleSuback.ts +3 -0
  27. package/client/handlers/handleUnsuback.test.ts +101 -0
  28. package/client/mod.ts +1 -1
  29. package/client/store/memoryStore.ts +2 -2
  30. package/client/store/store.ts +3 -1
  31. package/deno/README.md +1 -2
  32. package/deno/tcpClient.test.ts +75 -0
  33. package/deno/tcpClient.ts +16 -11
  34. package/deno/tcpServer.test.ts +22 -21
  35. package/deno/tcpServer.ts +5 -0
  36. package/deno/tlsServer.test.ts +97 -0
  37. package/deno/tlsServer.ts +42 -0
  38. package/deno/wsServer.test.ts +93 -0
  39. package/deno/wsServer.ts +73 -0
  40. package/dev_utils/generateCert.ts +95 -0
  41. package/dev_utils/mockConn.ts +36 -0
  42. package/dev_utils/mockServer.ts +28 -0
  43. package/dev_utils/mod.ts +30 -3
  44. package/dev_utils/packetHelpers.ts +404 -0
  45. package/dev_utils/test-handlers.ts +98 -0
  46. package/dev_utils/timers.ts +14 -0
  47. package/dev_utils/webStreamPair.test.ts +171 -0
  48. package/dev_utils/webStreamPair.ts +143 -0
  49. package/dist/bin/conformanceServer.js +17 -12
  50. package/dist/bin/conformanceServer.js.map +1 -1
  51. package/dist/bin/demoServer.js +16 -12
  52. package/dist/bin/demoServer.js.map +1 -1
  53. package/dist/bin/mqtt.js +2 -2
  54. package/dist/bin/mqtt.js.map +1 -1
  55. package/dist/client/ConnectionState.d.ts +2 -0
  56. package/dist/client/ConnectionState.d.ts.map +1 -1
  57. package/dist/client/ConnectionState.js +2 -0
  58. package/dist/client/ConnectionState.js.map +1 -1
  59. package/dist/client/client.d.ts +13 -16
  60. package/dist/client/client.d.ts.map +1 -1
  61. package/dist/client/client.js +34 -20
  62. package/dist/client/client.js.map +1 -1
  63. package/dist/client/context.d.ts +11 -3
  64. package/dist/client/context.d.ts.map +1 -1
  65. package/dist/client/context.js +44 -12
  66. package/dist/client/context.js.map +1 -1
  67. package/dist/client/deps.d.ts +3 -2
  68. package/dist/client/deps.d.ts.map +1 -1
  69. package/dist/client/deps.js +1 -1
  70. package/dist/client/deps.js.map +1 -1
  71. package/dist/client/handlers/handleAuth.d.ts +9 -0
  72. package/dist/client/handlers/handleAuth.d.ts.map +1 -0
  73. package/dist/client/handlers/handleAuth.js +66 -0
  74. package/dist/client/handlers/handleAuth.js.map +1 -0
  75. package/dist/client/handlers/handleConnack.d.ts +2 -2
  76. package/dist/client/handlers/handleConnack.d.ts.map +1 -1
  77. package/dist/client/handlers/handleConnack.js +16 -6
  78. package/dist/client/handlers/handleConnack.js.map +1 -1
  79. package/dist/client/handlers/handleDisconnect.d.ts +11 -0
  80. package/dist/client/handlers/handleDisconnect.d.ts.map +1 -0
  81. package/dist/client/handlers/handleDisconnect.js +15 -0
  82. package/dist/client/handlers/handleDisconnect.js.map +1 -0
  83. package/dist/client/handlers/handlePacket.d.ts.map +1 -1
  84. package/dist/client/handlers/handlePacket.js +14 -3
  85. package/dist/client/handlers/handlePacket.js.map +1 -1
  86. package/dist/client/handlers/handlePuback.d.ts.map +1 -1
  87. package/dist/client/handlers/handlePuback.js +5 -0
  88. package/dist/client/handlers/handlePuback.js.map +1 -1
  89. package/dist/client/handlers/handlePubcomp.d.ts.map +1 -1
  90. package/dist/client/handlers/handlePubcomp.js +5 -0
  91. package/dist/client/handlers/handlePubcomp.js.map +1 -1
  92. package/dist/client/handlers/handlePubrec.d.ts.map +1 -1
  93. package/dist/client/handlers/handlePubrec.js +5 -1
  94. package/dist/client/handlers/handlePubrec.js.map +1 -1
  95. package/dist/client/handlers/handleSuback.d.ts +1 -0
  96. package/dist/client/handlers/handleSuback.d.ts.map +1 -1
  97. package/dist/client/handlers/handleSuback.js +3 -0
  98. package/dist/client/handlers/handleSuback.js.map +1 -1
  99. package/dist/client/mod.d.ts +1 -1
  100. package/dist/client/mod.d.ts.map +1 -1
  101. package/dist/client/mod.js +1 -1
  102. package/dist/client/mod.js.map +1 -1
  103. package/dist/client/store/memoryStore.d.ts.map +1 -1
  104. package/dist/client/store/memoryStore.js +2 -2
  105. package/dist/client/store/memoryStore.js.map +1 -1
  106. package/dist/client/store/store.d.ts +2 -1
  107. package/dist/client/store/store.d.ts.map +1 -1
  108. package/dist/client/store/store.js +1 -1
  109. package/dist/client/store/store.js.map +1 -1
  110. package/dist/dev_utils/generateCert.d.ts +11 -0
  111. package/dist/dev_utils/generateCert.d.ts.map +1 -0
  112. package/dist/dev_utils/generateCert.js +76 -0
  113. package/dist/dev_utils/generateCert.js.map +1 -0
  114. package/dist/examples/authHandler.test.d.ts +2 -0
  115. package/dist/examples/authHandler.test.d.ts.map +1 -0
  116. package/dist/examples/authHandler.test.js +123 -0
  117. package/dist/examples/authHandler.test.js.map +1 -0
  118. package/dist/examples/mqtt.test.d.ts +2 -0
  119. package/dist/examples/mqtt.test.d.ts.map +1 -0
  120. package/dist/examples/mqtt.test.js +70 -0
  121. package/dist/examples/mqtt.test.js.map +1 -0
  122. package/dist/examples/mqtts.test.d.ts +2 -0
  123. package/dist/examples/mqtts.test.d.ts.map +1 -0
  124. package/dist/examples/mqtts.test.js +81 -0
  125. package/dist/examples/mqtts.test.js.map +1 -0
  126. package/dist/mqttConn/mqttConn.d.ts +23 -15
  127. package/dist/mqttConn/mqttConn.d.ts.map +1 -1
  128. package/dist/mqttConn/mqttConn.js +56 -35
  129. package/dist/mqttConn/mqttConn.js.map +1 -1
  130. package/dist/mqttPacket/AuthenticationResult.d.ts.map +1 -1
  131. package/dist/mqttPacket/BitMask.d.ts.map +1 -1
  132. package/dist/mqttPacket/PacketType.d.ts.map +1 -1
  133. package/dist/mqttPacket/Properties.d.ts +2 -2
  134. package/dist/mqttPacket/Properties.d.ts.map +1 -1
  135. package/dist/mqttPacket/Properties.js.map +1 -1
  136. package/dist/mqttPacket/ReasonCode.d.ts +1 -0
  137. package/dist/mqttPacket/ReasonCode.d.ts.map +1 -1
  138. package/dist/mqttPacket/ReasonCode.js +1 -0
  139. package/dist/mqttPacket/ReasonCode.js.map +1 -1
  140. package/dist/mqttPacket/RetainHandling.d.ts.map +1 -1
  141. package/dist/mqttPacket/auth.d.ts +3 -5
  142. package/dist/mqttPacket/auth.d.ts.map +1 -1
  143. package/dist/mqttPacket/auth.js +31 -30
  144. package/dist/mqttPacket/auth.js.map +1 -1
  145. package/dist/mqttPacket/codec.d.ts +48 -0
  146. package/dist/mqttPacket/codec.d.ts.map +1 -0
  147. package/dist/mqttPacket/codec.js +93 -0
  148. package/dist/mqttPacket/codec.js.map +1 -0
  149. package/dist/mqttPacket/connack.d.ts +4 -5
  150. package/dist/mqttPacket/connack.d.ts.map +1 -1
  151. package/dist/mqttPacket/connack.js +43 -45
  152. package/dist/mqttPacket/connack.js.map +1 -1
  153. package/dist/mqttPacket/connect.d.ts +4 -5
  154. package/dist/mqttPacket/connect.d.ts.map +1 -1
  155. package/dist/mqttPacket/connect.js +156 -157
  156. package/dist/mqttPacket/connect.js.map +1 -1
  157. package/dist/mqttPacket/decoder.d.ts +1 -13
  158. package/dist/mqttPacket/decoder.d.ts.map +1 -1
  159. package/dist/mqttPacket/decoder.js +6 -27
  160. package/dist/mqttPacket/decoder.js.map +1 -1
  161. package/dist/mqttPacket/disconnect.d.ts +4 -5
  162. package/dist/mqttPacket/disconnect.d.ts.map +1 -1
  163. package/dist/mqttPacket/disconnect.js +41 -43
  164. package/dist/mqttPacket/disconnect.js.map +1 -1
  165. package/dist/mqttPacket/encoder.d.ts +1 -15
  166. package/dist/mqttPacket/encoder.d.ts.map +1 -1
  167. package/dist/mqttPacket/encoder.js +4 -27
  168. package/dist/mqttPacket/encoder.js.map +1 -1
  169. package/dist/mqttPacket/mod.d.ts +21 -103
  170. package/dist/mqttPacket/mod.d.ts.map +1 -1
  171. package/dist/mqttPacket/mod.js +5 -94
  172. package/dist/mqttPacket/mod.js.map +1 -1
  173. package/dist/mqttPacket/pingreq.d.ts +4 -5
  174. package/dist/mqttPacket/pingreq.d.ts.map +1 -1
  175. package/dist/mqttPacket/pingreq.js +11 -13
  176. package/dist/mqttPacket/pingreq.js.map +1 -1
  177. package/dist/mqttPacket/pingres.d.ts +4 -5
  178. package/dist/mqttPacket/pingres.d.ts.map +1 -1
  179. package/dist/mqttPacket/pingres.js +11 -13
  180. package/dist/mqttPacket/pingres.js.map +1 -1
  181. package/dist/mqttPacket/protocolLevels.d.ts +11 -6
  182. package/dist/mqttPacket/protocolLevels.d.ts.map +1 -1
  183. package/dist/mqttPacket/protocolLevels.js +5 -1
  184. package/dist/mqttPacket/protocolLevels.js.map +1 -1
  185. package/dist/mqttPacket/pubblishAcks.d.ts +4 -5
  186. package/dist/mqttPacket/pubblishAcks.d.ts.map +1 -1
  187. package/dist/mqttPacket/pubblishAcks.js +43 -45
  188. package/dist/mqttPacket/pubblishAcks.js.map +1 -1
  189. package/dist/mqttPacket/publish.d.ts +5 -5
  190. package/dist/mqttPacket/publish.d.ts.map +1 -1
  191. package/dist/mqttPacket/publish.js +53 -55
  192. package/dist/mqttPacket/publish.js.map +1 -1
  193. package/dist/mqttPacket/suback.d.ts +4 -5
  194. package/dist/mqttPacket/suback.d.ts.map +1 -1
  195. package/dist/mqttPacket/suback.js +38 -40
  196. package/dist/mqttPacket/suback.js.map +1 -1
  197. package/dist/mqttPacket/subscribe.d.ts +36 -7
  198. package/dist/mqttPacket/subscribe.d.ts.map +1 -1
  199. package/dist/mqttPacket/subscribe.js +90 -89
  200. package/dist/mqttPacket/subscribe.js.map +1 -1
  201. package/dist/mqttPacket/types.d.ts +1 -8
  202. package/dist/mqttPacket/types.d.ts.map +1 -1
  203. package/dist/mqttPacket/unsuback.d.ts +4 -5
  204. package/dist/mqttPacket/unsuback.d.ts.map +1 -1
  205. package/dist/mqttPacket/unsuback.js +32 -34
  206. package/dist/mqttPacket/unsuback.js.map +1 -1
  207. package/dist/mqttPacket/unsubscribe.d.ts +23 -6
  208. package/dist/mqttPacket/unsubscribe.d.ts.map +1 -1
  209. package/dist/mqttPacket/unsubscribe.js +45 -44
  210. package/dist/mqttPacket/unsubscribe.js.map +1 -1
  211. package/dist/mqttPacket/validators.d.ts +4 -16
  212. package/dist/mqttPacket/validators.d.ts.map +1 -1
  213. package/dist/mqttPacket/validators.js +5 -26
  214. package/dist/mqttPacket/validators.js.map +1 -1
  215. package/dist/node/tcpClient.d.ts +1 -1
  216. package/dist/node/tcpClient.d.ts.map +1 -1
  217. package/dist/node/tcpClient.js +12 -7
  218. package/dist/node/tcpClient.js.map +1 -1
  219. package/dist/node/tcpServer.d.ts.map +1 -1
  220. package/dist/node/tcpServer.js +4 -0
  221. package/dist/node/tcpServer.js.map +1 -1
  222. package/dist/node/tlsServer.d.ts +19 -0
  223. package/dist/node/tlsServer.d.ts.map +1 -0
  224. package/dist/node/tlsServer.js +58 -0
  225. package/dist/node/tlsServer.js.map +1 -0
  226. package/dist/node/wrapNodeSocket.d.ts.map +1 -1
  227. package/dist/node/wrapNodeSocket.js +6 -28
  228. package/dist/node/wrapNodeSocket.js.map +1 -1
  229. package/dist/persistence/basicPersistence.d.ts +36 -0
  230. package/dist/persistence/basicPersistence.d.ts.map +1 -0
  231. package/dist/persistence/basicPersistence.js +306 -0
  232. package/dist/persistence/basicPersistence.js.map +1 -0
  233. package/dist/persistence/deps.d.ts +3 -2
  234. package/dist/persistence/deps.d.ts.map +1 -1
  235. package/dist/persistence/deps.js +2 -1
  236. package/dist/persistence/deps.js.map +1 -1
  237. package/dist/persistence/memory/memoryPersistence.d.ts +6 -23
  238. package/dist/persistence/memory/memoryPersistence.d.ts.map +1 -1
  239. package/dist/persistence/memory/memoryPersistence.js +12 -115
  240. package/dist/persistence/memory/memoryPersistence.js.map +1 -1
  241. package/dist/persistence/memory/memoryStorage.d.ts +45 -0
  242. package/dist/persistence/memory/memoryStorage.d.ts.map +1 -0
  243. package/dist/persistence/memory/memoryStorage.js +143 -0
  244. package/dist/persistence/memory/memoryStorage.js.map +1 -0
  245. package/dist/persistence/mod.d.ts +3 -3
  246. package/dist/persistence/mod.d.ts.map +1 -1
  247. package/dist/persistence/mod.js +6 -1
  248. package/dist/persistence/mod.js.map +1 -1
  249. package/dist/persistence/persistence.d.ts +44 -69
  250. package/dist/persistence/persistence.d.ts.map +1 -1
  251. package/dist/persistence/persistence.js +1 -2
  252. package/dist/persistence/persistence.js.map +1 -1
  253. package/dist/persistence/sqlite/sqliteDatabase.d.ts +46 -0
  254. package/dist/persistence/sqlite/sqliteDatabase.d.ts.map +1 -0
  255. package/dist/persistence/sqlite/sqliteDatabase.js +215 -0
  256. package/dist/persistence/sqlite/sqliteDatabase.js.map +1 -0
  257. package/dist/persistence/sqlite/sqlitePersistence.d.ts +16 -0
  258. package/dist/persistence/sqlite/sqlitePersistence.d.ts.map +1 -0
  259. package/dist/persistence/sqlite/sqlitePersistence.js +29 -0
  260. package/dist/persistence/sqlite/sqlitePersistence.js.map +1 -0
  261. package/dist/persistence/sqlite/sqliteStorage.d.ts +36 -0
  262. package/dist/persistence/sqlite/sqliteStorage.d.ts.map +1 -0
  263. package/dist/persistence/sqlite/sqliteStorage.js +194 -0
  264. package/dist/persistence/sqlite/sqliteStorage.js.map +1 -0
  265. package/dist/persistence/storage.d.ts +38 -0
  266. package/dist/persistence/storage.d.ts.map +1 -0
  267. package/dist/persistence/storage.js +5 -0
  268. package/dist/persistence/storage.js.map +1 -0
  269. package/dist/server/config.d.ts +47 -0
  270. package/dist/server/config.d.ts.map +1 -0
  271. package/dist/server/config.js +41 -0
  272. package/dist/server/config.js.map +1 -0
  273. package/dist/server/context.d.ts +198 -24
  274. package/dist/server/context.d.ts.map +1 -1
  275. package/dist/server/context.js +432 -53
  276. package/dist/server/context.js.map +1 -1
  277. package/dist/server/deps.d.ts +5 -6
  278. package/dist/server/deps.d.ts.map +1 -1
  279. package/dist/server/deps.js +2 -2
  280. package/dist/server/deps.js.map +1 -1
  281. package/dist/server/handlers/completeConnect.d.ts +8 -0
  282. package/dist/server/handlers/completeConnect.d.ts.map +1 -0
  283. package/dist/server/handlers/completeConnect.js +74 -0
  284. package/dist/server/handlers/completeConnect.js.map +1 -0
  285. package/dist/server/handlers/handleAuth.d.ts +9 -0
  286. package/dist/server/handlers/handleAuth.d.ts.map +1 -0
  287. package/dist/server/handlers/handleAuth.js +69 -0
  288. package/dist/server/handlers/handleAuth.js.map +1 -0
  289. package/dist/server/handlers/handleConnect.d.ts +2 -4
  290. package/dist/server/handlers/handleConnect.d.ts.map +1 -1
  291. package/dist/server/handlers/handleConnect.js +140 -67
  292. package/dist/server/handlers/handleConnect.js.map +1 -1
  293. package/dist/server/handlers/handleDisconnect.d.ts +1 -1
  294. package/dist/server/handlers/handleDisconnect.d.ts.map +1 -1
  295. package/dist/server/handlers/handleDisconnect.js +3 -3
  296. package/dist/server/handlers/handleDisconnect.js.map +1 -1
  297. package/dist/server/handlers/handlePacket.d.ts.map +1 -1
  298. package/dist/server/handlers/handlePacket.js +19 -6
  299. package/dist/server/handlers/handlePacket.js.map +1 -1
  300. package/dist/server/handlers/handlePuback.d.ts +1 -3
  301. package/dist/server/handlers/handlePuback.d.ts.map +1 -1
  302. package/dist/server/handlers/handlePuback.js +2 -8
  303. package/dist/server/handlers/handlePuback.js.map +1 -1
  304. package/dist/server/handlers/handlePubcomp.d.ts +1 -1
  305. package/dist/server/handlers/handlePubcomp.d.ts.map +1 -1
  306. package/dist/server/handlers/handlePubcomp.js +2 -4
  307. package/dist/server/handlers/handlePubcomp.js.map +1 -1
  308. package/dist/server/handlers/handlePublish.d.ts +1 -1
  309. package/dist/server/handlers/handlePublish.d.ts.map +1 -1
  310. package/dist/server/handlers/handlePublish.js +149 -45
  311. package/dist/server/handlers/handlePublish.js.map +1 -1
  312. package/dist/server/handlers/handlePubrec.d.ts.map +1 -1
  313. package/dist/server/handlers/handlePubrec.js +2 -3
  314. package/dist/server/handlers/handlePubrec.js.map +1 -1
  315. package/dist/server/handlers/handlePubrel.d.ts.map +1 -1
  316. package/dist/server/handlers/handlePubrel.js +6 -2
  317. package/dist/server/handlers/handlePubrel.js.map +1 -1
  318. package/dist/server/handlers/handleSubscribe.d.ts +1 -6
  319. package/dist/server/handlers/handleSubscribe.d.ts.map +1 -1
  320. package/dist/server/handlers/handleSubscribe.js +99 -38
  321. package/dist/server/handlers/handleSubscribe.js.map +1 -1
  322. package/dist/server/handlers/handleUnsubscribe.d.ts.map +1 -1
  323. package/dist/server/handlers/handleUnsubscribe.js +19 -4
  324. package/dist/server/handlers/handleUnsubscribe.js.map +1 -1
  325. package/dist/server/mod.d.ts +3 -3
  326. package/dist/server/mod.d.ts.map +1 -1
  327. package/dist/server/mod.js +1 -1
  328. package/dist/server/mod.js.map +1 -1
  329. package/dist/server/server.d.ts +29 -6
  330. package/dist/server/server.d.ts.map +1 -1
  331. package/dist/server/server.js +84 -15
  332. package/dist/server/server.js.map +1 -1
  333. package/dist/socket/socket.d.ts +11 -9
  334. package/dist/socket/socket.d.ts.map +1 -1
  335. package/dist/socket/socket.js +66 -18
  336. package/dist/socket/socket.js.map +1 -1
  337. package/dist/timer/timer.d.ts +32 -0
  338. package/dist/timer/timer.d.ts.map +1 -1
  339. package/dist/timer/timer.js +32 -0
  340. package/dist/timer/timer.js.map +1 -1
  341. package/dist/trie/trie.d.ts +10 -5
  342. package/dist/trie/trie.d.ts.map +1 -1
  343. package/dist/trie/trie.js +61 -41
  344. package/dist/trie/trie.js.map +1 -1
  345. package/dist/utils/assert.d.ts.map +1 -1
  346. package/dist/utils/{BufferedAsyncIterable.d.ts → bufferedAsyncIterable.d.ts} +1 -1
  347. package/dist/utils/bufferedAsyncIterable.d.ts.map +1 -0
  348. package/dist/utils/{BufferedAsyncIterable.js → bufferedAsyncIterable.js} +1 -1
  349. package/dist/utils/bufferedAsyncIterable.js.map +1 -0
  350. package/dist/utils/deferred.d.ts.map +1 -1
  351. package/dist/utils/deferred.js.map +1 -1
  352. package/dist/utils/getOrInsertPolyFill.d.ts +2 -0
  353. package/dist/utils/getOrInsertPolyFill.d.ts.map +1 -0
  354. package/dist/utils/getOrInsertPolyFill.js +12 -0
  355. package/dist/utils/getOrInsertPolyFill.js.map +1 -0
  356. package/dist/utils/logger.d.ts +40 -3
  357. package/dist/utils/logger.d.ts.map +1 -1
  358. package/dist/utils/logger.js +53 -7
  359. package/dist/utils/logger.js.map +1 -1
  360. package/dist/utils/mod.d.ts +6 -1
  361. package/dist/utils/mod.d.ts.map +1 -1
  362. package/dist/utils/mod.js +5 -1
  363. package/dist/utils/mod.js.map +1 -1
  364. package/dist/utils/outboundTopicAliasManager.d.ts +52 -0
  365. package/dist/utils/outboundTopicAliasManager.d.ts.map +1 -0
  366. package/dist/utils/outboundTopicAliasManager.js +74 -0
  367. package/dist/utils/outboundTopicAliasManager.js.map +1 -0
  368. package/dist/utils/queue.d.ts.map +1 -1
  369. package/dist/utils/topicFilter.d.ts +32 -0
  370. package/dist/utils/topicFilter.d.ts.map +1 -0
  371. package/dist/utils/topicFilter.js +52 -0
  372. package/dist/utils/topicFilter.js.map +1 -0
  373. package/dist/utils/utils.d.ts +2 -0
  374. package/dist/utils/utils.d.ts.map +1 -1
  375. package/dist/utils/utils.js +2 -0
  376. package/dist/utils/utils.js.map +1 -1
  377. package/dist/utils/validators.d.ts +34 -0
  378. package/dist/utils/validators.d.ts.map +1 -0
  379. package/dist/utils/validators.js +61 -0
  380. package/dist/utils/validators.js.map +1 -0
  381. package/dist/web/webSocketStream.d.ts +29 -0
  382. package/dist/web/webSocketStream.d.ts.map +1 -0
  383. package/dist/web/webSocketStream.js +69 -0
  384. package/dist/web/webSocketStream.js.map +1 -0
  385. package/dist/web/wrapWebSocket.d.ts +12 -0
  386. package/dist/web/wrapWebSocket.d.ts.map +1 -0
  387. package/dist/web/wrapWebSocket.js +41 -0
  388. package/dist/web/wrapWebSocket.js.map +1 -0
  389. package/dist/web/wsClient.d.ts +7 -0
  390. package/dist/web/wsClient.d.ts.map +1 -0
  391. package/dist/web/wsClient.js +22 -0
  392. package/dist/web/wsClient.js.map +1 -0
  393. package/dist/web/wsClient.test.d.ts +2 -0
  394. package/dist/web/wsClient.test.d.ts.map +1 -0
  395. package/dist/web/wsClient.test.js +20 -0
  396. package/dist/web/wsClient.test.js.map +1 -0
  397. package/examples/authHandler.test.ts +164 -0
  398. package/examples/mqtt.test.ts +89 -0
  399. package/examples/mqtts.test.ts +100 -0
  400. package/examples/webSocket.test.ts +94 -0
  401. package/mqttConn/mqttConn.test.ts +9 -9
  402. package/mqttConn/mqttConn.ts +76 -44
  403. package/mqttPacket/Properties.ts +6 -3
  404. package/mqttPacket/ReasonCode.ts +2 -1
  405. package/mqttPacket/auth.test.ts +1 -1
  406. package/mqttPacket/auth.ts +41 -48
  407. package/mqttPacket/codec.ts +146 -0
  408. package/mqttPacket/connack.ts +57 -68
  409. package/mqttPacket/connect.test.ts +2 -2
  410. package/mqttPacket/connect.ts +175 -182
  411. package/mqttPacket/decoder.test.ts +0 -39
  412. package/mqttPacket/decoder.ts +8 -35
  413. package/mqttPacket/disconnect.ts +57 -68
  414. package/mqttPacket/encoder.ts +5 -40
  415. package/mqttPacket/mod.ts +48 -200
  416. package/mqttPacket/pingreq.ts +21 -27
  417. package/mqttPacket/pingres.ts +21 -27
  418. package/mqttPacket/protocolLevels.ts +12 -7
  419. package/mqttPacket/pubblishAcks.ts +56 -70
  420. package/mqttPacket/publish.ts +67 -74
  421. package/mqttPacket/suback.ts +48 -58
  422. package/mqttPacket/subscribe.ts +141 -117
  423. package/mqttPacket/types.ts +1 -9
  424. package/mqttPacket/unsuback.ts +46 -58
  425. package/mqttPacket/unsubscribe.ts +74 -63
  426. package/mqttPacket/validators.ts +5 -31
  427. package/node/socket-node-stream.test.ts +322 -0
  428. package/node/socket-node-stream.ts +174 -0
  429. package/node/tcpClient.test.ts +70 -0
  430. package/node/tcpClient.ts +13 -12
  431. package/node/tcpServer.test.ts +24 -20
  432. package/node/tcpServer.ts +6 -0
  433. package/node/tlsServer.test.ts +94 -0
  434. package/node/tlsServer.ts +81 -0
  435. package/node/wrapNodeSocket.ts +7 -30
  436. package/package.json +72 -44
  437. package/persistence/basicPersistence.ts +495 -0
  438. package/persistence/deps.ts +11 -1
  439. package/persistence/memory/memoryPersistence.ts +12 -153
  440. package/persistence/memory/memoryStorage.ts +232 -0
  441. package/persistence/mod.ts +4 -9
  442. package/persistence/persistence.test.ts +24 -0
  443. package/persistence/persistence.testing.ts +1324 -0
  444. package/persistence/persistence.ts +111 -67
  445. package/persistence/sqlite/sqliteDatabase.ts +294 -0
  446. package/persistence/sqlite/sqlitePersistence.test.ts +48 -0
  447. package/persistence/sqlite/sqlitePersistence.ts +36 -0
  448. package/persistence/sqlite/sqliteStorage.ts +324 -0
  449. package/persistence/storage.ts +84 -0
  450. package/server/config.ts +65 -0
  451. package/server/context.ts +658 -74
  452. package/server/deps.ts +25 -5
  453. package/server/handlers/completeConnect.ts +93 -0
  454. package/server/handlers/duplicate.test.ts +196 -0
  455. package/server/handlers/handleAuth.test.ts +225 -0
  456. package/server/handlers/handleAuth.ts +88 -0
  457. package/server/handlers/handleConnect.test.ts +589 -0
  458. package/server/handlers/handleConnect.ts +201 -86
  459. package/server/handlers/handleConnect.version.test.ts +108 -0
  460. package/server/handlers/handleDisconnect.test.ts +56 -0
  461. package/server/handlers/handleDisconnect.ts +3 -3
  462. package/server/handlers/handlePacket.test.ts +24 -0
  463. package/server/handlers/handlePacket.ts +30 -8
  464. package/server/handlers/handlePingreq.test.ts +29 -0
  465. package/server/handlers/handlePuback.test.ts +28 -0
  466. package/server/handlers/handlePuback.ts +5 -8
  467. package/server/handlers/handlePubcomp.test.ts +28 -0
  468. package/server/handlers/handlePubcomp.ts +5 -4
  469. package/server/handlers/handlePublish.test.ts +471 -0
  470. package/server/handlers/handlePublish.ts +189 -35
  471. package/server/handlers/handlePubrec.test.ts +28 -0
  472. package/server/handlers/handlePubrec.ts +2 -3
  473. package/server/handlers/handlePubrel.test.ts +74 -0
  474. package/server/handlers/handlePubrel.ts +12 -2
  475. package/server/handlers/handleSubscribe.test.ts +971 -0
  476. package/server/handlers/handleSubscribe.ts +158 -39
  477. package/server/handlers/handleUnsubscribe.test.ts +79 -0
  478. package/server/handlers/handleUnsubscribe.ts +29 -5
  479. package/server/handlers/keepalive.test.ts +132 -0
  480. package/server/handlers/session.persistence.test.ts +194 -0
  481. package/server/handlers/will.delivery.test.ts +221 -0
  482. package/server/mod.ts +4 -3
  483. package/server/preconnect.test.ts +151 -0
  484. package/server/server.ts +115 -17
  485. package/socket/socket.test.ts +91 -0
  486. package/socket/socket.ts +81 -34
  487. package/timer/timer.test.ts +4 -7
  488. package/timer/timer.ts +36 -0
  489. package/tools/benchmarks/receiver.ts +51 -0
  490. package/tools/benchmarks/sender.ts +48 -0
  491. package/tools/benchmarks/utils.ts +31 -0
  492. package/tools/mqtt-compat/README.md +130 -0
  493. package/tools/mqtt-compat/broker.ts +52 -0
  494. package/tools/mqtt-compat/paho-mqtt4.test.ts +379 -0
  495. package/tools/mqtt-compat/paho-mqtt5.tests.ts +887 -0
  496. package/trie/trie.test.ts +9 -1
  497. package/trie/trie.ts +70 -45
  498. package/utils/bufferedAsyncIterable.test.ts +92 -0
  499. package/utils/deferred.test.ts +36 -0
  500. package/utils/deferred.ts +0 -1
  501. package/utils/getOrInsertPolyFill.ts +12 -0
  502. package/utils/logger.test.ts +189 -0
  503. package/utils/logger.ts +62 -7
  504. package/utils/mod.ts +15 -1
  505. package/utils/outboundTopicAliasManager.ts +100 -0
  506. package/utils/queue.test.ts +61 -0
  507. package/utils/topicFilter.test.ts +63 -0
  508. package/utils/topicFilter.ts +61 -0
  509. package/utils/utils.ts +3 -0
  510. package/utils/validators.ts +67 -0
  511. package/web/webSocketStream.ts +97 -0
  512. package/web/wrapWebSocket.ts +52 -0
  513. package/web/wsClient.test.ts +26 -0
  514. package/web/wsClient.ts +25 -0
  515. package/benchmarks/receiver.ts +0 -35
  516. package/benchmarks/sender.ts +0 -32
  517. package/benchmarks/utils.ts +0 -9
  518. package/dev_utils/dummyConn.ts +0 -110
  519. package/dev_utils/socketPair.ts +0 -85
  520. package/dist/persistence/store.d.ts +0 -14
  521. package/dist/persistence/store.d.ts.map +0 -1
  522. package/dist/persistence/store.js +0 -2
  523. package/dist/persistence/store.js.map +0 -1
  524. package/dist/utils/BufferedAsyncIterable.d.ts.map +0 -1
  525. package/dist/utils/BufferedAsyncIterable.js.map +0 -1
  526. package/examples/tcpServer.test.ts +0 -148
  527. package/persistence/memory/memoryPersistence.test.ts +0 -156
  528. package/persistence/store.ts +0 -16
  529. package/server/test/handleConnect.test.ts +0 -122
  530. package/server/test/test-handlers.ts +0 -53
  531. /package/utils/{BufferedAsyncIterable.ts → bufferedAsyncIterable.ts} +0 -0
package/client/context.ts CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  import type {
10
10
  AnyPacket,
11
11
  ConnectPacket,
12
- MemoryStore,
12
+ IStore,
13
13
  PacketId,
14
14
  ProtocolLevel,
15
15
  PublishPacket,
@@ -17,6 +17,8 @@ import type {
17
17
  SockConn,
18
18
  SubscribePacket,
19
19
  TAuthenticationResult,
20
+ TPacketType,
21
+ TReasonCode,
20
22
  UnsubscribePacket,
21
23
  } from "./deps.ts";
22
24
 
@@ -26,6 +28,24 @@ import { ConnectionState } from "./ConnectionState.ts";
26
28
  import type { Client } from "./client.ts";
27
29
  import { assert } from "../utils/assert.ts";
28
30
 
31
+ /**
32
+ * packets not allowed during authentication
33
+ */
34
+ function blockedDuringAuthentication(pktType: TPacketType) {
35
+ return (
36
+ pktType === PacketType.publish ||
37
+ pktType === PacketType.subscribe ||
38
+ pktType === PacketType.unsubscribe
39
+ );
40
+ }
41
+
42
+ /** Possible results from authHandler */
43
+ export type AuthenticatedResult = {
44
+ reasonCode: TReasonCode;
45
+ reasonString?: string;
46
+ authData?: Uint8Array;
47
+ };
48
+
29
49
  export class Context {
30
50
  mqttConn?: MqttConn;
31
51
  #connectionState: TConnectionState;
@@ -35,10 +55,10 @@ export class Context {
35
55
  unresolvedPublish: Map<PacketId, Deferred<void>>;
36
56
  unresolvedSubscribe: Map<PacketId, Deferred<ReturnCodes>>;
37
57
  unresolvedUnSubscribe: Map<PacketId, Deferred<void>>;
38
- store: MemoryStore;
58
+ store: IStore;
39
59
  #client: Client;
40
60
 
41
- constructor(store: MemoryStore, client: Client) {
61
+ constructor(store: IStore, client: Client) {
42
62
  this.#client = client;
43
63
  this.store = store;
44
64
  this.#connectionState = ConnectionState.offline;
@@ -64,6 +84,25 @@ export class Context {
64
84
  }
65
85
  }
66
86
 
87
+ authHandler(
88
+ _ctx: Context,
89
+ authMethod: string,
90
+ authData: Uint8Array,
91
+ ): AuthenticatedResult | Promise<AuthenticatedResult> {
92
+ return this.#client.onAuth(authMethod, authData);
93
+ }
94
+
95
+ setPingTimer(interval: number) {
96
+ if (this.pingTimer) {
97
+ this.pingTimer.clear();
98
+ }
99
+ this.pingTimer = new Timer(
100
+ this.sendPing.bind(this),
101
+ interval * 1000,
102
+ true,
103
+ );
104
+ }
105
+
67
106
  async connect(packet: ConnectPacket) {
68
107
  this.connectionState = ConnectionState.connecting;
69
108
  if (packet.protocolLevel === MQTTLevel.unknown) {
@@ -73,16 +112,15 @@ export class Context {
73
112
  await this.mqttConn?.send(packet);
74
113
  const keepAlive = packet.keepAlive || 0;
75
114
  if (keepAlive > 0) {
76
- this.pingTimer = new Timer(
77
- this.sendPing.bind(this),
78
- keepAlive * 1000,
79
- true,
80
- );
115
+ this.setPingTimer(keepAlive);
81
116
  }
82
117
  }
83
118
 
84
119
  async disconnect() {
85
- if (this.connectionState !== ConnectionState.connected) {
120
+ if (
121
+ this.connectionState !== ConnectionState.connected &&
122
+ this.connectionState !== ConnectionState.authenticating
123
+ ) {
86
124
  throw "Not connected";
87
125
  }
88
126
  if (this.mqttConn) {
@@ -97,14 +135,29 @@ export class Context {
97
135
  }
98
136
 
99
137
  async send(packet: AnyPacket) {
100
- logger.debug({ send: packet });
101
- if (
102
- this.connectionState === ConnectionState.connected &&
103
- !this.mqttConn?.isClosed
104
- ) {
105
- await this.mqttConn?.send(packet);
106
- this.pingTimer?.reset();
107
- return;
138
+ logger.debug("client.ctx.send", this.#connectionState, { packet });
139
+ if (!this.mqttConn?.isClosed) {
140
+ if (this.connectionState === ConnectionState.connected) {
141
+ await this.mqttConn?.send(packet);
142
+ this.pingTimer?.reset();
143
+ return;
144
+ }
145
+ if (
146
+ this.connectionState === ConnectionState.connecting &&
147
+ packet.type === PacketType.auth
148
+ ) {
149
+ await this.mqttConn?.send(packet);
150
+ this.pingTimer?.reset();
151
+ return;
152
+ }
153
+ if (
154
+ this.connectionState === ConnectionState.authenticating &&
155
+ !blockedDuringAuthentication(packet.type)
156
+ ) {
157
+ await this.mqttConn?.send(packet);
158
+ this.pingTimer?.reset();
159
+ return;
160
+ }
108
161
  }
109
162
  logger.debug("not connected");
110
163
  this.pingTimer?.clear();
@@ -122,6 +175,7 @@ export class Context {
122
175
  connectPacket: ConnectPacket,
123
176
  ): Promise<boolean> {
124
177
  this.mqttConn = new MqttConn({ conn });
178
+ this.mqttConn.codecOpts.protocolLevel = connectPacket.protocolLevel;
125
179
  try {
126
180
  logger.debug("Send connect packet", connectPacket);
127
181
  await this.connect(connectPacket);
@@ -136,7 +190,7 @@ export class Context {
136
190
  `Caught something that is not an instance of Error: ${err}`,
137
191
  );
138
192
  queueMicrotask(() => this.#client.onError(err));
139
- logger.debug(`error ${err}`);
193
+ logger.debug("error", err);
140
194
  if (!this.mqttConn.isClosed) {
141
195
  this.mqttConn.close();
142
196
  }
@@ -164,7 +218,7 @@ export class Context {
164
218
  await this.send(packet);
165
219
  return;
166
220
  }
167
- packet.id = this.store.nextId();
221
+ packet.id = await this.store.nextId();
168
222
  this.store.pendingOutgoing.set(packet.id, packet);
169
223
  const deferred = new Deferred<void>();
170
224
  this.unresolvedPublish.set(packet.id, deferred);
@@ -173,7 +227,7 @@ export class Context {
173
227
  }
174
228
 
175
229
  async subscribe(packet: SubscribePacket): Promise<ReturnCodes> {
176
- packet.id = this.store.nextId();
230
+ packet.id = await this.store.nextId();
177
231
  this.store.pendingOutgoing.set(packet.id, packet);
178
232
  const deferred = new Deferred<ReturnCodes>();
179
233
  this.unresolvedSubscribe.set(packet.id, deferred);
@@ -182,7 +236,7 @@ export class Context {
182
236
  }
183
237
 
184
238
  async unsubscribe(packet: UnsubscribePacket): Promise<void> {
185
- packet.id = this.store.nextId();
239
+ packet.id = await this.store.nextId();
186
240
  this.store.pendingOutgoing.set(packet.id, packet);
187
241
  const deferred = new Deferred<void>();
188
242
  this.unresolvedUnSubscribe.set(packet.id, deferred);
package/client/deps.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export type {
2
2
  AnyPacket,
3
+ AuthPacket,
3
4
  ConnackPacket,
4
5
  ConnectPacket,
5
6
  DisconnectPacket,
@@ -18,6 +19,7 @@ export type {
18
19
  SubscribePacket,
19
20
  TAuthenticationResult,
20
21
  Topic,
22
+ TPacketType,
21
23
  TReasonCode,
22
24
  UnsubackPacket,
23
25
  UnsubscribePacket,
@@ -31,6 +33,7 @@ export {
31
33
  MQTTLevel,
32
34
  PacketNameByType,
33
35
  PacketType,
36
+ ReasonCode,
34
37
  ReasonCodeByNumber,
35
38
  } from "../mqttPacket/mod.ts";
36
39
 
@@ -39,3 +42,4 @@ export type { SockConn } from "../socket/socket.ts";
39
42
  export { Timer } from "../timer/timer.ts";
40
43
  export { BufferedAsyncIterable, Deferred, logger } from "../utils/mod.ts";
41
44
  export { MemoryStore } from "./store/memoryStore.ts";
45
+ export type { IStore } from "./store/store.ts";
@@ -0,0 +1,193 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { handleAuth } from "./handleAuth.ts";
4
+ import { ConnectionState } from "../ConnectionState.ts";
5
+ import { PacketType, ReasonCode } from "../deps.ts";
6
+ import type { AuthPacket } from "../deps.ts";
7
+ import type { AuthenticatedResult } from "../context.ts";
8
+ import { Deferred } from "../../utils/mod.ts";
9
+
10
+ function createMockContext() {
11
+ const sentPackets: unknown[] = [];
12
+ return {
13
+ connectionState: ConnectionState.connecting as string,
14
+ pingTimer: { clear: () => {} },
15
+ unresolvedConnect: new Deferred<number>(),
16
+ authHandler: (
17
+ _ctx: unknown,
18
+ _authMethod: string,
19
+ _authData: Uint8Array,
20
+ ): Promise<AuthenticatedResult> => {
21
+ return Promise.resolve({
22
+ reasonCode: ReasonCode.continueAuthentication,
23
+ authData: new Uint8Array([1, 2, 3]),
24
+ });
25
+ },
26
+ send: (packet: unknown) => {
27
+ sentPackets.push(packet);
28
+ },
29
+ sentPackets,
30
+ };
31
+ }
32
+
33
+ test("handleAuth sets connected state on ReasonCode.success", async () => {
34
+ const ctx = createMockContext();
35
+ const packet: AuthPacket = {
36
+ type: PacketType.auth,
37
+ protocolLevel: 5 as const,
38
+ reasonCode: ReasonCode.success,
39
+ };
40
+
41
+ await handleAuth(ctx as never, packet);
42
+
43
+ assert.deepStrictEqual(
44
+ ctx.connectionState,
45
+ ConnectionState.connected,
46
+ "Should set connection state to connected when reasonCode is success",
47
+ );
48
+ });
49
+
50
+ test("handleAuth handles authentication failure when connecting", async () => {
51
+ const ctx = createMockContext();
52
+ ctx.connectionState = ConnectionState.connecting;
53
+
54
+ const packet: AuthPacket = {
55
+ type: PacketType.auth,
56
+ protocolLevel: 5 as const,
57
+ reasonCode: ReasonCode.badAuthenticationMethod,
58
+ };
59
+
60
+ await handleAuth(ctx as never, packet);
61
+
62
+ assert.deepStrictEqual(
63
+ ctx.connectionState,
64
+ ConnectionState.disconnecting,
65
+ "Should transition state to disconnecting on failure during connect",
66
+ );
67
+
68
+ await assert.rejects(
69
+ ctx.unresolvedConnect.promise,
70
+ /Connect failed/,
71
+ "Should reject unresolvedConnect with connect failed error",
72
+ );
73
+ });
74
+
75
+ test("handleAuth throws error on authentication failure when connected", async () => {
76
+ const ctx = createMockContext();
77
+ ctx.connectionState = ConnectionState.connected;
78
+
79
+ const packet: AuthPacket = {
80
+ type: PacketType.auth,
81
+ protocolLevel: 5 as const,
82
+ reasonCode: ReasonCode.badAuthenticationMethod,
83
+ };
84
+
85
+ await assert.rejects(
86
+ async () => {
87
+ await handleAuth(ctx as never, packet);
88
+ },
89
+ Error,
90
+ "Should throw an error if reasonCode indicates failure after already connected",
91
+ );
92
+ });
93
+
94
+ test("handleAuth throws error if authMethod or authData is missing", async () => {
95
+ const ctx = createMockContext();
96
+ const packet: AuthPacket = {
97
+ type: PacketType.auth,
98
+ protocolLevel: 5 as const,
99
+ reasonCode: ReasonCode.continueAuthentication,
100
+ properties: {
101
+ authenticationMethod: "SCRAM-SHA-256",
102
+ // authenticationData missing
103
+ },
104
+ };
105
+
106
+ await assert.rejects(
107
+ async () => {
108
+ await handleAuth(ctx as never, packet);
109
+ },
110
+ /Auth method and\/or Auth data missing/,
111
+ "Should throw when missing required auth properties",
112
+ );
113
+ });
114
+
115
+ test("handleAuth transitions state and sends response packet on continueAuthentication success", async () => {
116
+ const ctx = createMockContext();
117
+ ctx.connectionState = ConnectionState.connected;
118
+
119
+ ctx.authHandler = () =>
120
+ Promise.resolve({
121
+ reasonCode: ReasonCode.continueAuthentication,
122
+ authData: new Uint8Array([4, 5, 6]),
123
+ reasonString: "Continue",
124
+ });
125
+
126
+ const packet: AuthPacket = {
127
+ type: PacketType.auth,
128
+ protocolLevel: 5 as const,
129
+ reasonCode: ReasonCode.continueAuthentication,
130
+ properties: {
131
+ authenticationMethod: "SCRAM-SHA-256",
132
+ authenticationData: new Uint8Array([1, 2, 3]),
133
+ },
134
+ };
135
+
136
+ await handleAuth(ctx as never, packet);
137
+
138
+ assert.deepStrictEqual(
139
+ ctx.connectionState,
140
+ ConnectionState.authenticating,
141
+ "Should transition connection state to authenticating",
142
+ );
143
+ assert.deepStrictEqual(
144
+ ctx.sentPackets.length,
145
+ 1,
146
+ "Should send a response auth packet",
147
+ );
148
+ assert.deepStrictEqual(ctx.sentPackets[0], {
149
+ type: PacketType.auth,
150
+ protocolLevel: 5,
151
+ reasonCode: ReasonCode.continueAuthentication,
152
+ properties: {
153
+ authenticationMethod: "SCRAM-SHA-256",
154
+ authenticationData: new Uint8Array([4, 5, 6]),
155
+ reasonString: "Continue",
156
+ },
157
+ });
158
+ });
159
+
160
+ test("handleAuth handles failure result from authHandler", async () => {
161
+ const ctx = createMockContext();
162
+ ctx.connectionState = ConnectionState.connecting;
163
+
164
+ ctx.authHandler = () =>
165
+ Promise.resolve({
166
+ reasonCode: ReasonCode.notAuthorized,
167
+ reasonString: "Not authorized to proceed",
168
+ });
169
+
170
+ const packet: AuthPacket = {
171
+ type: PacketType.auth,
172
+ protocolLevel: 5 as const,
173
+ reasonCode: ReasonCode.continueAuthentication,
174
+ properties: {
175
+ authenticationMethod: "SCRAM-SHA-256",
176
+ authenticationData: new Uint8Array([1, 2, 3]),
177
+ },
178
+ };
179
+
180
+ await handleAuth(ctx as never, packet);
181
+
182
+ assert.deepStrictEqual(
183
+ ctx.connectionState,
184
+ ConnectionState.disconnecting,
185
+ "Should set state to disconnecting on authHandler failure",
186
+ );
187
+
188
+ await assert.rejects(
189
+ ctx.unresolvedConnect.promise,
190
+ /Connect failed: Not authorized to proceed/,
191
+ "Should reject unresolvedConnect with the reasonString provided by authHandler",
192
+ );
193
+ });
@@ -0,0 +1,89 @@
1
+ import type { AuthenticatedResult, Context } from "../context.ts";
2
+ import { ConnectionState } from "../ConnectionState.ts";
3
+ import { PacketType, ReasonCode, ReasonCodeByNumber } from "../deps.ts";
4
+ import type { AuthPacket } from "../deps.ts";
5
+
6
+ /**
7
+ * Handle error
8
+ */
9
+
10
+ function handleError(ctx: Context, errMsg: string) {
11
+ if (ctx.connectionState === ConnectionState.connecting) {
12
+ const err = new Error(
13
+ `Connect failed: ${errMsg}`,
14
+ );
15
+ ctx.connectionState = ConnectionState.disconnecting;
16
+ ctx.pingTimer?.clear();
17
+ ctx.unresolvedConnect?.reject(err);
18
+ return;
19
+ }
20
+ throw new Error(errMsg);
21
+ }
22
+
23
+ /**
24
+ * Handle success
25
+ */
26
+
27
+ async function handleResult(
28
+ ctx: Context,
29
+ authMethod: string,
30
+ result: AuthenticatedResult,
31
+ ) {
32
+ await ctx.send({
33
+ type: PacketType.auth,
34
+ protocolLevel: 5,
35
+ reasonCode: result.reasonCode,
36
+ properties: result.authData
37
+ ? {
38
+ authenticationMethod: authMethod,
39
+ authenticationData: result.authData,
40
+ reasonString: result.reasonString,
41
+ }
42
+ : {},
43
+ });
44
+ }
45
+
46
+ /**
47
+ * Handles v5 Auth packet
48
+ * @param ctx - The connection context containing send method
49
+ * @returns Promise that resolves
50
+ */
51
+
52
+ export async function handleAuth(
53
+ ctx: Context,
54
+ authPacket: AuthPacket,
55
+ ): Promise<void> {
56
+ const reasonCode = authPacket.reasonCode;
57
+ if (reasonCode === ReasonCode.success) {
58
+ // we are connected again
59
+ ctx.connectionState = ConnectionState.connected;
60
+ return;
61
+ }
62
+
63
+ if (reasonCode !== ReasonCode.continueAuthentication) {
64
+ // something went wrong
65
+ handleError(ctx, ReasonCodeByNumber[reasonCode]);
66
+ return;
67
+ }
68
+
69
+ // we need to send something back
70
+ if (ctx.connectionState === ConnectionState.connected) {
71
+ // pauze auther activities
72
+ ctx.connectionState = ConnectionState.authenticating;
73
+ }
74
+
75
+ const authMethod = authPacket.properties?.authenticationMethod;
76
+ const authData = authPacket.properties?.authenticationData;
77
+ if (!(authMethod && authData)) {
78
+ throw new Error("Auth method and/or Auth data missing");
79
+ }
80
+ const result = await ctx.authHandler(
81
+ ctx,
82
+ authMethod,
83
+ authData,
84
+ );
85
+ if (result.reasonCode === ReasonCode.continueAuthentication) {
86
+ return handleResult(ctx, authMethod, result);
87
+ }
88
+ return handleError(ctx, result.reasonString || "Error during authentication");
89
+ }
@@ -0,0 +1,173 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ import { handleConnack } from "./handleConnack.ts";
4
+ import { ConnectionState } from "../ConnectionState.ts";
5
+ import { AuthenticationResult, MQTTLevel } from "../deps.ts";
6
+ import type { ConnackPacket } from "../deps.ts";
7
+ import { Deferred } from "../../utils/mod.ts";
8
+
9
+ function createMockContext() {
10
+ const sentPackets: unknown[] = [];
11
+ return {
12
+ connectionState: ConnectionState.connecting as string,
13
+ protocolLevel: 4 as const,
14
+ mqttConn: { codecOpts: { protocolLevel: MQTTLevel.unknown } },
15
+ pingTimer: { reset: () => {}, clear: () => {} },
16
+ unresolvedConnect: new Deferred<number>(),
17
+ store: {
18
+ pendingOutgoing: new Map(),
19
+ pendingIncoming: new Map(),
20
+ pendingAckOutgoing: new Map(),
21
+ async *pendingOutgoingPackets() {},
22
+ },
23
+ send: (packet: unknown) => {
24
+ sentPackets.push(packet);
25
+ },
26
+ sentPackets,
27
+ };
28
+ }
29
+
30
+ test("handleConnack sets connected state on success", async () => {
31
+ const ctx = createMockContext();
32
+ const packet = {
33
+ type: 2,
34
+ protocolLevel: 4 as const,
35
+ sessionPresent: false,
36
+ returnCode: AuthenticationResult.ok,
37
+ } as ConnackPacket;
38
+
39
+ await handleConnack(ctx as never, packet);
40
+
41
+ assert.deepStrictEqual(
42
+ ctx.connectionState,
43
+ ConnectionState.connected,
44
+ "Should be connected after successful CONNACK",
45
+ );
46
+ });
47
+
48
+ test("handleConnack resolves connect promise on success", async () => {
49
+ const ctx = createMockContext();
50
+ const packet = {
51
+ type: 2,
52
+ protocolLevel: 4 as const,
53
+ sessionPresent: false,
54
+ returnCode: AuthenticationResult.ok,
55
+ } as ConnackPacket;
56
+
57
+ await handleConnack(ctx as never, packet);
58
+
59
+ const result = await ctx.unresolvedConnect.promise;
60
+ assert.deepStrictEqual(result, 0, "Should resolve with success code 0");
61
+ });
62
+
63
+ test("handleConnack rejects on bad username/password", async () => {
64
+ const ctx = createMockContext();
65
+ const packet = {
66
+ type: 2,
67
+ protocolLevel: 4 as const,
68
+ sessionPresent: false,
69
+ returnCode: AuthenticationResult.badUsernameOrPassword,
70
+ } as ConnackPacket;
71
+
72
+ await handleConnack(ctx as never, packet);
73
+
74
+ assert.deepStrictEqual(
75
+ ctx.connectionState,
76
+ ConnectionState.disconnecting,
77
+ "Should be disconnecting on auth failure",
78
+ );
79
+
80
+ await assert.rejects(
81
+ ctx.unresolvedConnect.promise,
82
+ /Connect failed/,
83
+ "Should reject with connect failed error",
84
+ );
85
+ });
86
+
87
+ test("handleConnack rejects on not authorized", async () => {
88
+ const ctx = createMockContext();
89
+ const packet = {
90
+ type: 2,
91
+ protocolLevel: 4 as const,
92
+ sessionPresent: false,
93
+ returnCode: AuthenticationResult.notAuthorized,
94
+ } as ConnackPacket;
95
+
96
+ await handleConnack(ctx as never, packet);
97
+
98
+ assert.deepStrictEqual(
99
+ ctx.connectionState,
100
+ ConnectionState.disconnecting,
101
+ );
102
+
103
+ await assert.rejects(
104
+ ctx.unresolvedConnect.promise,
105
+ /Connect failed/,
106
+ );
107
+ });
108
+
109
+ test("handleConnack handles MQTT v5 reason codes", async () => {
110
+ const ctx = createMockContext();
111
+ (ctx as { protocolLevel: number }).protocolLevel = 5;
112
+ const packet = {
113
+ type: 2,
114
+ protocolLevel: 5 as const,
115
+ sessionPresent: false,
116
+ reasonCode: 0,
117
+ } as ConnackPacket;
118
+
119
+ await handleConnack(ctx as never, packet);
120
+
121
+ assert.deepStrictEqual(
122
+ ctx.connectionState,
123
+ ConnectionState.connected,
124
+ "Should be connected with v5 success reason code",
125
+ );
126
+ });
127
+
128
+ test("handleConnack resets ping timer on success", async () => {
129
+ let timerReset = false;
130
+ const ctx = createMockContext();
131
+ ctx.pingTimer = {
132
+ reset: () => {
133
+ timerReset = true;
134
+ },
135
+ clear: () => {},
136
+ };
137
+
138
+ const packet = {
139
+ type: 2,
140
+ protocolLevel: 4 as const,
141
+ sessionPresent: false,
142
+ returnCode: AuthenticationResult.ok,
143
+ } as ConnackPacket;
144
+
145
+ await handleConnack(ctx as never, packet);
146
+
147
+ assert.deepStrictEqual(timerReset, true, "Ping timer should be reset");
148
+ });
149
+
150
+ test("handleConnack clears ping timer on failure", async () => {
151
+ let timerCleared = false;
152
+ const ctx = createMockContext();
153
+ ctx.pingTimer = {
154
+ reset: () => {},
155
+ clear: () => {
156
+ timerCleared = true;
157
+ },
158
+ };
159
+
160
+ const packet = {
161
+ type: 2,
162
+ protocolLevel: 4 as const,
163
+ sessionPresent: false,
164
+ returnCode: AuthenticationResult.badUsernameOrPassword,
165
+ } as ConnackPacket;
166
+
167
+ await handleConnack(ctx as never, packet);
168
+ assert.deepStrictEqual(timerCleared, true, "Ping timer should be cleared");
169
+ await assert.rejects(
170
+ ctx.unresolvedConnect.promise,
171
+ /Connect failed/,
172
+ );
173
+ });
@@ -5,20 +5,30 @@ import type { ConnackPacket, TReasonCode } from "../deps.ts";
5
5
 
6
6
  /**
7
7
  * Handles the CONNACK packet received from the MQTT broker
8
- * @param packet - The CONNACK packet containing the connection acknowledgment
9
8
  * @param ctx - The connection context
9
+ * @param packet - The CONNACK packet containing the connection acknowledgment
10
10
  * @returns Promise that resolves when handling is complete
11
11
  */
12
- export async function handleConnack(packet: ConnackPacket, ctx: Context) {
13
- const result = packet.protocolLevel === 5
14
- ? packet.reasonCode
15
- : packet.returnCode;
12
+ export async function handleConnack(ctx: Context, packet: ConnackPacket) {
13
+ const isVersion5 = packet.protocolLevel === 5;
14
+ const result = isVersion5 ? packet.reasonCode : packet.returnCode;
16
15
  if (result === 0) {
17
16
  ctx.connectionState = ConnectionState.connected;
18
17
  if (ctx.mqttConn) {
19
18
  ctx.mqttConn.codecOpts.protocolLevel = ctx.protocolLevel;
20
19
  }
21
- ctx.pingTimer?.reset();
20
+
21
+ const serverKeepAlive = isVersion5
22
+ ? packet.properties?.serverKeepAlive
23
+ : undefined;
24
+
25
+ if (serverKeepAlive === 0) {
26
+ ctx.pingTimer?.clear(); // Server disabled keepalive
27
+ } else if (serverKeepAlive !== undefined) {
28
+ ctx.setPingTimer(serverKeepAlive); // Server set a new interval
29
+ } else {
30
+ ctx.pingTimer?.reset(); // Default fallback for V4 or V5 without override
31
+ }
22
32
  ctx.unresolvedConnect?.resolve(result);
23
33
  // start transmitting packets that were queued before
24
34
  for await (const packet of ctx.store.pendingOutgoingPackets()) {