@seriousme/opifex 1.9.3 → 1.10.1

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 (304) hide show
  1. package/README.md +37 -26
  2. package/bin/conformanceServer.ts +3 -2
  3. package/bin/demoServer.ts +3 -2
  4. package/bin/mqtt.ts +126 -117
  5. package/client/client.ts +35 -15
  6. package/client/context.ts +42 -22
  7. package/client/deps.ts +5 -0
  8. package/client/handlers/handleConnack.ts +17 -5
  9. package/client/handlers/handlePublish.ts +4 -1
  10. package/client/handlers/handlePubrec.ts +3 -1
  11. package/client/handlers/handlePubrel.ts +3 -1
  12. package/client/handlers/handleSuback.ts +3 -1
  13. package/client/mod.ts +8 -1
  14. package/client/store/memoryStore.ts +2 -1
  15. package/dev_utils/dummyConn.ts +17 -2
  16. package/dist/bin/conformanceServer.js +3 -2
  17. package/dist/bin/conformanceServer.js.map +1 -1
  18. package/dist/bin/demoServer.js +3 -2
  19. package/dist/bin/demoServer.js.map +1 -1
  20. package/dist/bin/mqtt.d.ts +29 -0
  21. package/dist/bin/mqtt.d.ts.map +1 -1
  22. package/dist/bin/mqtt.js +101 -96
  23. package/dist/bin/mqtt.js.map +1 -1
  24. package/dist/client/client.d.ts +7 -4
  25. package/dist/client/client.d.ts.map +1 -1
  26. package/dist/client/client.js +17 -9
  27. package/dist/client/client.js.map +1 -1
  28. package/dist/client/context.d.ts +3 -1
  29. package/dist/client/context.d.ts.map +1 -1
  30. package/dist/client/context.js +27 -13
  31. package/dist/client/context.js.map +1 -1
  32. package/dist/client/deps.d.ts +3 -2
  33. package/dist/client/deps.d.ts.map +1 -1
  34. package/dist/client/deps.js +2 -1
  35. package/dist/client/deps.js.map +1 -1
  36. package/dist/client/handlers/handleConnack.d.ts +1 -1
  37. package/dist/client/handlers/handleConnack.d.ts.map +1 -1
  38. package/dist/client/handlers/handleConnack.js +14 -5
  39. package/dist/client/handlers/handleConnack.js.map +1 -1
  40. package/dist/client/handlers/handlePublish.d.ts +1 -1
  41. package/dist/client/handlers/handlePublish.d.ts.map +1 -1
  42. package/dist/client/handlers/handlePublish.js +2 -0
  43. package/dist/client/handlers/handlePublish.js.map +1 -1
  44. package/dist/client/handlers/handlePubrec.d.ts +1 -1
  45. package/dist/client/handlers/handlePubrec.d.ts.map +1 -1
  46. package/dist/client/handlers/handlePubrec.js +1 -0
  47. package/dist/client/handlers/handlePubrec.js.map +1 -1
  48. package/dist/client/handlers/handlePubrel.d.ts +1 -1
  49. package/dist/client/handlers/handlePubrel.d.ts.map +1 -1
  50. package/dist/client/handlers/handlePubrel.js +1 -0
  51. package/dist/client/handlers/handlePubrel.js.map +1 -1
  52. package/dist/client/handlers/handleSuback.d.ts.map +1 -1
  53. package/dist/client/handlers/handleSuback.js +3 -1
  54. package/dist/client/handlers/handleSuback.js.map +1 -1
  55. package/dist/client/mod.d.ts +3 -1
  56. package/dist/client/mod.d.ts.map +1 -1
  57. package/dist/client/mod.js +2 -1
  58. package/dist/client/mod.js.map +1 -1
  59. package/dist/client/store/memoryStore.d.ts +1 -1
  60. package/dist/client/store/memoryStore.d.ts.map +1 -1
  61. package/dist/client/store/memoryStore.js.map +1 -1
  62. package/dist/mqttConn/mqttConn.d.ts +13 -8
  63. package/dist/mqttConn/mqttConn.d.ts.map +1 -1
  64. package/dist/mqttConn/mqttConn.js +27 -12
  65. package/dist/mqttConn/mqttConn.js.map +1 -1
  66. package/dist/mqttPacket/PacketType.d.ts +1 -0
  67. package/dist/mqttPacket/PacketType.d.ts.map +1 -1
  68. package/dist/mqttPacket/PacketType.js +1 -0
  69. package/dist/mqttPacket/PacketType.js.map +1 -1
  70. package/dist/mqttPacket/Properties.d.ts +157 -0
  71. package/dist/mqttPacket/Properties.d.ts.map +1 -0
  72. package/dist/mqttPacket/Properties.js +177 -0
  73. package/dist/mqttPacket/Properties.js.map +1 -0
  74. package/dist/mqttPacket/ReasonCode.d.ts +74 -0
  75. package/dist/mqttPacket/ReasonCode.d.ts.map +1 -0
  76. package/dist/mqttPacket/ReasonCode.js +230 -0
  77. package/dist/mqttPacket/ReasonCode.js.map +1 -0
  78. package/dist/mqttPacket/RetainHandling.d.ts +12 -0
  79. package/dist/mqttPacket/RetainHandling.d.ts.map +1 -0
  80. package/dist/mqttPacket/RetainHandling.js +12 -0
  81. package/dist/mqttPacket/RetainHandling.js.map +1 -0
  82. package/dist/mqttPacket/auth.d.ts +21 -0
  83. package/dist/mqttPacket/auth.d.ts.map +1 -0
  84. package/dist/mqttPacket/auth.js +34 -0
  85. package/dist/mqttPacket/auth.js.map +1 -0
  86. package/dist/mqttPacket/connack.d.ts +15 -7
  87. package/dist/mqttPacket/connack.d.ts.map +1 -1
  88. package/dist/mqttPacket/connack.js +43 -15
  89. package/dist/mqttPacket/connack.js.map +1 -1
  90. package/dist/mqttPacket/connect.d.ts +27 -8
  91. package/dist/mqttPacket/connect.d.ts.map +1 -1
  92. package/dist/mqttPacket/connect.js +106 -30
  93. package/dist/mqttPacket/connect.js.map +1 -1
  94. package/dist/mqttPacket/decoder.d.ts +42 -3
  95. package/dist/mqttPacket/decoder.d.ts.map +1 -1
  96. package/dist/mqttPacket/decoder.js +135 -4
  97. package/dist/mqttPacket/decoder.js.map +1 -1
  98. package/dist/mqttPacket/disconnect.d.ts +13 -7
  99. package/dist/mqttPacket/disconnect.d.ts.map +1 -1
  100. package/dist/mqttPacket/disconnect.js +45 -6
  101. package/dist/mqttPacket/disconnect.js.map +1 -1
  102. package/dist/mqttPacket/encoder.d.ts +57 -8
  103. package/dist/mqttPacket/encoder.d.ts.map +1 -1
  104. package/dist/mqttPacket/encoder.js +185 -13
  105. package/dist/mqttPacket/encoder.js.map +1 -1
  106. package/dist/mqttPacket/length.d.ts.map +1 -1
  107. package/dist/mqttPacket/length.js +3 -2
  108. package/dist/mqttPacket/length.js.map +1 -1
  109. package/dist/mqttPacket/mod.d.ts +56 -91
  110. package/dist/mqttPacket/mod.d.ts.map +1 -1
  111. package/dist/mqttPacket/mod.js +22 -22
  112. package/dist/mqttPacket/mod.js.map +1 -1
  113. package/dist/mqttPacket/pingreq.d.ts +4 -6
  114. package/dist/mqttPacket/pingreq.d.ts.map +1 -1
  115. package/dist/mqttPacket/pingreq.js +5 -4
  116. package/dist/mqttPacket/pingreq.js.map +1 -1
  117. package/dist/mqttPacket/pingres.d.ts +4 -6
  118. package/dist/mqttPacket/pingres.d.ts.map +1 -1
  119. package/dist/mqttPacket/pingres.js +7 -5
  120. package/dist/mqttPacket/pingres.js.map +1 -1
  121. package/dist/mqttPacket/protocolLevels.d.ts +11 -0
  122. package/dist/mqttPacket/protocolLevels.d.ts.map +1 -0
  123. package/dist/mqttPacket/protocolLevels.js +11 -0
  124. package/dist/mqttPacket/protocolLevels.js.map +1 -0
  125. package/dist/mqttPacket/pubblishAcks.d.ts +35 -0
  126. package/dist/mqttPacket/pubblishAcks.d.ts.map +1 -0
  127. package/dist/mqttPacket/pubblishAcks.js +56 -0
  128. package/dist/mqttPacket/pubblishAcks.js.map +1 -0
  129. package/dist/mqttPacket/publish.d.ts +19 -8
  130. package/dist/mqttPacket/publish.d.ts.map +1 -1
  131. package/dist/mqttPacket/publish.js +26 -7
  132. package/dist/mqttPacket/publish.js.map +1 -1
  133. package/dist/mqttPacket/suback.d.ts +14 -7
  134. package/dist/mqttPacket/suback.d.ts.map +1 -1
  135. package/dist/mqttPacket/suback.js +41 -20
  136. package/dist/mqttPacket/suback.js.map +1 -1
  137. package/dist/mqttPacket/subscribe.d.ts +24 -9
  138. package/dist/mqttPacket/subscribe.d.ts.map +1 -1
  139. package/dist/mqttPacket/subscribe.js +71 -15
  140. package/dist/mqttPacket/subscribe.js.map +1 -1
  141. package/dist/mqttPacket/types.d.ts +33 -0
  142. package/dist/mqttPacket/types.d.ts.map +1 -1
  143. package/dist/mqttPacket/unsuback.d.ts +14 -7
  144. package/dist/mqttPacket/unsuback.d.ts.map +1 -1
  145. package/dist/mqttPacket/unsuback.js +29 -6
  146. package/dist/mqttPacket/unsuback.js.map +1 -1
  147. package/dist/mqttPacket/unsubscribe.d.ts +14 -7
  148. package/dist/mqttPacket/unsubscribe.d.ts.map +1 -1
  149. package/dist/mqttPacket/unsubscribe.js +24 -8
  150. package/dist/mqttPacket/unsubscribe.js.map +1 -1
  151. package/dist/node/wrapNodeSocket.d.ts.map +1 -1
  152. package/dist/node/wrapNodeSocket.js.map +1 -1
  153. package/dist/persistence/deps.d.ts +1 -1
  154. package/dist/persistence/deps.d.ts.map +1 -1
  155. package/dist/persistence/deps.js +1 -1
  156. package/dist/persistence/deps.js.map +1 -1
  157. package/dist/server/context.d.ts +3 -1
  158. package/dist/server/context.d.ts.map +1 -1
  159. package/dist/server/context.js +8 -2
  160. package/dist/server/context.js.map +1 -1
  161. package/dist/server/deps.d.ts +2 -2
  162. package/dist/server/deps.d.ts.map +1 -1
  163. package/dist/server/deps.js +1 -1
  164. package/dist/server/deps.js.map +1 -1
  165. package/dist/server/handlers/handleConnect.d.ts +1 -1
  166. package/dist/server/handlers/handleConnect.d.ts.map +1 -1
  167. package/dist/server/handlers/handleConnect.js +9 -1
  168. package/dist/server/handlers/handleConnect.js.map +1 -1
  169. package/dist/server/handlers/handlePacket.d.ts +1 -1
  170. package/dist/server/handlers/handlePacket.d.ts.map +1 -1
  171. package/dist/server/handlers/handlePacket.js +1 -1
  172. package/dist/server/handlers/handlePacket.js.map +1 -1
  173. package/dist/server/handlers/handlePingreq.d.ts.map +1 -1
  174. package/dist/server/handlers/handlePingreq.js +1 -0
  175. package/dist/server/handlers/handlePingreq.js.map +1 -1
  176. package/dist/server/handlers/handlePublish.d.ts +2 -2
  177. package/dist/server/handlers/handlePublish.d.ts.map +1 -1
  178. package/dist/server/handlers/handlePublish.js +2 -0
  179. package/dist/server/handlers/handlePublish.js.map +1 -1
  180. package/dist/server/handlers/handlePubrec.d.ts +1 -1
  181. package/dist/server/handlers/handlePubrec.d.ts.map +1 -1
  182. package/dist/server/handlers/handlePubrec.js +1 -0
  183. package/dist/server/handlers/handlePubrec.js.map +1 -1
  184. package/dist/server/handlers/handlePubrel.d.ts +1 -1
  185. package/dist/server/handlers/handlePubrel.d.ts.map +1 -1
  186. package/dist/server/handlers/handlePubrel.js +1 -0
  187. package/dist/server/handlers/handlePubrel.js.map +1 -1
  188. package/dist/server/handlers/handleSubscribe.d.ts +1 -1
  189. package/dist/server/handlers/handleSubscribe.d.ts.map +1 -1
  190. package/dist/server/handlers/handleSubscribe.js +2 -1
  191. package/dist/server/handlers/handleSubscribe.js.map +1 -1
  192. package/dist/server/handlers/handleUnsubscribe.d.ts +1 -1
  193. package/dist/server/handlers/handleUnsubscribe.d.ts.map +1 -1
  194. package/dist/server/handlers/handleUnsubscribe.js +1 -0
  195. package/dist/server/handlers/handleUnsubscribe.js.map +1 -1
  196. package/dist/server/server.d.ts +2 -2
  197. package/dist/server/server.d.ts.map +1 -1
  198. package/dist/server/server.js +5 -3
  199. package/dist/server/server.js.map +1 -1
  200. package/dist/socket/socket.d.ts.map +1 -1
  201. package/dist/socket/socket.js +6 -1
  202. package/dist/socket/socket.js.map +1 -1
  203. package/dist/utils/assert.d.ts +0 -3
  204. package/dist/utils/assert.d.ts.map +1 -1
  205. package/dist/utils/assert.js +0 -7
  206. package/dist/utils/assert.js.map +1 -1
  207. package/dist/utils/mod.d.ts +0 -3
  208. package/dist/utils/mod.d.ts.map +1 -1
  209. package/dist/utils/mod.js +0 -2
  210. package/dist/utils/mod.js.map +1 -1
  211. package/mqttConn/mqttConn.test.ts +27 -12
  212. package/mqttConn/mqttConn.ts +45 -14
  213. package/mqttPacket/PacketType.ts +1 -0
  214. package/mqttPacket/Properties.ts +276 -0
  215. package/mqttPacket/ReasonCode.test.ts +22 -0
  216. package/mqttPacket/ReasonCode.ts +256 -0
  217. package/mqttPacket/RetainHandling.ts +11 -0
  218. package/mqttPacket/auth.test.ts +112 -0
  219. package/mqttPacket/auth.ts +72 -0
  220. package/mqttPacket/connack.test.ts +84 -64
  221. package/mqttPacket/connack.ts +84 -20
  222. package/mqttPacket/connect.test.ts +497 -18
  223. package/mqttPacket/connect.ts +167 -36
  224. package/mqttPacket/decoder.test.ts +33 -16
  225. package/mqttPacket/decoder.ts +173 -5
  226. package/mqttPacket/disconnect.test.ts +97 -18
  227. package/mqttPacket/disconnect.ts +82 -10
  228. package/mqttPacket/encoder.test.ts +32 -8
  229. package/mqttPacket/encoder.ts +236 -11
  230. package/mqttPacket/length.ts +3 -2
  231. package/mqttPacket/mod.ts +75 -32
  232. package/mqttPacket/pingreq.test.ts +52 -4
  233. package/mqttPacket/pingreq.ts +20 -7
  234. package/mqttPacket/pingres.test.ts +52 -4
  235. package/mqttPacket/pingres.ts +22 -8
  236. package/mqttPacket/properties.test.ts +193 -0
  237. package/mqttPacket/protocolLevels.ts +13 -0
  238. package/mqttPacket/pubblishAcks.ts +117 -0
  239. package/mqttPacket/publish.test.ts +212 -133
  240. package/mqttPacket/publish.ts +69 -14
  241. package/mqttPacket/publishAcks.test.ts +128 -0
  242. package/mqttPacket/suback.test.ts +71 -27
  243. package/mqttPacket/suback.ts +78 -26
  244. package/mqttPacket/subscribe.test.ts +132 -43
  245. package/mqttPacket/subscribe.ts +125 -22
  246. package/mqttPacket/types.ts +40 -0
  247. package/mqttPacket/unsuback.test.ts +80 -30
  248. package/mqttPacket/unsuback.ts +65 -10
  249. package/mqttPacket/unsubscribe.test.ts +59 -34
  250. package/mqttPacket/unsubscribe.ts +61 -14
  251. package/node/wrapNodeSocket.ts +2 -1
  252. package/package.json +2 -2
  253. package/persistence/deps.ts +1 -1
  254. package/persistence/memory/memoryPersistence.test.ts +5 -1
  255. package/server/context.ts +23 -10
  256. package/server/deps.ts +2 -0
  257. package/server/handlers/handleConnect.ts +12 -9
  258. package/server/handlers/handlePacket.ts +10 -11
  259. package/server/handlers/handlePingreq.ts +1 -0
  260. package/server/handlers/handlePublish.ts +6 -2
  261. package/server/handlers/handlePubrec.ts +3 -1
  262. package/server/handlers/handlePubrel.ts +3 -1
  263. package/server/handlers/handleSubscribe.ts +3 -6
  264. package/server/handlers/handleUnsubscribe.ts +3 -1
  265. package/server/server.ts +8 -12
  266. package/server/test/handleConnect.test.ts +2 -1
  267. package/server/test/test-handlers.ts +2 -1
  268. package/socket/socket.ts +5 -1
  269. package/utils/assert.ts +0 -18
  270. package/utils/mod.ts +0 -3
  271. package/dist/mqttPacket/puback.d.ts +0 -16
  272. package/dist/mqttPacket/puback.d.ts.map +0 -1
  273. package/dist/mqttPacket/puback.js +0 -21
  274. package/dist/mqttPacket/puback.js.map +0 -1
  275. package/dist/mqttPacket/pubcomp.d.ts +0 -17
  276. package/dist/mqttPacket/pubcomp.d.ts.map +0 -1
  277. package/dist/mqttPacket/pubcomp.js +0 -21
  278. package/dist/mqttPacket/pubcomp.js.map +0 -1
  279. package/dist/mqttPacket/pubrec.d.ts +0 -17
  280. package/dist/mqttPacket/pubrec.d.ts.map +0 -1
  281. package/dist/mqttPacket/pubrec.js +0 -21
  282. package/dist/mqttPacket/pubrec.js.map +0 -1
  283. package/dist/mqttPacket/pubrel.d.ts +0 -17
  284. package/dist/mqttPacket/pubrel.d.ts.map +0 -1
  285. package/dist/mqttPacket/pubrel.js +0 -21
  286. package/dist/mqttPacket/pubrel.js.map +0 -1
  287. package/dist/utils/args.d.ts +0 -28
  288. package/dist/utils/args.d.ts.map +0 -1
  289. package/dist/utils/args.js +0 -76
  290. package/dist/utils/args.js.map +0 -1
  291. package/dist/utils/platform.d.ts +0 -5
  292. package/dist/utils/platform.d.ts.map +0 -1
  293. package/dist/utils/platform.js +0 -8
  294. package/dist/utils/platform.js.map +0 -1
  295. package/mqttPacket/puback.test.ts +0 -55
  296. package/mqttPacket/puback.ts +0 -34
  297. package/mqttPacket/pubcomp.test.ts +0 -55
  298. package/mqttPacket/pubcomp.ts +0 -35
  299. package/mqttPacket/pubrec.test.ts +0 -55
  300. package/mqttPacket/pubrec.ts +0 -35
  301. package/mqttPacket/pubrel.test.ts +0 -55
  302. package/mqttPacket/pubrel.ts +0 -35
  303. package/utils/args.ts +0 -103
  304. package/utils/platform.ts +0 -8
