@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.
- package/README.md +37 -26
- package/bin/conformanceServer.ts +3 -2
- package/bin/demoServer.ts +3 -2
- package/bin/mqtt.ts +126 -117
- package/client/client.ts +35 -15
- package/client/context.ts +42 -22
- 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/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 +101 -96
- package/dist/bin/mqtt.js.map +1 -1
- package/dist/client/client.d.ts +7 -4
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +17 -9
- package/dist/client/client.js.map +1 -1
- package/dist/client/context.d.ts +3 -1
- package/dist/client/context.d.ts.map +1 -1
- package/dist/client/context.js +27 -13
- 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 +15 -7
- 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 +27 -8
- 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 +13 -7
- 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 +56 -91
- package/dist/mqttPacket/mod.d.ts.map +1 -1
- package/dist/mqttPacket/mod.js +22 -22
- 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 +11 -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 +35 -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 +14 -7
- 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 +24 -9
- 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 +33 -0
- package/dist/mqttPacket/types.d.ts.map +1 -1
- package/dist/mqttPacket/unsuback.d.ts +14 -7
- 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 +14 -7
- 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/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/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/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/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 +72 -0
- package/mqttPacket/connack.test.ts +84 -64
- package/mqttPacket/connack.ts +84 -20
- package/mqttPacket/connect.test.ts +497 -18
- package/mqttPacket/connect.ts +167 -36
- package/mqttPacket/decoder.test.ts +33 -16
- package/mqttPacket/decoder.ts +173 -5
- package/mqttPacket/disconnect.test.ts +97 -18
- package/mqttPacket/disconnect.ts +82 -10
- package/mqttPacket/encoder.test.ts +32 -8
- package/mqttPacket/encoder.ts +236 -11
- package/mqttPacket/length.ts +3 -2
- package/mqttPacket/mod.ts +75 -32
- 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 +117 -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 +78 -26
- package/mqttPacket/subscribe.test.ts +132 -43
- package/mqttPacket/subscribe.ts +125 -22
- package/mqttPacket/types.ts +40 -0
- package/mqttPacket/unsuback.test.ts +80 -30
- package/mqttPacket/unsuback.ts +65 -10
- package/mqttPacket/unsubscribe.test.ts +59 -34
- package/mqttPacket/unsubscribe.ts +61 -14
- 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/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/mod.ts +0 -3
- 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
package/mqttPacket/connect.ts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ClientId,
|
|
3
|
+
CodecOpts,
|
|
4
|
+
Payload,
|
|
5
|
+
ProtocolLevel,
|
|
6
|
+
ProtocolLevelNoV5,
|
|
7
|
+
QoS,
|
|
8
|
+
Topic,
|
|
9
|
+
TPacketType,
|
|
10
|
+
} from "./types.ts";
|
|
11
|
+
import type { ConnectProperties, WillProperties } from "./Properties.ts";
|
|
12
|
+
import { PropertySetType } from "./Properties.ts";
|
|
2
13
|
import { PacketType } from "./PacketType.ts";
|
|
3
14
|
import { BitMask } from "./BitMask.ts";
|
|
4
|
-
import { Encoder } from "./encoder.ts";
|
|
15
|
+
import { Encoder, EncoderError } from "./encoder.ts";
|
|
5
16
|
import {
|
|
6
17
|
booleanFlag,
|
|
7
18
|
Decoder,
|
|
@@ -12,10 +23,10 @@ import {
|
|
|
12
23
|
/**
|
|
13
24
|
* ConnectPacket is sent from the client to the server to initiate a connection.
|
|
14
25
|
*/
|
|
15
|
-
export type
|
|
26
|
+
export type ConnectPacketV4 = {
|
|
16
27
|
type: TPacketType;
|
|
17
28
|
protocolName?: string;
|
|
18
|
-
protocolLevel
|
|
29
|
+
protocolLevel: ProtocolLevelNoV5;
|
|
19
30
|
clientId?: ClientId;
|
|
20
31
|
username?: string;
|
|
21
32
|
password?: Uint8Array;
|
|
@@ -27,31 +38,85 @@ export type ConnectPacket = {
|
|
|
27
38
|
};
|
|
28
39
|
clean?: boolean;
|
|
29
40
|
keepAlive?: number;
|
|
41
|
+
bridgeMode?: boolean;
|
|
30
42
|
};
|
|
31
43
|
|
|
44
|
+
export type ConnectPacketV5 = {
|
|
45
|
+
type: TPacketType;
|
|
46
|
+
protocolName?: string;
|
|
47
|
+
protocolLevel: 5;
|
|
48
|
+
clientId?: ClientId;
|
|
49
|
+
username?: string;
|
|
50
|
+
password?: Uint8Array;
|
|
51
|
+
will?: {
|
|
52
|
+
topic: Topic;
|
|
53
|
+
payload: Payload;
|
|
54
|
+
retain?: boolean;
|
|
55
|
+
qos?: QoS;
|
|
56
|
+
properties?: WillProperties;
|
|
57
|
+
};
|
|
58
|
+
clean?: boolean;
|
|
59
|
+
keepAlive?: number;
|
|
60
|
+
bridgeMode?: boolean;
|
|
61
|
+
properties?: ConnectProperties;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export type ConnectPacket = ConnectPacketV4 | ConnectPacketV5;
|
|
65
|
+
|
|
32
66
|
function invalidProtocolName(version: number, name: string): boolean {
|
|
33
|
-
if (version ===
|
|
34
|
-
return
|
|
67
|
+
if (version === 3 && name === "MQIsdp") {
|
|
68
|
+
return false;
|
|
35
69
|
}
|
|
36
|
-
|
|
70
|
+
if (version === 4 && name === "MQTT") {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
if (version === 5 && name == "MQTT") {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return true;
|
|
37
77
|
}
|
|
38
78
|
|
|
39
79
|
export const connect: {
|
|
40
|
-
encode(packet: ConnectPacket
|
|
41
|
-
decode(
|
|
80
|
+
encode(packet: ConnectPacket, _codecOpts: CodecOpts): Uint8Array;
|
|
81
|
+
decode(
|
|
82
|
+
buffer: Uint8Array,
|
|
83
|
+
flags: number,
|
|
84
|
+
codecOpts: CodecOpts,
|
|
85
|
+
packetType: TPacketType,
|
|
86
|
+
): ConnectPacket;
|
|
42
87
|
} = {
|
|
43
|
-
encode(packet: ConnectPacket
|
|
88
|
+
encode(packet: ConnectPacket, codecOpts: CodecOpts): Uint8Array {
|
|
44
89
|
const flags = 0;
|
|
45
90
|
|
|
46
|
-
|
|
47
|
-
|
|
91
|
+
if (typeof packet.protocolLevel !== "number") {
|
|
92
|
+
throw new EncoderError("Protocol level must be a number");
|
|
93
|
+
}
|
|
94
|
+
const protocolLevel = packet.protocolLevel || 4;
|
|
95
|
+
if (protocolLevel < 3 || protocolLevel > 5) {
|
|
96
|
+
throw new EncoderError("Unsupported protocol level");
|
|
97
|
+
}
|
|
98
|
+
const protocolName = protocolLevel > 3 ? "MQTT" : "MQIsdp";
|
|
48
99
|
const clientId = packet.clientId || "";
|
|
49
|
-
const usernameFlag =
|
|
50
|
-
|
|
100
|
+
const usernameFlag = packet.username !== undefined;
|
|
101
|
+
if (protocolLevel === 3 && clientId === "") {
|
|
102
|
+
throw new EncoderError("Client id required for protocol level 3");
|
|
103
|
+
}
|
|
104
|
+
const passwordFlag = usernameFlag && packet.password !== undefined;
|
|
51
105
|
const willRetain = !!packet.will?.retain;
|
|
52
106
|
const willQoS = packet.will?.qos || 0;
|
|
53
|
-
const willFlag =
|
|
107
|
+
const willFlag = packet.will !== undefined;
|
|
108
|
+
if (willFlag) {
|
|
109
|
+
if (packet.will?.topic === undefined) {
|
|
110
|
+
throw new EncoderError("Will topic must be defined");
|
|
111
|
+
}
|
|
112
|
+
if (packet.will?.payload === undefined) {
|
|
113
|
+
throw new EncoderError("Will payload must be defined");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
54
116
|
const cleanSession = packet.clean !== false;
|
|
117
|
+
if (!cleanSession && (clientId === "")) {
|
|
118
|
+
throw new EncoderError("Client id required for clean session");
|
|
119
|
+
}
|
|
55
120
|
const connectFlags = (usernameFlag ? BitMask.bit7 : 0) +
|
|
56
121
|
(passwordFlag ? BitMask.bit6 : 0) +
|
|
57
122
|
(willRetain ? BitMask.bit5 : 0) +
|
|
@@ -60,35 +125,64 @@ export const connect: {
|
|
|
60
125
|
(willFlag ? BitMask.bit2 : 0) +
|
|
61
126
|
(cleanSession ? BitMask.bit1 : 0);
|
|
62
127
|
const keepAlive = packet.keepAlive || 0;
|
|
128
|
+
const bridgeMode = !!packet.bridgeMode;
|
|
129
|
+
const rawProtocolLevel = bridgeMode ? protocolLevel + 128 : protocolLevel;
|
|
63
130
|
|
|
64
|
-
const encoder = new Encoder();
|
|
131
|
+
const encoder = new Encoder(packet.type);
|
|
65
132
|
encoder
|
|
66
133
|
.setUtf8String(protocolName)
|
|
67
|
-
.setByte(
|
|
134
|
+
.setByte(rawProtocolLevel)
|
|
68
135
|
.setByte(connectFlags)
|
|
69
|
-
.setInt16(keepAlive)
|
|
70
|
-
|
|
136
|
+
.setInt16(keepAlive);
|
|
137
|
+
if (packet.protocolLevel === 5) {
|
|
138
|
+
encoder.setProperties(
|
|
139
|
+
packet.properties || {},
|
|
140
|
+
PropertySetType.connect,
|
|
141
|
+
codecOpts.maxOutgoingPacketSize,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
encoder.setUtf8String(clientId);
|
|
71
145
|
|
|
72
|
-
if (
|
|
146
|
+
if (
|
|
147
|
+
packet.will !== undefined && packet.will.topic !== undefined &&
|
|
148
|
+
packet.will.payload !== undefined
|
|
149
|
+
) {
|
|
150
|
+
if (packet.protocolLevel === 5) {
|
|
151
|
+
encoder.setProperties(
|
|
152
|
+
packet.will?.properties || {},
|
|
153
|
+
PropertySetType.will,
|
|
154
|
+
codecOpts.maxOutgoingPacketSize,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
73
157
|
encoder.setTopic(packet.will.topic).setByteArray(packet.will.payload);
|
|
74
158
|
}
|
|
75
159
|
|
|
76
|
-
if (packet.username) {
|
|
160
|
+
if (packet.username !== undefined) {
|
|
77
161
|
encoder.setUtf8String(packet.username);
|
|
78
162
|
}
|
|
79
163
|
|
|
80
|
-
if (packet.password) {
|
|
164
|
+
if (passwordFlag && packet.password !== undefined) {
|
|
81
165
|
encoder.setByteArray(packet.password);
|
|
82
166
|
}
|
|
83
|
-
return
|
|
167
|
+
return encoder.done(flags);
|
|
84
168
|
},
|
|
85
169
|
|
|
86
|
-
decode(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
170
|
+
decode(
|
|
171
|
+
buffer: Uint8Array,
|
|
172
|
+
flags: number,
|
|
173
|
+
_codecOpts: CodecOpts,
|
|
174
|
+
packetType: TPacketType,
|
|
175
|
+
): ConnectPacket {
|
|
176
|
+
const decoder = new Decoder(packetType, buffer);
|
|
177
|
+
const protocolName = decoder.getUTF8String();
|
|
178
|
+
const rawProtocolLevel = decoder.getByte();
|
|
179
|
+
const bridgeMode = rawProtocolLevel > 128;
|
|
180
|
+
const protocolLevel = bridgeMode
|
|
181
|
+
? rawProtocolLevel - 128
|
|
182
|
+
: rawProtocolLevel;
|
|
183
|
+
|
|
90
184
|
if (invalidProtocolName(protocolLevel, protocolName)) {
|
|
91
|
-
throw new DecoderError("Invalid protocol name");
|
|
185
|
+
throw new DecoderError("Invalid protocol name or level");
|
|
92
186
|
}
|
|
93
187
|
|
|
94
188
|
const connectFlags = decoder.getByte();
|
|
@@ -112,12 +206,24 @@ export const connect: {
|
|
|
112
206
|
throw new DecoderError("Invalid will qos");
|
|
113
207
|
}
|
|
114
208
|
|
|
115
|
-
|
|
116
|
-
|
|
209
|
+
if (!usernameFlag && passwordFlag) {
|
|
210
|
+
throw new DecoderError("Password without username");
|
|
211
|
+
}
|
|
117
212
|
|
|
213
|
+
const keepAlive = decoder.getInt16();
|
|
214
|
+
const isV5 = protocolLevel === 5;
|
|
215
|
+
let properties;
|
|
216
|
+
if (isV5) {
|
|
217
|
+
properties = decoder.getProperties(PropertySetType.connect);
|
|
218
|
+
}
|
|
219
|
+
const clientId = decoder.getUTF8String();
|
|
220
|
+
let willProperties;
|
|
118
221
|
let willTopic;
|
|
119
222
|
let willPayload;
|
|
120
223
|
if (willFlag) {
|
|
224
|
+
if (isV5) {
|
|
225
|
+
willProperties = decoder.getProperties(PropertySetType.will);
|
|
226
|
+
}
|
|
121
227
|
willTopic = decoder.getTopic();
|
|
122
228
|
willPayload = decoder.getByteArray();
|
|
123
229
|
}
|
|
@@ -125,7 +231,7 @@ export const connect: {
|
|
|
125
231
|
let username;
|
|
126
232
|
let password;
|
|
127
233
|
if (usernameFlag) {
|
|
128
|
-
username = decoder.
|
|
234
|
+
username = decoder.getUTF8String();
|
|
129
235
|
}
|
|
130
236
|
|
|
131
237
|
if (passwordFlag) {
|
|
@@ -143,13 +249,40 @@ export const connect: {
|
|
|
143
249
|
throw new DecoderError("Clean session must be true if clientID is empty");
|
|
144
250
|
}
|
|
145
251
|
|
|
146
|
-
|
|
252
|
+
let bridgeModeProp = {};
|
|
253
|
+
if (bridgeMode) {
|
|
254
|
+
bridgeModeProp = { bridgeMode };
|
|
255
|
+
}
|
|
256
|
+
const commonProps = {
|
|
147
257
|
type: PacketType.connect,
|
|
148
258
|
protocolName: protocolName,
|
|
149
|
-
protocolLevel,
|
|
150
259
|
clientId: clientId,
|
|
151
|
-
username
|
|
260
|
+
username,
|
|
152
261
|
password: password ? password : undefined,
|
|
262
|
+
clean: cleanSession,
|
|
263
|
+
keepAlive,
|
|
264
|
+
...bridgeModeProp,
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
if (isV5) {
|
|
268
|
+
return {
|
|
269
|
+
...commonProps,
|
|
270
|
+
protocolLevel: 5,
|
|
271
|
+
will: willFlag
|
|
272
|
+
? {
|
|
273
|
+
topic: willTopic || "",
|
|
274
|
+
payload: willPayload || Uint8Array.from([0]),
|
|
275
|
+
retain: willRetain,
|
|
276
|
+
qos: willQoS,
|
|
277
|
+
properties: willProperties,
|
|
278
|
+
}
|
|
279
|
+
: undefined,
|
|
280
|
+
properties,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
...commonProps,
|
|
285
|
+
protocolLevel: protocolLevel as ProtocolLevel,
|
|
153
286
|
will: willFlag
|
|
154
287
|
? {
|
|
155
288
|
topic: willTopic || "",
|
|
@@ -158,8 +291,6 @@ export const connect: {
|
|
|
158
291
|
qos: willQoS,
|
|
159
292
|
}
|
|
160
293
|
: undefined,
|
|
161
|
-
clean: cleanSession,
|
|
162
|
-
keepAlive,
|
|
163
294
|
};
|
|
164
295
|
},
|
|
165
296
|
};
|
|
@@ -4,10 +4,11 @@ import { test } from "node:test";
|
|
|
4
4
|
import { Decoder } from "./decoder.ts";
|
|
5
5
|
|
|
6
6
|
const utf8encoder = new TextEncoder();
|
|
7
|
+
const packetType = 0;
|
|
7
8
|
|
|
8
9
|
test("decode byte", () => {
|
|
9
10
|
const byte = 127;
|
|
10
|
-
const decoder = new Decoder(Uint8Array.from([byte]));
|
|
11
|
+
const decoder = new Decoder(packetType, Uint8Array.from([byte]));
|
|
11
12
|
assert.deepStrictEqual(decoder.getByte(), byte);
|
|
12
13
|
assert.deepStrictEqual(decoder.done(), true);
|
|
13
14
|
});
|
|
@@ -16,7 +17,7 @@ test("decode Int16", () => {
|
|
|
16
17
|
const value = 0xf0f2;
|
|
17
18
|
const msb = 0xf0;
|
|
18
19
|
const lsb = 0xf2;
|
|
19
|
-
const decoder = new Decoder(Uint8Array.from([msb, lsb]));
|
|
20
|
+
const decoder = new Decoder(packetType, Uint8Array.from([msb, lsb]));
|
|
20
21
|
assert.deepStrictEqual(decoder.getInt16(), value);
|
|
21
22
|
assert.deepStrictEqual(decoder.done(), true);
|
|
22
23
|
});
|
|
@@ -25,7 +26,7 @@ test("decode Int16 with remainder", () => {
|
|
|
25
26
|
const value = 0xf0f2;
|
|
26
27
|
const msb = 0xf0;
|
|
27
28
|
const lsb = 0xf2;
|
|
28
|
-
const decoder = new Decoder(Uint8Array.from([msb, lsb, 0xff]));
|
|
29
|
+
const decoder = new Decoder(packetType, Uint8Array.from([msb, lsb, 0xff]));
|
|
29
30
|
assert.deepStrictEqual(decoder.getInt16(), value, "value is correct");
|
|
30
31
|
assert.deepStrictEqual(decoder.atEnd(), false);
|
|
31
32
|
});
|
|
@@ -35,6 +36,7 @@ test("decode byte array", () => {
|
|
|
35
36
|
byteArray.fill(127);
|
|
36
37
|
const len = byteArray.length;
|
|
37
38
|
const decoder = new Decoder(
|
|
39
|
+
packetType,
|
|
38
40
|
Uint8Array.from([len >> 8, len & 0xff, ...byteArray]),
|
|
39
41
|
);
|
|
40
42
|
assert.deepStrictEqual(decoder.getByteArray(), Uint8Array.from(byteArray));
|
|
@@ -44,7 +46,7 @@ test("decode byte array", () => {
|
|
|
44
46
|
test("decode byte array as remainder", () => {
|
|
45
47
|
const str = "hello world";
|
|
46
48
|
const byteArray = utf8encoder.encode(str);
|
|
47
|
-
const decoder = new Decoder(byteArray);
|
|
49
|
+
const decoder = new Decoder(packetType, byteArray);
|
|
48
50
|
assert.deepStrictEqual(decoder.getRemainder(), byteArray);
|
|
49
51
|
assert.deepStrictEqual(decoder.done(), true);
|
|
50
52
|
});
|
|
@@ -54,8 +56,11 @@ test("decode byte array as empty remainder", () => {
|
|
|
54
56
|
const emptyArray = Uint8Array.from([]);
|
|
55
57
|
const byteArray = utf8encoder.encode(str);
|
|
56
58
|
const len = byteArray.length;
|
|
57
|
-
const decoder = new Decoder(
|
|
58
|
-
|
|
59
|
+
const decoder = new Decoder(
|
|
60
|
+
packetType,
|
|
61
|
+
Uint8Array.from([0x00, len, ...byteArray]),
|
|
62
|
+
);
|
|
63
|
+
assert.deepStrictEqual(decoder.getUTF8String(), str);
|
|
59
64
|
assert.deepStrictEqual(decoder.getRemainder(), emptyArray);
|
|
60
65
|
assert.deepStrictEqual(decoder.done(), true);
|
|
61
66
|
});
|
|
@@ -64,8 +69,11 @@ test("decode string", () => {
|
|
|
64
69
|
const str = "hello world";
|
|
65
70
|
const byteArray = utf8encoder.encode(str);
|
|
66
71
|
const len = byteArray.length;
|
|
67
|
-
const decoder = new Decoder(
|
|
68
|
-
|
|
72
|
+
const decoder = new Decoder(
|
|
73
|
+
packetType,
|
|
74
|
+
Uint8Array.from([0x00, len, ...byteArray]),
|
|
75
|
+
);
|
|
76
|
+
assert.deepStrictEqual(decoder.getUTF8String(), str);
|
|
69
77
|
assert.deepStrictEqual(decoder.done(), true);
|
|
70
78
|
});
|
|
71
79
|
|
|
@@ -73,13 +81,16 @@ test("decode topic", () => {
|
|
|
73
81
|
const str = "hello world";
|
|
74
82
|
const byteArray = utf8encoder.encode(str);
|
|
75
83
|
const len = byteArray.length;
|
|
76
|
-
const decoder = new Decoder(
|
|
84
|
+
const decoder = new Decoder(
|
|
85
|
+
packetType,
|
|
86
|
+
Uint8Array.from([0x00, len, ...byteArray]),
|
|
87
|
+
);
|
|
77
88
|
assert.deepStrictEqual(decoder.getTopic(), str);
|
|
78
89
|
assert.deepStrictEqual(decoder.done(), true);
|
|
79
90
|
});
|
|
80
91
|
|
|
81
92
|
test("Topic too short", () => {
|
|
82
|
-
const decoder = new Decoder(Uint8Array.from([0x00, 0]));
|
|
93
|
+
const decoder = new Decoder(packetType, Uint8Array.from([0x00, 0]));
|
|
83
94
|
assert.throws(
|
|
84
95
|
() => decoder.getTopic(),
|
|
85
96
|
Error,
|
|
@@ -88,7 +99,7 @@ test("Topic too short", () => {
|
|
|
88
99
|
});
|
|
89
100
|
|
|
90
101
|
test("Invalid topic", () => {
|
|
91
|
-
const decoder = new Decoder(Uint8Array.from([0x00, 0x01, 0x00]));
|
|
102
|
+
const decoder = new Decoder(packetType, Uint8Array.from([0x00, 0x01, 0x00]));
|
|
92
103
|
assert.throws(
|
|
93
104
|
() => decoder.getTopic(),
|
|
94
105
|
Error,
|
|
@@ -97,7 +108,7 @@ test("Invalid topic", () => {
|
|
|
97
108
|
});
|
|
98
109
|
|
|
99
110
|
test("Invalid topicFilter", () => {
|
|
100
|
-
const decoder = new Decoder(Uint8Array.from([0x00, 0x01, 0x00]));
|
|
111
|
+
const decoder = new Decoder(packetType, Uint8Array.from([0x00, 0x01, 0x00]));
|
|
101
112
|
assert.throws(
|
|
102
113
|
() => decoder.getTopic(),
|
|
103
114
|
Error,
|
|
@@ -109,15 +120,21 @@ test("Buffer too short", () => {
|
|
|
109
120
|
const str = "hello world";
|
|
110
121
|
const byteArray = utf8encoder.encode(str);
|
|
111
122
|
const len = byteArray.length;
|
|
112
|
-
const decoder = new Decoder(
|
|
113
|
-
|
|
123
|
+
const decoder = new Decoder(
|
|
124
|
+
packetType,
|
|
125
|
+
Uint8Array.from([0x00, len + 1, ...byteArray]),
|
|
126
|
+
);
|
|
127
|
+
assert.throws(() => decoder.getUTF8String(), Error, "too short");
|
|
114
128
|
});
|
|
115
129
|
|
|
116
130
|
test("Buffer too long", () => {
|
|
117
131
|
const str = "hello world";
|
|
118
132
|
const byteArray = utf8encoder.encode(str);
|
|
119
133
|
const len = byteArray.length;
|
|
120
|
-
const decoder = new Decoder(
|
|
121
|
-
|
|
134
|
+
const decoder = new Decoder(
|
|
135
|
+
packetType,
|
|
136
|
+
Uint8Array.from([0x00, len, ...byteArray, 0]),
|
|
137
|
+
);
|
|
138
|
+
assert.deepStrictEqual(decoder.getUTF8String(), str);
|
|
122
139
|
assert.throws(() => decoder.done(), Error, "too long");
|
|
123
140
|
});
|
package/mqttPacket/decoder.ts
CHANGED
|
@@ -1,7 +1,32 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
TBitMask,
|
|
3
|
+
Topic,
|
|
4
|
+
TopicFilter,
|
|
5
|
+
TPacketType,
|
|
6
|
+
TReasonCode,
|
|
7
|
+
UTF8StringPair,
|
|
8
|
+
} from "./types.ts";
|
|
2
9
|
import { invalidTopic, invalidTopicFilter } from "./validators.ts";
|
|
10
|
+
import { isValidReasonCode } from "./ReasonCode.ts";
|
|
11
|
+
import type {
|
|
12
|
+
Mqttv5PropertyTypesNoUser,
|
|
13
|
+
PropsByPacketSetType,
|
|
14
|
+
SubscriptionIdentifiersType,
|
|
15
|
+
UserPropertyType,
|
|
16
|
+
ValidPropertyNumber,
|
|
17
|
+
} from "./Properties.ts";
|
|
18
|
+
import {
|
|
19
|
+
propertyByNumber,
|
|
20
|
+
PropertyByPropertySetType,
|
|
21
|
+
propertyKind,
|
|
22
|
+
propertyToId,
|
|
23
|
+
propertyToKind,
|
|
24
|
+
} from "./Properties.ts";
|
|
3
25
|
|
|
4
26
|
const utf8Decoder = new TextDecoder("utf-8");
|
|
27
|
+
const userPropID = propertyToId.userProperty;
|
|
28
|
+
const subIdentID = propertyToId.subscriptionIdentifier;
|
|
29
|
+
const subIdentsID = propertyToId.subscriptionIdentifiers;
|
|
5
30
|
/**
|
|
6
31
|
* Checks if a specific bit flag is set in a byte using a bitmask
|
|
7
32
|
* @param byte - The byte to check
|
|
@@ -48,6 +73,7 @@ export class DecoderError extends Error {
|
|
|
48
73
|
* Decoder class for parsing MQTT packets
|
|
49
74
|
*/
|
|
50
75
|
export class Decoder {
|
|
76
|
+
private packetType: TPacketType;
|
|
51
77
|
private buf: Uint8Array;
|
|
52
78
|
private pos: number;
|
|
53
79
|
private len: number;
|
|
@@ -57,7 +83,8 @@ export class Decoder {
|
|
|
57
83
|
* @param buf - The buffer to decode
|
|
58
84
|
* @param pos - Starting position in the buffer (default: 0)
|
|
59
85
|
*/
|
|
60
|
-
constructor(buf: Uint8Array, pos: number = 0) {
|
|
86
|
+
constructor(packetType: TPacketType, buf: Uint8Array, pos: number = 0) {
|
|
87
|
+
this.packetType = packetType;
|
|
61
88
|
this.buf = buf;
|
|
62
89
|
this.pos = pos;
|
|
63
90
|
this.len = buf.length;
|
|
@@ -93,6 +120,37 @@ export class Decoder {
|
|
|
93
120
|
return (msb << 8) | lsb;
|
|
94
121
|
}
|
|
95
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Gets a 4 byte integer from the buffer (for v5)
|
|
125
|
+
* @returns The 32 bit integer value
|
|
126
|
+
*/
|
|
127
|
+
getInt32(): number {
|
|
128
|
+
const msb = this.getInt16();
|
|
129
|
+
const lsb = this.getInt16();
|
|
130
|
+
return (msb << 16) | lsb;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Gets a variable byte integer from the buffer (for v5)
|
|
135
|
+
* its like the length decoder in length.ts but this one works directly on the buffer
|
|
136
|
+
* @returns The decoded variable byte integer
|
|
137
|
+
* @throws {DecoderError} If malformed variable byte integer
|
|
138
|
+
*/
|
|
139
|
+
getVariableByteInteger(): number {
|
|
140
|
+
let num = 0;
|
|
141
|
+
let multiplier = 1;
|
|
142
|
+
let byte;
|
|
143
|
+
do {
|
|
144
|
+
byte = this.getByte();
|
|
145
|
+
num += (byte & 127) * multiplier;
|
|
146
|
+
if (multiplier > 128 * 128 * 128) {
|
|
147
|
+
throw new DecoderError("Malformed Variable Byte Integer");
|
|
148
|
+
}
|
|
149
|
+
multiplier *= 128;
|
|
150
|
+
} while ((byte & 128) !== 0);
|
|
151
|
+
return num;
|
|
152
|
+
}
|
|
153
|
+
|
|
96
154
|
/**
|
|
97
155
|
* Gets a byte array from the buffer
|
|
98
156
|
* @returns A subarray of the buffer
|
|
@@ -110,18 +168,28 @@ export class Decoder {
|
|
|
110
168
|
* Gets a UTF-8 string from the buffer
|
|
111
169
|
* @returns The decoded UTF-8 string
|
|
112
170
|
*/
|
|
113
|
-
|
|
171
|
+
getUTF8String(): string {
|
|
114
172
|
const str = utf8Decoder.decode(this.getByteArray());
|
|
115
173
|
return str;
|
|
116
174
|
}
|
|
117
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Gets a UTF-8 string pair from the buffer (for v5)
|
|
178
|
+
* @returns The decoded UTF-8 pair as [name,value]
|
|
179
|
+
*/
|
|
180
|
+
getUTF8StringPair(): UTF8StringPair {
|
|
181
|
+
const name = utf8Decoder.decode(this.getByteArray());
|
|
182
|
+
const value = utf8Decoder.decode(this.getByteArray());
|
|
183
|
+
return [name, value];
|
|
184
|
+
}
|
|
185
|
+
|
|
118
186
|
/**
|
|
119
187
|
* Gets a topic from the buffer
|
|
120
188
|
* @returns The decoded topic
|
|
121
189
|
* @throws {DecoderError} If topic is invalid
|
|
122
190
|
*/
|
|
123
191
|
getTopic(): Topic {
|
|
124
|
-
const topic = this.
|
|
192
|
+
const topic = this.getUTF8String();
|
|
125
193
|
if (invalidTopic(topic)) {
|
|
126
194
|
throw new DecoderError(
|
|
127
195
|
"Topic must contain valid UTF-8 and contain more than 1 byte and no wildcards",
|
|
@@ -136,7 +204,7 @@ export class Decoder {
|
|
|
136
204
|
* @throws {DecoderError} If topic filter is invalid
|
|
137
205
|
*/
|
|
138
206
|
getTopicFilter(): TopicFilter {
|
|
139
|
-
const topicFilter = this.
|
|
207
|
+
const topicFilter = this.getUTF8String();
|
|
140
208
|
if (invalidTopicFilter(topicFilter)) {
|
|
141
209
|
throw new DecoderError(
|
|
142
210
|
"Topicfilter must contain valid UTF-8 and contain more than 1 byte and valid wildcards",
|
|
@@ -156,6 +224,106 @@ export class Decoder {
|
|
|
156
224
|
return this.buf.subarray(start, end);
|
|
157
225
|
}
|
|
158
226
|
|
|
227
|
+
/**
|
|
228
|
+
* Gets a single property
|
|
229
|
+
* @param id
|
|
230
|
+
* @returns
|
|
231
|
+
*/
|
|
232
|
+
private getProperty(
|
|
233
|
+
id: ValidPropertyNumber,
|
|
234
|
+
): Mqttv5PropertyTypesNoUser {
|
|
235
|
+
switch (propertyToKind[id]) {
|
|
236
|
+
case propertyKind.boolean:
|
|
237
|
+
return !!this.getByte();
|
|
238
|
+
case propertyKind.byte:
|
|
239
|
+
return this.getByte();
|
|
240
|
+
case propertyKind.int16:
|
|
241
|
+
return this.getInt16();
|
|
242
|
+
case propertyKind.int32:
|
|
243
|
+
return this.getInt32();
|
|
244
|
+
case propertyKind.varInt:
|
|
245
|
+
return this.getVariableByteInteger();
|
|
246
|
+
case propertyKind.byteArray:
|
|
247
|
+
return this.getByteArray();
|
|
248
|
+
case propertyKind.utf8string:
|
|
249
|
+
return this.getUTF8String();
|
|
250
|
+
}
|
|
251
|
+
// deno-coverage-ignore
|
|
252
|
+
throw new DecoderError("Invalid property kind");
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Gets all properties from the buffer
|
|
257
|
+
* and validates if they are allowed for this type of packet
|
|
258
|
+
* @param propertySetType
|
|
259
|
+
* @returns
|
|
260
|
+
* @throws {DecoderError} If properties are invalid
|
|
261
|
+
*/
|
|
262
|
+
getProperties<T extends keyof PropsByPacketSetType>(
|
|
263
|
+
propertySetType: T,
|
|
264
|
+
): PropsByPacketSetType[T] {
|
|
265
|
+
const allowedProps: readonly number[] =
|
|
266
|
+
PropertyByPropertySetType[propertySetType];
|
|
267
|
+
const properties = {} as PropsByPacketSetType[T];
|
|
268
|
+
const propLength = this.getVariableByteInteger();
|
|
269
|
+
const endPos = this.pos + propLength;
|
|
270
|
+
const userProps: UserPropertyType = [];
|
|
271
|
+
const subIdents: SubscriptionIdentifiersType = [];
|
|
272
|
+
|
|
273
|
+
while (this.pos < endPos) {
|
|
274
|
+
const id = this.getVariableByteInteger() as ValidPropertyNumber;
|
|
275
|
+
const label = propertyByNumber[id];
|
|
276
|
+
if (
|
|
277
|
+
id === subIdentID && allowedProps.includes(subIdentsID)
|
|
278
|
+
) {
|
|
279
|
+
subIdents.push(this.getVariableByteInteger());
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (!allowedProps.includes(id)) {
|
|
283
|
+
throw new DecoderError(
|
|
284
|
+
`Property type ${label ? label : id} not allowed at byte ${this.pos}`,
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
if (id === userPropID) {
|
|
288
|
+
const stringPair = this.getUTF8StringPair();
|
|
289
|
+
userProps.push(stringPair);
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const value = this.getProperty(id);
|
|
294
|
+
|
|
295
|
+
// deno-lint-ignore no-explicit-any
|
|
296
|
+
if ((properties as any)[label] !== undefined) {
|
|
297
|
+
throw new DecoderError(`Property ${label} only allowed once`);
|
|
298
|
+
} else {
|
|
299
|
+
// deno-lint-ignore no-explicit-any
|
|
300
|
+
(properties as any)[label] = value;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (userProps.length > 0) {
|
|
304
|
+
// deno-lint-ignore no-explicit-any
|
|
305
|
+
(properties as any).userProperty = userProps;
|
|
306
|
+
}
|
|
307
|
+
if (subIdents.length > 0) {
|
|
308
|
+
// deno-lint-ignore no-explicit-any
|
|
309
|
+
(properties as any).subscriptionIdentifiers = subIdents;
|
|
310
|
+
}
|
|
311
|
+
return properties;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Gets a reason code from the buffer
|
|
316
|
+
* @returns The decoded reason code
|
|
317
|
+
* @throws {DecoderError} If reason code is invalid
|
|
318
|
+
*/
|
|
319
|
+
getReasonCode(): TReasonCode {
|
|
320
|
+
const reasonCode = this.getByte();
|
|
321
|
+
if (!isValidReasonCode(this.packetType, reasonCode)) {
|
|
322
|
+
throw new DecoderError("Invalid reason code");
|
|
323
|
+
}
|
|
324
|
+
return reasonCode as TReasonCode;
|
|
325
|
+
}
|
|
326
|
+
|
|
159
327
|
/**
|
|
160
328
|
* Checks if decoder has reached the end of the buffer
|
|
161
329
|
* @returns True if at end, false otherwise
|