@seriousme/opifex 1.9.4 → 1.11.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 +37 -26
- package/bin/conformanceServer.ts +3 -2
- package/bin/demoServer.ts +3 -2
- package/bin/mqtt.ts +127 -118
- package/client/client.ts +61 -21
- package/client/context.ts +71 -30
- package/client/deps.ts +5 -0
- package/client/handlers/handleConnack.ts +17 -5
- package/client/handlers/handlePublish.ts +4 -1
- package/client/handlers/handlePubrec.ts +3 -1
- package/client/handlers/handlePubrel.ts +3 -1
- package/client/handlers/handleSuback.ts +3 -1
- package/client/mod.ts +8 -1
- package/client/store/memoryStore.ts +2 -1
- package/deno/tcpClient.ts +1 -1
- package/dev_utils/dummyConn.ts +17 -2
- package/dist/bin/conformanceServer.js +3 -2
- package/dist/bin/conformanceServer.js.map +1 -1
- package/dist/bin/demoServer.js +3 -2
- package/dist/bin/demoServer.js.map +1 -1
- package/dist/bin/mqtt.d.ts +29 -0
- package/dist/bin/mqtt.d.ts.map +1 -1
- package/dist/bin/mqtt.js +102 -97
- package/dist/bin/mqtt.js.map +1 -1
- package/dist/client/client.d.ts +16 -5
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +36 -15
- package/dist/client/client.js.map +1 -1
- package/dist/client/context.d.ts +8 -3
- package/dist/client/context.d.ts.map +1 -1
- package/dist/client/context.js +51 -21
- package/dist/client/context.js.map +1 -1
- package/dist/client/deps.d.ts +3 -2
- package/dist/client/deps.d.ts.map +1 -1
- package/dist/client/deps.js +2 -1
- package/dist/client/deps.js.map +1 -1
- package/dist/client/handlers/handleConnack.d.ts +1 -1
- package/dist/client/handlers/handleConnack.d.ts.map +1 -1
- package/dist/client/handlers/handleConnack.js +14 -5
- package/dist/client/handlers/handleConnack.js.map +1 -1
- package/dist/client/handlers/handlePublish.d.ts +1 -1
- package/dist/client/handlers/handlePublish.d.ts.map +1 -1
- package/dist/client/handlers/handlePublish.js +2 -0
- package/dist/client/handlers/handlePublish.js.map +1 -1
- package/dist/client/handlers/handlePubrec.d.ts +1 -1
- package/dist/client/handlers/handlePubrec.d.ts.map +1 -1
- package/dist/client/handlers/handlePubrec.js +1 -0
- package/dist/client/handlers/handlePubrec.js.map +1 -1
- package/dist/client/handlers/handlePubrel.d.ts +1 -1
- package/dist/client/handlers/handlePubrel.d.ts.map +1 -1
- package/dist/client/handlers/handlePubrel.js +1 -0
- package/dist/client/handlers/handlePubrel.js.map +1 -1
- package/dist/client/handlers/handleSuback.d.ts.map +1 -1
- package/dist/client/handlers/handleSuback.js +3 -1
- package/dist/client/handlers/handleSuback.js.map +1 -1
- package/dist/client/mod.d.ts +3 -1
- package/dist/client/mod.d.ts.map +1 -1
- package/dist/client/mod.js +2 -1
- package/dist/client/mod.js.map +1 -1
- package/dist/client/store/memoryStore.d.ts +1 -1
- package/dist/client/store/memoryStore.d.ts.map +1 -1
- package/dist/client/store/memoryStore.js.map +1 -1
- package/dist/mqttConn/mqttConn.d.ts +13 -8
- package/dist/mqttConn/mqttConn.d.ts.map +1 -1
- package/dist/mqttConn/mqttConn.js +27 -12
- package/dist/mqttConn/mqttConn.js.map +1 -1
- package/dist/mqttPacket/PacketType.d.ts +1 -0
- package/dist/mqttPacket/PacketType.d.ts.map +1 -1
- package/dist/mqttPacket/PacketType.js +1 -0
- package/dist/mqttPacket/PacketType.js.map +1 -1
- package/dist/mqttPacket/Properties.d.ts +157 -0
- package/dist/mqttPacket/Properties.d.ts.map +1 -0
- package/dist/mqttPacket/Properties.js +177 -0
- package/dist/mqttPacket/Properties.js.map +1 -0
- package/dist/mqttPacket/ReasonCode.d.ts +74 -0
- package/dist/mqttPacket/ReasonCode.d.ts.map +1 -0
- package/dist/mqttPacket/ReasonCode.js +230 -0
- package/dist/mqttPacket/ReasonCode.js.map +1 -0
- package/dist/mqttPacket/RetainHandling.d.ts +12 -0
- package/dist/mqttPacket/RetainHandling.d.ts.map +1 -0
- package/dist/mqttPacket/RetainHandling.js +12 -0
- package/dist/mqttPacket/RetainHandling.js.map +1 -0
- package/dist/mqttPacket/auth.d.ts +21 -0
- package/dist/mqttPacket/auth.d.ts.map +1 -0
- package/dist/mqttPacket/auth.js +34 -0
- package/dist/mqttPacket/auth.js.map +1 -0
- package/dist/mqttPacket/connack.d.ts +19 -11
- package/dist/mqttPacket/connack.d.ts.map +1 -1
- package/dist/mqttPacket/connack.js +43 -15
- package/dist/mqttPacket/connack.js.map +1 -1
- package/dist/mqttPacket/connect.d.ts +30 -11
- package/dist/mqttPacket/connect.d.ts.map +1 -1
- package/dist/mqttPacket/connect.js +106 -30
- package/dist/mqttPacket/connect.js.map +1 -1
- package/dist/mqttPacket/decoder.d.ts +42 -3
- package/dist/mqttPacket/decoder.d.ts.map +1 -1
- package/dist/mqttPacket/decoder.js +135 -4
- package/dist/mqttPacket/decoder.js.map +1 -1
- package/dist/mqttPacket/disconnect.d.ts +15 -9
- package/dist/mqttPacket/disconnect.d.ts.map +1 -1
- package/dist/mqttPacket/disconnect.js +45 -6
- package/dist/mqttPacket/disconnect.js.map +1 -1
- package/dist/mqttPacket/encoder.d.ts +57 -8
- package/dist/mqttPacket/encoder.d.ts.map +1 -1
- package/dist/mqttPacket/encoder.js +185 -13
- package/dist/mqttPacket/encoder.js.map +1 -1
- package/dist/mqttPacket/length.d.ts.map +1 -1
- package/dist/mqttPacket/length.js +3 -2
- package/dist/mqttPacket/length.js.map +1 -1
- package/dist/mqttPacket/mod.d.ts +57 -91
- package/dist/mqttPacket/mod.d.ts.map +1 -1
- package/dist/mqttPacket/mod.js +23 -29
- package/dist/mqttPacket/mod.js.map +1 -1
- package/dist/mqttPacket/pingreq.d.ts +4 -6
- package/dist/mqttPacket/pingreq.d.ts.map +1 -1
- package/dist/mqttPacket/pingreq.js +5 -4
- package/dist/mqttPacket/pingreq.js.map +1 -1
- package/dist/mqttPacket/pingres.d.ts +4 -6
- package/dist/mqttPacket/pingres.d.ts.map +1 -1
- package/dist/mqttPacket/pingres.js +7 -5
- package/dist/mqttPacket/pingres.js.map +1 -1
- package/dist/mqttPacket/protocolLevels.d.ts +12 -0
- package/dist/mqttPacket/protocolLevels.d.ts.map +1 -0
- package/dist/mqttPacket/protocolLevels.js +11 -0
- package/dist/mqttPacket/protocolLevels.js.map +1 -0
- package/dist/mqttPacket/pubblishAcks.d.ts +42 -0
- package/dist/mqttPacket/pubblishAcks.d.ts.map +1 -0
- package/dist/mqttPacket/pubblishAcks.js +56 -0
- package/dist/mqttPacket/pubblishAcks.js.map +1 -0
- package/dist/mqttPacket/publish.d.ts +19 -8
- package/dist/mqttPacket/publish.d.ts.map +1 -1
- package/dist/mqttPacket/publish.js +26 -7
- package/dist/mqttPacket/publish.js.map +1 -1
- package/dist/mqttPacket/suback.d.ts +18 -11
- package/dist/mqttPacket/suback.d.ts.map +1 -1
- package/dist/mqttPacket/suback.js +41 -20
- package/dist/mqttPacket/suback.js.map +1 -1
- package/dist/mqttPacket/subscribe.d.ts +27 -12
- package/dist/mqttPacket/subscribe.d.ts.map +1 -1
- package/dist/mqttPacket/subscribe.js +71 -15
- package/dist/mqttPacket/subscribe.js.map +1 -1
- package/dist/mqttPacket/types.d.ts +36 -0
- package/dist/mqttPacket/types.d.ts.map +1 -1
- package/dist/mqttPacket/unsuback.d.ts +17 -10
- package/dist/mqttPacket/unsuback.d.ts.map +1 -1
- package/dist/mqttPacket/unsuback.js +29 -6
- package/dist/mqttPacket/unsuback.js.map +1 -1
- package/dist/mqttPacket/unsubscribe.d.ts +17 -10
- package/dist/mqttPacket/unsubscribe.d.ts.map +1 -1
- package/dist/mqttPacket/unsubscribe.js +24 -8
- package/dist/mqttPacket/unsubscribe.js.map +1 -1
- package/dist/mqttPacket/validators.d.ts +15 -0
- package/dist/mqttPacket/validators.d.ts.map +1 -1
- package/dist/mqttPacket/validators.js +15 -0
- package/dist/mqttPacket/validators.js.map +1 -1
- package/dist/node/tcpClient.js +1 -1
- package/dist/node/tcpClient.js.map +1 -1
- package/dist/node/wrapNodeSocket.d.ts.map +1 -1
- package/dist/node/wrapNodeSocket.js.map +1 -1
- package/dist/persistence/deps.d.ts +1 -1
- package/dist/persistence/deps.d.ts.map +1 -1
- package/dist/persistence/deps.js +1 -1
- package/dist/persistence/deps.js.map +1 -1
- package/dist/persistence/memory/memoryPersistence.js +1 -1
- package/dist/persistence/memory/memoryPersistence.js.map +1 -1
- package/dist/server/context.d.ts +3 -1
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/context.js +8 -2
- package/dist/server/context.js.map +1 -1
- package/dist/server/deps.d.ts +2 -2
- package/dist/server/deps.d.ts.map +1 -1
- package/dist/server/deps.js +1 -1
- package/dist/server/deps.js.map +1 -1
- package/dist/server/handlers/handleConnect.d.ts +1 -1
- package/dist/server/handlers/handleConnect.d.ts.map +1 -1
- package/dist/server/handlers/handleConnect.js +9 -1
- package/dist/server/handlers/handleConnect.js.map +1 -1
- package/dist/server/handlers/handlePacket.d.ts +1 -1
- package/dist/server/handlers/handlePacket.d.ts.map +1 -1
- package/dist/server/handlers/handlePacket.js +1 -1
- package/dist/server/handlers/handlePacket.js.map +1 -1
- package/dist/server/handlers/handlePingreq.d.ts.map +1 -1
- package/dist/server/handlers/handlePingreq.js +1 -0
- package/dist/server/handlers/handlePingreq.js.map +1 -1
- package/dist/server/handlers/handlePublish.d.ts +2 -2
- package/dist/server/handlers/handlePublish.d.ts.map +1 -1
- package/dist/server/handlers/handlePublish.js +2 -0
- package/dist/server/handlers/handlePublish.js.map +1 -1
- package/dist/server/handlers/handlePubrec.d.ts +1 -1
- package/dist/server/handlers/handlePubrec.d.ts.map +1 -1
- package/dist/server/handlers/handlePubrec.js +1 -0
- package/dist/server/handlers/handlePubrec.js.map +1 -1
- package/dist/server/handlers/handlePubrel.d.ts +1 -1
- package/dist/server/handlers/handlePubrel.d.ts.map +1 -1
- package/dist/server/handlers/handlePubrel.js +1 -0
- package/dist/server/handlers/handlePubrel.js.map +1 -1
- package/dist/server/handlers/handleSubscribe.d.ts +1 -1
- package/dist/server/handlers/handleSubscribe.d.ts.map +1 -1
- package/dist/server/handlers/handleSubscribe.js +2 -1
- package/dist/server/handlers/handleSubscribe.js.map +1 -1
- package/dist/server/handlers/handleUnsubscribe.d.ts +1 -1
- package/dist/server/handlers/handleUnsubscribe.d.ts.map +1 -1
- package/dist/server/handlers/handleUnsubscribe.js +1 -0
- package/dist/server/handlers/handleUnsubscribe.js.map +1 -1
- package/dist/server/server.d.ts +2 -2
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +5 -3
- package/dist/server/server.js.map +1 -1
- package/dist/socket/socket.d.ts.map +1 -1
- package/dist/socket/socket.js +6 -1
- package/dist/socket/socket.js.map +1 -1
- package/dist/utils/assert.d.ts +0 -3
- package/dist/utils/assert.d.ts.map +1 -1
- package/dist/utils/assert.js +0 -7
- package/dist/utils/assert.js.map +1 -1
- package/dist/utils/asyncQueue.d.ts +1 -3
- package/dist/utils/asyncQueue.d.ts.map +1 -1
- package/dist/utils/asyncQueue.js +16 -21
- package/dist/utils/asyncQueue.js.map +1 -1
- package/dist/utils/logger.d.ts +5 -15
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +7 -8
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/mod.d.ts +0 -3
- package/dist/utils/mod.d.ts.map +1 -1
- package/dist/utils/mod.js +0 -2
- package/dist/utils/mod.js.map +1 -1
- package/dist/utils/utils.d.ts +2 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +6 -0
- package/dist/utils/utils.js.map +1 -0
- package/mqttConn/mqttConn.test.ts +27 -12
- package/mqttConn/mqttConn.ts +45 -14
- package/mqttPacket/PacketType.ts +1 -0
- package/mqttPacket/Properties.ts +276 -0
- package/mqttPacket/ReasonCode.test.ts +22 -0
- package/mqttPacket/ReasonCode.ts +256 -0
- package/mqttPacket/RetainHandling.ts +11 -0
- package/mqttPacket/auth.test.ts +112 -0
- package/mqttPacket/auth.ts +71 -0
- package/mqttPacket/connack.test.ts +84 -64
- package/mqttPacket/connack.ts +88 -24
- package/mqttPacket/connect.test.ts +497 -18
- package/mqttPacket/connect.ts +170 -39
- package/mqttPacket/decoder.test.ts +33 -16
- package/mqttPacket/decoder.ts +173 -5
- package/mqttPacket/disconnect.test.ts +97 -18
- package/mqttPacket/disconnect.ts +84 -12
- package/mqttPacket/encoder.test.ts +32 -8
- package/mqttPacket/encoder.ts +236 -11
- package/mqttPacket/length.ts +3 -2
- package/mqttPacket/mod.ts +76 -39
- package/mqttPacket/pingreq.test.ts +52 -4
- package/mqttPacket/pingreq.ts +20 -7
- package/mqttPacket/pingres.test.ts +52 -4
- package/mqttPacket/pingres.ts +22 -8
- package/mqttPacket/properties.test.ts +193 -0
- package/mqttPacket/protocolLevels.ts +13 -0
- package/mqttPacket/pubblishAcks.ts +123 -0
- package/mqttPacket/publish.test.ts +212 -133
- package/mqttPacket/publish.ts +69 -14
- package/mqttPacket/publishAcks.test.ts +128 -0
- package/mqttPacket/suback.test.ts +71 -27
- package/mqttPacket/suback.ts +82 -30
- package/mqttPacket/subscribe.test.ts +132 -43
- package/mqttPacket/subscribe.ts +128 -25
- package/mqttPacket/types.ts +43 -0
- package/mqttPacket/unsuback.test.ts +80 -30
- package/mqttPacket/unsuback.ts +68 -13
- package/mqttPacket/unsubscribe.test.ts +59 -34
- package/mqttPacket/unsubscribe.ts +64 -17
- package/mqttPacket/validators.ts +15 -0
- package/node/tcpClient.ts +1 -1
- package/node/wrapNodeSocket.ts +2 -1
- package/package.json +2 -2
- package/persistence/deps.ts +1 -1
- package/persistence/memory/memoryPersistence.test.ts +5 -1
- package/persistence/memory/memoryPersistence.ts +1 -1
- package/server/context.ts +23 -10
- package/server/deps.ts +2 -0
- package/server/handlers/handleConnect.ts +12 -9
- package/server/handlers/handlePacket.ts +10 -11
- package/server/handlers/handlePingreq.ts +1 -0
- package/server/handlers/handlePublish.ts +6 -2
- package/server/handlers/handlePubrec.ts +3 -1
- package/server/handlers/handlePubrel.ts +3 -1
- package/server/handlers/handleSubscribe.ts +3 -6
- package/server/handlers/handleUnsubscribe.ts +3 -1
- package/server/server.ts +8 -12
- package/server/test/handleConnect.test.ts +2 -1
- package/server/test/test-handlers.ts +2 -1
- package/socket/socket.ts +5 -1
- package/utils/assert.ts +0 -18
- package/utils/asyncQueue.ts +17 -21
- package/utils/logger.ts +12 -11
- package/utils/mod.ts +0 -3
- package/utils/utils.ts +6 -0
- package/dist/mqttPacket/puback.d.ts +0 -16
- package/dist/mqttPacket/puback.d.ts.map +0 -1
- package/dist/mqttPacket/puback.js +0 -21
- package/dist/mqttPacket/puback.js.map +0 -1
- package/dist/mqttPacket/pubcomp.d.ts +0 -17
- package/dist/mqttPacket/pubcomp.d.ts.map +0 -1
- package/dist/mqttPacket/pubcomp.js +0 -21
- package/dist/mqttPacket/pubcomp.js.map +0 -1
- package/dist/mqttPacket/pubrec.d.ts +0 -17
- package/dist/mqttPacket/pubrec.d.ts.map +0 -1
- package/dist/mqttPacket/pubrec.js +0 -21
- package/dist/mqttPacket/pubrec.js.map +0 -1
- package/dist/mqttPacket/pubrel.d.ts +0 -17
- package/dist/mqttPacket/pubrel.d.ts.map +0 -1
- package/dist/mqttPacket/pubrel.js +0 -21
- package/dist/mqttPacket/pubrel.js.map +0 -1
- package/dist/utils/args.d.ts +0 -28
- package/dist/utils/args.d.ts.map +0 -1
- package/dist/utils/args.js +0 -76
- package/dist/utils/args.js.map +0 -1
- package/dist/utils/platform.d.ts +0 -5
- package/dist/utils/platform.d.ts.map +0 -1
- package/dist/utils/platform.js +0 -8
- package/dist/utils/platform.js.map +0 -1
- package/mqttPacket/puback.test.ts +0 -55
- package/mqttPacket/puback.ts +0 -34
- package/mqttPacket/pubcomp.test.ts +0 -55
- package/mqttPacket/pubcomp.ts +0 -35
- package/mqttPacket/pubrec.test.ts +0 -55
- package/mqttPacket/pubrec.ts +0 -35
- package/mqttPacket/pubrel.test.ts +0 -55
- package/mqttPacket/pubrel.ts +0 -35
- package/utils/args.ts +0 -103
- package/utils/platform.ts +0 -8
|
@@ -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
|
-
|
|
6
|
+
const codecOptsV4: CodecOpts = {
|
|
7
|
+
protocolLevel: MQTTLevel.v4,
|
|
8
|
+
maxIncomingPacketSize: 0xffff,
|
|
9
|
+
maxOutgoingPacketSize: 0xffff,
|
|
10
|
+
};
|
|
6
11
|
|
|
7
|
-
|
|
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
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
});
|
package/mqttPacket/suback.ts
CHANGED
|
@@ -1,48 +1,100 @@
|
|
|
1
|
-
import type {
|
|
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
|
-
|
|
7
|
-
* SubackPacket is sent by the server to the client to confirm receipt and
|
|
8
|
-
* processing of a SubscribePacket.
|
|
9
|
-
*/
|
|
10
|
-
export type SubackPacket = {
|
|
15
|
+
export type SubackPacketV4 = {
|
|
11
16
|
type: TPacketType;
|
|
17
|
+
protocolLevel: ProtocolLevelNoV5;
|
|
12
18
|
id: PacketId;
|
|
13
19
|
returnCodes: ReturnCodes;
|
|
14
20
|
};
|
|
15
21
|
|
|
22
|
+
export type SubackPacketV5 = {
|
|
23
|
+
type: TPacketType;
|
|
24
|
+
protocolLevel: 5;
|
|
25
|
+
id: PacketId;
|
|
26
|
+
properties: SubackProperties;
|
|
27
|
+
reasonCodes: Array<TReasonCode>;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* SubackPacket is sent by the server to the client to confirm receipt and
|
|
32
|
+
* processing of a SubscribePacket.
|
|
33
|
+
*/
|
|
34
|
+
export type SubackPacket = SubackPacketV4 | SubackPacketV5;
|
|
35
|
+
|
|
16
36
|
export const suback: {
|
|
17
|
-
encode(packet: SubackPacket
|
|
18
|
-
decode(
|
|
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
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
39
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
+
});
|
package/mqttPacket/subscribe.ts
CHANGED
|
@@ -1,78 +1,181 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
CodecOpts,
|
|
3
|
+
PacketId,
|
|
4
|
+
ProtocolLevelNoV5,
|
|
5
|
+
QoS,
|
|
6
|
+
TopicFilter,
|
|
7
|
+
TPacketType,
|
|
8
|
+
TRetainHandling,
|
|
9
|
+
} from "./types.ts";
|
|
10
|
+
import type { SubscribeProperties } from "./Properties.ts";
|
|
2
11
|
import { PacketType } from "./PacketType.ts";
|
|
3
12
|
import { BitMask } from "./BitMask.ts";
|
|
4
13
|
import { Encoder } from "./encoder.ts";
|
|
5
14
|
import { booleanFlag, Decoder, DecoderError } from "./decoder.ts";
|
|
6
15
|
|
|
7
|
-
|
|
8
|
-
* SubscribePacket is sent from client to server to subscribe to topics
|
|
9
|
-
*/
|
|
10
|
-
export type SubscribePacket = {
|
|
16
|
+
export type SubscribePacketV4 = {
|
|
11
17
|
type: TPacketType;
|
|
18
|
+
protocolLevel: ProtocolLevelNoV5;
|
|
12
19
|
id: PacketId;
|
|
13
|
-
subscriptions:
|
|
20
|
+
subscriptions: Array<SubscriptionV4>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type SubscribePacketV5 = {
|
|
24
|
+
type: TPacketType;
|
|
25
|
+
protocolLevel: 5;
|
|
26
|
+
id: PacketId;
|
|
27
|
+
properties?: SubscribeProperties;
|
|
28
|
+
subscriptions: Array<SubscriptionV5>;
|
|
14
29
|
};
|
|
15
30
|
|
|
31
|
+
/**
|
|
32
|
+
* SubscribePacket is sent from client to server to subscribe to topics
|
|
33
|
+
*/
|
|
34
|
+
export type SubscribePacket = SubscribePacketV4 | SubscribePacketV5;
|
|
16
35
|
/**
|
|
17
36
|
* The topic to subscribe to and the associated QoS
|
|
18
37
|
*/
|
|
19
|
-
export type
|
|
38
|
+
export type SubscriptionV4 = {
|
|
20
39
|
topicFilter: TopicFilter;
|
|
21
40
|
qos: QoS;
|
|
22
41
|
};
|
|
23
42
|
|
|
43
|
+
export type SubscriptionV5 = {
|
|
44
|
+
topicFilter: TopicFilter;
|
|
45
|
+
qos: QoS;
|
|
46
|
+
noLocal?: boolean;
|
|
47
|
+
retainAsPublished?: boolean;
|
|
48
|
+
retainHandling?: TRetainHandling;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type Subscription = SubscriptionV4 | SubscriptionV5;
|
|
52
|
+
|
|
24
53
|
export const subscribe: {
|
|
25
|
-
encode(packet: SubscribePacket
|
|
26
|
-
decode(
|
|
54
|
+
encode(packet: SubscribePacket, codecOpts: CodecOpts): Uint8Array;
|
|
55
|
+
decode(
|
|
56
|
+
buffer: Uint8Array,
|
|
57
|
+
flags: number,
|
|
58
|
+
codecOpts: CodecOpts,
|
|
59
|
+
packetType: TPacketType,
|
|
60
|
+
): SubscribePacket;
|
|
27
61
|
} = {
|
|
28
|
-
encode(packet: SubscribePacket
|
|
62
|
+
encode(packet: SubscribePacket, codecOpts: CodecOpts): Uint8Array {
|
|
29
63
|
// Bits 3,2,1 and 0 of the fixed header of the SUBSCRIBE Control Packet are reserved and
|
|
30
64
|
// MUST be set to 0,0,1 and 0 respectively. The Server MUST treat any other value as
|
|
31
65
|
// malformed and close the Network Connection [MQTT-3.8.1-1].
|
|
32
66
|
const flags = 0b0010;
|
|
33
67
|
|
|
34
|
-
const encoder = new Encoder();
|
|
68
|
+
const encoder = new Encoder(packet.type);
|
|
35
69
|
encoder.setInt16(packet.id);
|
|
70
|
+
if (packet.protocolLevel === 5) {
|
|
71
|
+
encoder.setProperties(
|
|
72
|
+
packet.properties || {},
|
|
73
|
+
packet.type,
|
|
74
|
+
codecOpts.maxOutgoingPacketSize,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
36
77
|
for (const sub of packet.subscriptions) {
|
|
37
|
-
encoder.
|
|
38
|
-
|
|
78
|
+
encoder.setTopicFilter(sub.topicFilter);
|
|
79
|
+
if (packet.protocolLevel === 5) {
|
|
80
|
+
const {
|
|
81
|
+
qos,
|
|
82
|
+
noLocal = false,
|
|
83
|
+
retainAsPublished = false,
|
|
84
|
+
retainHandling = 0,
|
|
85
|
+
} = sub as SubscriptionV5;
|
|
86
|
+
const option = (qos & 1 ? BitMask.bit0 : 0) +
|
|
87
|
+
(qos & 2 ? BitMask.bit1 : 0) +
|
|
88
|
+
(noLocal ? BitMask.bit2 : 0) +
|
|
89
|
+
(retainAsPublished ? BitMask.bit3 : 0) +
|
|
90
|
+
((retainHandling as number) & 1 ? BitMask.bit4 : 0) +
|
|
91
|
+
((retainHandling as number) & 2 ? BitMask.bit5 : 0);
|
|
92
|
+
encoder.setByte(option);
|
|
93
|
+
} else {
|
|
94
|
+
encoder.setByte(sub.qos);
|
|
95
|
+
}
|
|
39
96
|
}
|
|
40
|
-
return
|
|
97
|
+
return encoder.done(flags);
|
|
41
98
|
},
|
|
42
99
|
|
|
43
|
-
decode(
|
|
100
|
+
decode(
|
|
101
|
+
buffer: Uint8Array,
|
|
102
|
+
flags: number,
|
|
103
|
+
codecOpts: CodecOpts,
|
|
104
|
+
packetType: TPacketType,
|
|
105
|
+
): SubscribePacket {
|
|
44
106
|
// Bits 3,2,1 and 0 of the fixed header of the SUBSCRIBE Control Packet are reserved and
|
|
45
107
|
// MUST be set to 0,0,1 and 0 respectively. The Server MUST treat any other value as
|
|
46
108
|
// malformed and close the Network Connection [MQTT-3.8.1-1].
|
|
47
|
-
if (
|
|
109
|
+
if (flags !== 0b0010) {
|
|
48
110
|
throw new DecoderError("Invalid header");
|
|
49
111
|
}
|
|
50
|
-
|
|
51
|
-
const decoder = new Decoder(buffer);
|
|
112
|
+
const decoder = new Decoder(packetType, buffer);
|
|
52
113
|
const id = decoder.getInt16();
|
|
114
|
+
let properties = {};
|
|
115
|
+
if (codecOpts.protocolLevel === 5) {
|
|
116
|
+
properties = decoder.getProperties(PacketType.subscribe);
|
|
117
|
+
}
|
|
53
118
|
|
|
54
119
|
const subscriptions: Subscription[] = [];
|
|
55
|
-
// The payload of a SUBSCRIBE packet MUST contain at least one Topic Filter /
|
|
120
|
+
// The payload of a SUBSCRIBE packet MUST contain at least one Topic Filter / Option pair.
|
|
56
121
|
// A SUBSCRIBE packet with no payload is a protocol violation [MQTT-3.8.3-3].
|
|
57
122
|
do {
|
|
58
123
|
const topicFilter = decoder.getTopicFilter();
|
|
59
|
-
const
|
|
124
|
+
const option = decoder.getByte();
|
|
125
|
+
const qos = option & 0b11;
|
|
60
126
|
if (qos !== 0 && qos !== 1 && qos !== 2) {
|
|
61
127
|
throw new DecoderError("Invalid qos");
|
|
62
128
|
}
|
|
63
129
|
if (qos > 0 && id === 0) {
|
|
64
130
|
throw new DecoderError("Invalid packet identifier");
|
|
65
131
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
132
|
+
if (codecOpts.protocolLevel !== 5) {
|
|
133
|
+
if (option !== qos) {
|
|
134
|
+
throw new DecoderError("Invalid qos");
|
|
135
|
+
}
|
|
136
|
+
subscriptions.push({
|
|
137
|
+
topicFilter: topicFilter,
|
|
138
|
+
qos,
|
|
139
|
+
} as SubscriptionV4);
|
|
140
|
+
} else {
|
|
141
|
+
// Bits 6 and 7 of the Subscription Options byte are reserved for future use.
|
|
142
|
+
// The Server MUST treat a SUBSCRIBE packet as malformed if any of
|
|
143
|
+
// Reserved bits in the Payload are non-zero [MQTT-3.8.3-5].
|
|
144
|
+
if (option > 0b111111) {
|
|
145
|
+
throw new DecoderError("Invalid subscription options");
|
|
146
|
+
}
|
|
147
|
+
const noLocal = booleanFlag(option, BitMask.bit2);
|
|
148
|
+
const retainAsPublished = booleanFlag(option, BitMask.bit3);
|
|
149
|
+
const retainHandling = (option & 0b110000) >> 4;
|
|
150
|
+
if (
|
|
151
|
+
retainHandling !== 0 && retainHandling !== 1 && retainHandling !== 2
|
|
152
|
+
) {
|
|
153
|
+
throw new DecoderError("Invalid retain handling");
|
|
154
|
+
}
|
|
155
|
+
subscriptions.push({
|
|
156
|
+
topicFilter: topicFilter,
|
|
157
|
+
qos,
|
|
158
|
+
noLocal,
|
|
159
|
+
retainAsPublished,
|
|
160
|
+
retainHandling,
|
|
161
|
+
} as SubscriptionV5);
|
|
162
|
+
}
|
|
70
163
|
} while (!decoder.atEnd());
|
|
71
164
|
decoder.done();
|
|
165
|
+
if (codecOpts.protocolLevel !== 5) {
|
|
166
|
+
return {
|
|
167
|
+
type: PacketType.subscribe,
|
|
168
|
+
protocolLevel: codecOpts.protocolLevel,
|
|
169
|
+
id,
|
|
170
|
+
subscriptions: subscriptions as Array<SubscriptionV4>,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
72
173
|
return {
|
|
73
174
|
type: PacketType.subscribe,
|
|
175
|
+
protocolLevel: 5,
|
|
74
176
|
id,
|
|
75
|
-
|
|
177
|
+
properties,
|
|
178
|
+
subscriptions: subscriptions as Array<SubscriptionV5>,
|
|
76
179
|
};
|
|
77
180
|
},
|
|
78
181
|
};
|