@@ -0,0 +1,128 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+
4
+ import { decode, encode, MQTTLevel, PacketType, ReasonCode } from "./mod.ts";
5
+ import type { CodecOpts, TPacketType, TReasonCode } from "./mod.ts";
6
+
7
+ const codecOptsV4: CodecOpts = {
8
+ protocolLevel: MQTTLevel.v4,
9
+ maxIncomingPacketSize: 0xffff,
10
+ maxOutgoingPacketSize: 0xffff,
11
+ };
12
+
13
+ const codecOptsV5: CodecOpts = {
14
+ protocolLevel: MQTTLevel.v5,
15
+ maxIncomingPacketSize: 0xffff,
16
+ maxOutgoingPacketSize: 0xffff,
17
+ };
18
+
19
+ const packetTypesToTest = [
20
+ [PacketType.puback, "Puback", ReasonCode.packetIdentifierInUse],
21
+ [PacketType.pubrec, "Pubrec", ReasonCode.packetIdentifierInUse],
22
+ [PacketType.pubrel, "Pubrel", ReasonCode.packetIdentifierNotFound],
23
+ [PacketType.pubcomp, "Pubcomp", ReasonCode.packetIdentifierNotFound],
24
+ ];
25
+ for (const item of packetTypesToTest) {
26
+ const [ackType, label, reasonCode] = item as [
27
+ TPacketType,
28
+ string,
29
+ TReasonCode,
30
+ ];
31
+ const ackTypeByte = (ackType << 4) + (ackType === PacketType.pubrel ? 2 : 0);
32
+ test(`encode/decode ${label} v4`, () => {
33
+ const packet = {
34
+ type: ackType,
35
+ protocolLevel: MQTTLevel.v4,
36
+ id: 1337,
37
+ };
38
+ const encoded = encode(packet, codecOptsV4);
39
+ assert.deepStrictEqual(
40
+ encoded,
41
+ Uint8Array.from([
42
+ // fixedHeader
43
+ ackTypeByte, // packetType + flags
44
+ 2, // remainingLength
45
+ // variableHeader
46
+ 5, // id MSB
47
+ 57, // id LSB
48
+ ]),
49
+ );
50
+ const decoded = decode(encoded, codecOptsV4);
51
+ assert.deepStrictEqual(decoded, packet);
52
+ });
53
+
54
+ test(`encode/decode ${label} v5`, () => {
55
+ const packet = {
56
+ type: ackType,
57
+ protocolLevel: MQTTLevel.v5,
58
+ id: 1337,
59
+ reasonCode,
60
+ properties: { reasonString: "test" },
61
+ };
62
+ const encoded = encode(packet, codecOptsV5);
63
+ assert.deepStrictEqual(
64
+ encoded,
65
+ Uint8Array.from([
66
+ // fixedHeader
67
+ ackTypeByte, // packetType + flags
68
+ 11, // remainingLength
69
+ // variableHeader
70
+ 5, // id MSB
71
+ 57, // id LSB
72
+ reasonCode, // reasonCode
73
+ // properties
74
+ 7, // propertyLength
75
+ 31, // reasonString
76
+ 0, // string length MSB
77
+ 4, // string length LSB
78
+ 116, //'t'
79
+ 101, //'e'
80
+ 115, //'s'
81
+ 116, //'t'
82
+ ]),
83
+ );
84
+ const decoded = decode(encoded, codecOptsV5);
85
+ assert.deepStrictEqual(decoded, packet);
86
+ });
87
+
88
+ test(`encode/decode short ${label} v5`, () => {
89
+ const packet = {
90
+ type: ackType,
91
+ protocolLevel: MQTTLevel.v5,
92
+ id: 1337,
93
+ reasonCode: 0,
94
+ };
95
+ const encoded = encode(packet, codecOptsV5);
96
+ assert.deepStrictEqual(
97
+ encoded,
98
+ Uint8Array.from([
99
+ // fixedHeader
100
+ ackTypeByte, // packetType + flags
101
+ 2, // remainingLength
102
+ // variableHeader
103
+ 5, // id MSB
104
+ 57, // id LSB
105
+ ]),
106
+ );
107
+ const decoded = decode(encoded, codecOptsV5);
108
+ assert.deepStrictEqual(decoded, packet);
109
+ });
110
+
111
+ test("decode short puback packets", () => {
112
+ assert.throws(
113
+ () => decode(Uint8Array.from([ackTypeByte]), codecOptsV4),
114
+ Error,
115
+ "decoding failed",
116
+ );
117
+ assert.throws(
118
+ () => decode(Uint8Array.from([ackTypeByte, 3, 0, 0, 0]), codecOptsV4),
119
+ Error,
120
+ "too long",
121
+ );
122
+ assert.throws(
123
+ () => decode(Uint8Array.from([ackTypeByte, 2, 5]), codecOptsV5),
124
+ Error,
125
+ "decoding failed",
126
+ );
127
+ });
128
+ }
@@ -1,16 +1,30 @@
1
- import { PacketType } from "./PacketType.ts";
2
1
  import assert from "node:assert/strict";
3
2
  import { test } from "node:test";
3
+ import { decode, encode, MQTTLevel, PacketType, ReasonCode } from "./mod.ts";
4
+ import type { CodecOpts } from "./mod.ts";
4
5
 
5
- import { decode, encode } from "./mod.ts";
6
+ const codecOptsV4: CodecOpts = {
7
+ protocolLevel: MQTTLevel.v4,
8
+ maxIncomingPacketSize: 0xffff,
9
+ maxOutgoingPacketSize: 0xffff,
10
+ };
6
11
 
7
- test("encode Suback", () => {
12
+ const codecOptsV5: CodecOpts = {
13
+ protocolLevel: MQTTLevel.v5,
14
+ maxIncomingPacketSize: 0xffff,
15
+ maxOutgoingPacketSize: 0xffff,
16
+ };
17
+
18
+ test("encode/decode Suback v4", () => {
19
+ const packet = {
20
+ type: PacketType.suback,
21
+ protocolLevel: MQTTLevel.v4,
22
+ id: 1,
23
+ returnCodes: [0, 1],
24
+ };
25
+ const encoded = encode(packet, codecOptsV4);
8
26
  assert.deepStrictEqual(
9
- encode({
10
- type: PacketType.suback,
11
- id: 1,
12
- returnCodes: [0, 1],
13
- }),
27
+ encoded,
14
28
  Uint8Array.from([
15
29
  // fixedHeader
16
30
  0x90, // packetType + flags
@@ -23,27 +37,57 @@ test("encode Suback", () => {
23
37
  1,
24
38
  ]),
25
39
  );
40
+ const decoded = decode(encoded, codecOptsV4);
41
+ assert.deepStrictEqual(decoded, packet);
26
42
  });
27
43
 
28
- test("decode Suback", () => {
29
- assert.deepStrictEqual(
30
- decode(
31
- Uint8Array.from([
32
- // fixedHeader
33
- 0x90, // packetType + flags
34
- 4, // remainingLength
35
- // variableHeader
36
- 0, // id MSB
37
- 1, // id LSB
38
- // payload
39
- 0,
40
- 1,
41
- ]),
42
- ),
43
- {
44
- type: PacketType.suback,
45
- id: 1,
46
- returnCodes: [0, 1],
44
+ test("encode/decode Suback v5", () => {
45
+ const packet = {
46
+ type: PacketType.suback,
47
+ protocolLevel: MQTTLevel.v5,
48
+ id: 1,
49
+ reasonCodes: [ReasonCode.grantedQos0, ReasonCode.grantedQos1],
50
+ properties: {
51
+ reasonString: "reason",
52
+ userProperty: [["test", "test"]],
47
53
  },
54
+ };
55
+ const encoded = encode(packet, codecOptsV5);
56
+ assert.deepStrictEqual(
57
+ encoded,
58
+ Uint8Array.from([
59
+ // fixedHeader
60
+ 144, // packetType + flags
61
+ 27, // remaining length
62
+ 0, // id MSB
63
+ 1, // id LSB
64
+ 22, // propertysize
65
+ 31, // reason string
66
+ 0, // string length MSB
67
+ 6, // string length LSB
68
+ 114, // r
69
+ 101, // e
70
+ 97, // a
71
+ 115, // s
72
+ 111, // o
73
+ 110, // n
74
+ 38, // user property
75
+ 0, // string length MSB
76
+ 4, // string length LSB
77
+ 116, // t
78
+ 101, // e
79
+ 115, // s
80
+ 116, // t
81
+ 0, // string length MSB
82
+ 4, // string length LSB
83
+ 116, // t
84
+ 101, // e
85
+ 115, // s
86
+ 116, // t
87
+ 0, // return code
88
+ 1, // return code
89
+ ]),
48
90
  );
91
+ const decoded = decode(encoded, codecOptsV5);
92
+ assert.deepStrictEqual(decoded, packet);
49
93
  });
@@ -1,48 +1,100 @@
1
- import type { PacketId, ReturnCodes, TPacketType } from "./types.ts";
1
+ import type {
2
+ CodecOpts,
3
+ PacketId,
4
+ ProtocolLevelNoV5,
5
+ ReturnCodes,
6
+ TPacketType,
7
+ TReasonCode,
8
+ } from "./types.ts";
9
+ import type { SubackProperties } from "./Properties.ts";
2
10
  import { PacketType } from "./PacketType.ts";
3
11
  import { Encoder } from "./encoder.ts";
4
- import { Decoder } from "./decoder.ts";
12
+ import { Decoder, DecoderError } from "./decoder.ts";
13
+ const validReturnCodes = [0x00, 0x01, 0x02, 0x80];
5
14
 
6
15
  /**
7
16
  * SubackPacket is sent by the server to the client to confirm receipt and
8
17
  * processing of a SubscribePacket.
9
18
  */
10
- export type SubackPacket = {
19
+ export type SubackPacketV4 = {
11
20
  type: TPacketType;
21
+ protocolLevel: ProtocolLevelNoV5;
12
22
  id: PacketId;
13
23
  returnCodes: ReturnCodes;
14
24
  };
15
25
 
26
+ export type SubackPacketV5 = {
27
+ type: TPacketType;
28
+ protocolLevel: 5;
29
+ id: PacketId;
30
+ properties: SubackProperties;
31
+ reasonCodes: Array<TReasonCode>;
32
+ };
33
+
34
+ export type SubackPacket = SubackPacketV4 | SubackPacketV5;
35
+
16
36
  export const suback: {
17
- encode(packet: SubackPacket): { flags: number; bytes: number[] };
18
- decode(buffer: Uint8Array): SubackPacket;
37
+ encode(packet: SubackPacket, _codecOpts: CodecOpts): Uint8Array;
38
+ decode(
39
+ buffer: Uint8Array,
40
+ flags: number,
41
+ codecOpts: CodecOpts,
42
+ packetType: TPacketType,
43
+ ): SubackPacket;
19
44
  } = {
20
- encode(packet: SubackPacket): { flags: number; bytes: number[] } {
45
+ encode(packet: SubackPacket, codecOpts: CodecOpts): Uint8Array {
21
46
  const flags = 0;
22
- const encoder = new Encoder();
47
+ const encoder = new Encoder(packet.type);
23
48
  encoder.setInt16(packet.id);
24
- encoder.setRemainder(packet.returnCodes);
25
-
26
- return {
27
- flags,
28
- bytes: encoder.done(),
29
- };
49
+ if (packet.protocolLevel !== 5) {
50
+ for (const code of packet.returnCodes) {
51
+ if (!validReturnCodes.includes(code)) {
52
+ throw new Error("Invalid return code");
53
+ }
54
+ }
55
+ encoder.setRemainder(packet.returnCodes);
56
+ return encoder.done(flags);
57
+ }
58
+ encoder.setProperties(
59
+ packet.properties || {},
60
+ packet.type,
61
+ codecOpts.maxOutgoingPacketSize,
62
+ );
63
+ for (const code of packet.reasonCodes) {
64
+ encoder.setReasonCode(code);
65
+ }
66
+ return encoder.done(flags);
30
67
  },
31
68
 
32
- decode(buffer: Uint8Array): SubackPacket {
33
- const decoder = new Decoder(buffer);
34
- const id = decoder.getInt16();
35
- const payload = decoder.getRemainder();
36
- const returnCodes = [];
69
+ decode(
70
+ buffer: Uint8Array,
71
+ _flags: number,
72
+ codecOpts: CodecOpts,
73
+ packetType: TPacketType,
74
+ ): SubackPacket {
75
+ const packet = {} as SubackPacket;
76
+ const decoder = new Decoder(packetType, buffer);
77
+ packet.type = PacketType.suback;
78
+ packet.id = decoder.getInt16();
79
+ packet.protocolLevel = codecOpts.protocolLevel;
37
80
 
38
- for (const code of payload) {
39
- returnCodes.push(code);
81
+ if (packet.protocolLevel !== 5) {
82
+ const payload = decoder.getRemainder();
83
+ packet.returnCodes = [];
84
+ for (const code of payload) {
85
+ if (!validReturnCodes.includes(code)) {
86
+ throw new DecoderError("Invalid return code");
87
+ }
88
+ packet.returnCodes.push(code);
89
+ }
90
+ return packet;
40
91
  }
41
-
42
- return {
43
- type: PacketType.suback,
44
- id,
45
- returnCodes,
46
- };
92
+ packet.properties = decoder.getProperties(PacketType.suback);
93
+ packet.reasonCodes = [];
94
+ while (!decoder.atEnd()) {
95
+ const code = decoder.getReasonCode();
96
+ packet.reasonCodes.push(code);
97
+ }
98
+ return packet;
47
99
  },
48
100
  };
@@ -2,18 +2,34 @@ import { PacketType } from "./PacketType.ts";
2
2
  import assert from "node:assert/strict";
3
3
  import { test } from "node:test";
4
4
 
5
- import { decode, encode } from "./mod.ts";
5
+ import { decode, encode, MQTTLevel, RetainHandling } from "./mod.ts";
6
+ import type { CodecOpts } from "./mod.ts";
6
7
 
7
- test("encode Subscribe", () => {
8
+ const codecOptsV4: CodecOpts = {
9
+ protocolLevel: MQTTLevel.v4,
10
+ maxIncomingPacketSize: 0xffff,
11
+ maxOutgoingPacketSize: 0xffff,
12
+ };
13
+
14
+ const codecOptsV5: CodecOpts = {
15
+ protocolLevel: MQTTLevel.v5,
16
+ maxIncomingPacketSize: 0xffff,
17
+ maxOutgoingPacketSize: 0xffff,
18
+ };
19
+
20
+ test("encode/decode Subscribe v4", () => {
21
+ const packet = {
22
+ type: PacketType.subscribe,
23
+ protocolLevel: MQTTLevel.v4,
24
+ id: 1,
25
+ subscriptions: [
26
+ { topicFilter: "a/b", qos: 0 },
27
+ { topicFilter: "c/d", qos: 1 },
28
+ ],
29
+ };
30
+ const encoded = encode(packet, codecOptsV4);
8
31
  assert.deepStrictEqual(
9
- encode({
10
- type: PacketType.subscribe,
11
- id: 1,
12
- subscriptions: [
13
- { topicFilter: "a/b", qos: 0 },
14
- { topicFilter: "c/d", qos: 1 },
15
- ],
16
- }),
32
+ encoded,
17
33
  Uint8Array.from([
18
34
  // fixedHeader
19
35
  0x82, // packetType + flags
@@ -36,45 +52,75 @@ test("encode Subscribe", () => {
36
52
  1, // qos
37
53
  ]),
38
54
  );
55
+ const decoded = decode(encoded, codecOptsV4);
56
+ assert.deepStrictEqual(decoded, packet);
39
57
  });
40
58
 
41
- test("decode Subscribe", () => {
42
- assert.deepStrictEqual(
43
- decode(
44
- Uint8Array.from([
45
- // fixedHeader
46
- 0x82, // packetType + flags
47
- 14, // remainingLength
48
- // variableHeader
49
- 0, // id MSB
50
- 1, // id LSB
51
- // payload
52
- 0, // topic filter length MSB
53
- 3, // topic filter length LSB
54
- 97, // 'a'
55
- 47, // '/'
56
- 98, // 'b'
57
- 0, // qos
58
- 0, // topic filter length MSB
59
- 3, // topic filter length LSB
60
- 99, // 'c'
61
- 47, // '/'
62
- 100, // 'd'
63
- 1, // qos
64
- ]),
65
- ),
66
- {
67
- type: PacketType.subscribe,
68
- id: 1,
69
- subscriptions: [
70
- { topicFilter: "a/b", qos: 0 },
71
- { topicFilter: "c/d", qos: 1 },
72
- ],
59
+ test("encode/decode Subscribe v5", () => {
60
+ const packet = {
61
+ type: PacketType.subscribe,
62
+ protocolLevel: MQTTLevel.v5,
63
+ id: 1,
64
+ subscriptions: [
65
+ { topicFilter: "a/b", qos: 0 },
66
+ {
67
+ topicFilter: "c/d",
68
+ qos: 2,
69
+ noLocal: true,
70
+ retainAsPublished: true,
71
+ retainHandling: RetainHandling.noRetain,
72
+ },
73
+ ],
74
+ properties: {
75
+ subscriptionIdentifier: 123,
73
76
  },
77
+ };
78
+ const encoded = encode(packet, codecOptsV5);
79
+ assert.deepStrictEqual(
80
+ encoded,
81
+ Uint8Array.from([
82
+ // fixedHeader
83
+ 0x82, // packetType + flags
84
+ 17, // remainingLength
85
+ // variableHeader
86
+ 0, // id MSB
87
+ 1, // id LSB
88
+ 2, // propertyLength
89
+ 11, // subscription identifier
90
+ 123, // 123
91
+ // payload
92
+ 0, // topic filter length MSB
93
+ 3, // topic filter length LSB
94
+ 97, // 'a'
95
+ 47, // '/'
96
+ 98, // 'b'
97
+ 0, // options
98
+ 0, // topic filter length MSB
99
+ 3, // topic filter length LSB
100
+ 99, // 'c'
101
+ 47, // '/'
102
+ 100, // 'd'
103
+ 46, // options 0b101110
104
+ ]),
74
105
  );
106
+ const decoded = decode(encoded, codecOptsV5);
107
+ // add the defaults for comparison
108
+ const packetWithDefaults = {
109
+ ...packet,
110
+ subscriptions: [
111
+ {
112
+ ...packet.subscriptions[0],
113
+ noLocal: false,
114
+ retainAsPublished: false,
115
+ retainHandling: RetainHandling.sendRetained,
116
+ },
117
+ { ...packet.subscriptions[1] },
118
+ ],
119
+ };
120
+ assert.deepStrictEqual(decoded, packetWithDefaults);
75
121
  });
76
122
 
77
- test("decode Subscribe missing bit 1 flag", () => {
123
+ test("decode Subscribe v4 missing bit 1 flag", () => {
78
124
  assert.throws(
79
125
  () =>
80
126
  decode(
@@ -99,6 +145,7 @@ test("decode Subscribe missing bit 1 flag", () => {
99
145
  100, // 'd'
100
146
  1, // qos
101
147
  ]),
148
+ codecOptsV4,
102
149
  ),
103
150
  Error,
104
151
  "Invalid header",
@@ -129,6 +176,7 @@ test("decode Subscribe packet too short", () => {
129
176
  47, // '/'
130
177
  1, // qos
131
178
  ]),
179
+ codecOptsV4,
132
180
  ),
133
181
  Error,
134
182
  "Invalid qos",
@@ -154,6 +202,7 @@ test("decode Subscribe packet too short", () => {
154
202
  3, // topic filter length LSB
155
203
  99, // 'c'
156
204
  ]),
205
+ codecOptsV4,
157
206
  ),
158
207
  Error,
159
208
  "too short",
@@ -169,6 +218,7 @@ test("decode Subscribe packet too short", () => {
169
218
  0, // id MSB
170
219
  1, // id LSB
171
220
  ]),
221
+ codecOptsV4,
172
222
  ),
173
223
  Error,
174
224
  "too short",
@@ -199,6 +249,7 @@ test("decode Subscribe packet invalid packet id with QoS > 0", () => {
199
249
  47, // '/'
200
250
  1, // qos
201
251
  ]),
252
+ codecOptsV4,
202
253
  ),
203
254
  Error,
204
255
  "Invalid packet identifier",
@@ -226,8 +277,46 @@ test("decode Subscribe packet invalid packet id with QoS > 0", () => {
226
277
  47, // '/'
227
278
  2, // qos
228
279
  ]),
280
+ codecOptsV4,
229
281
  ),
230
282
  Error,
231
283
  "Invalid packet identifier",
232
284
  );
233
285
  });
286
+
287
+ test("decode Subscribe v5 with invalid subscription options", () => {
288
+ for (
289
+ const item of [
290
+ [0b10000000, /Invalid subscription options/], // bit 7 must be 0
291
+ [0b1000000, /Invalid subscription options/], // bit 6 must be 0
292
+ [0b110000, /Invalid retain handling/], // retain handling can't be 3
293
+ [0b100011, /Invalid qos/], // qos can't be 3
294
+ ]
295
+ ) {
296
+ const [options, err] = item as [number, RegExp];
297
+ assert.throws(
298
+ () =>
299
+ decode(
300
+ Uint8Array.from([
301
+ // fixedHeader
302
+ 0x82, // packetType + flags
303
+ 9, // remainingLength
304
+ // variableHeader
305
+ 0, // id MSB
306
+ 1, // id LSB
307
+ 0, // propertyLength
308
+ // payload
309
+ 0, // topic filter length MSB
310
+ 3, // topic filter length LSB
311
+ 97, // 'a'
312
+ 47, // '/'
313
+ 98, // 'b'
314
+ options, // options
315
+ ]),
316
+ codecOptsV5,
317
+ ),
318
+ err,
319
+ "Invalid subscription options",
320
+ );
321
+ }
322
+ });