@seriousme/opifex 1.6.2 → 1.7.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.
Files changed (128) hide show
  1. package/README.md +6 -7
  2. package/bin/conformanceServer.ts +67 -16
  3. package/bin/demoServer.ts +69 -14
  4. package/bin/mqtt.ts +30 -0
  5. package/client/ConnectionState.ts +12 -0
  6. package/client/client.ts +56 -2
  7. package/client/context.ts +5 -0
  8. package/client/handlers/handleConnack.ts +6 -0
  9. package/client/handlers/handlePacket.ts +7 -0
  10. package/client/handlers/handlePuback.ts +8 -2
  11. package/client/handlers/handlePubcomp.ts +10 -4
  12. package/client/handlers/handlePublish.ts +6 -2
  13. package/client/handlers/handlePubrec.ts +13 -6
  14. package/client/handlers/handlePubrel.ts +16 -6
  15. package/client/handlers/handleSuback.ts +9 -6
  16. package/client/handlers/handleUnsuback.ts +10 -3
  17. package/client/store/memoryStore.ts +25 -0
  18. package/client/store/store.ts +39 -0
  19. package/deno/tcpServer.test.ts +137 -2
  20. package/node/tcpServer.test.ts +61 -6
  21. package/node/tcpServer.ts +9 -2
  22. package/node/wrapNodeSocket.ts +13 -2
  23. package/package.json +13 -3
  24. package/persistence/memory/memoryPersistence.test.ts +2 -1
  25. package/persistence/memory/memoryPersistence.ts +1 -0
  26. package/persistence/store.ts +1 -0
  27. package/server/handlers/handleConnect.ts +49 -6
  28. package/server/handlers/handleDisconnect.ts +5 -0
  29. package/server/handlers/handlePacket.ts +7 -0
  30. package/server/handlers/handlePingreq.ts +6 -0
  31. package/server/handlers/handlePuback.ts +9 -2
  32. package/server/handlers/handlePubcomp.ts +8 -3
  33. package/server/handlers/handlePublish.ts +13 -0
  34. package/server/handlers/handlePubrec.ts +11 -3
  35. package/server/handlers/handlePubrel.ts +12 -4
  36. package/server/handlers/handleSubscribe.ts +28 -5
  37. package/server/handlers/handleUnsubscribe.ts +6 -0
  38. package/utils/asyncQueue.ts +2 -1
  39. package/utils/nextTick.ts +13 -1
  40. package/.github/workflows/closeStale.yml +0 -15
  41. package/.github/workflows/codeql-analysis.yml +0 -71
  42. package/.github/workflows/deno-ci.yml +0 -16
  43. package/.github/workflows/nodejs-ci.yml +0 -23
  44. package/.github/workflows/publish.yml +0 -16
  45. package/.github/workflows/update-license-year.sh +0 -14
  46. package/.github/workflows/update-license-year.yml +0 -13
  47. package/CHANGELOG.md +0 -74
  48. package/deno.json +0 -15
  49. package/deno.lock +0 -34
  50. package/dist/bin/conformanceServer.js +0 -51
  51. package/dist/bin/demoServer.js +0 -46
  52. package/dist/bin/mqtt.js +0 -227
  53. package/dist/client/ConnectionState.js +0 -7
  54. package/dist/client/client.js +0 -132
  55. package/dist/client/context.js +0 -148
  56. package/dist/client/deps.js +0 -5
  57. package/dist/client/handlers/handleConnack.js +0 -18
  58. package/dist/client/handlers/handlePacket.js +0 -50
  59. package/dist/client/handlers/handlePuback.js +0 -6
  60. package/dist/client/handlers/handlePubcomp.js +0 -9
  61. package/dist/client/handlers/handlePublish.js +0 -28
  62. package/dist/client/handlers/handlePubrec.js +0 -17
  63. package/dist/client/handlers/handlePubrel.js +0 -19
  64. package/dist/client/handlers/handleSuback.js +0 -9
  65. package/dist/client/handlers/handleUnsuback.js +0 -7
  66. package/dist/client/mod.js +0 -5
  67. package/dist/client/store/deps.js +0 -1
  68. package/dist/client/store/memoryStore.js +0 -36
  69. package/dist/client/store/store.js +0 -1
  70. package/dist/mqttConn/mqttConn.js +0 -104
  71. package/dist/mqttPacket/AuthenticationResult.js +0 -16
  72. package/dist/mqttPacket/BitMask.js +0 -10
  73. package/dist/mqttPacket/PacketType.js +0 -18
  74. package/dist/mqttPacket/connack.js +0 -27
  75. package/dist/mqttPacket/connect.js +0 -115
  76. package/dist/mqttPacket/decoder.js +0 -89
  77. package/dist/mqttPacket/disconnect.js +0 -14
  78. package/dist/mqttPacket/encoder.js +0 -56
  79. package/dist/mqttPacket/length.js +0 -43
  80. package/dist/mqttPacket/mod.js +0 -76
  81. package/dist/mqttPacket/pingreq.js +0 -15
  82. package/dist/mqttPacket/pingres.js +0 -14
  83. package/dist/mqttPacket/puback.js +0 -20
  84. package/dist/mqttPacket/pubcomp.js +0 -20
  85. package/dist/mqttPacket/publish.js +0 -51
  86. package/dist/mqttPacket/pubrec.js +0 -20
  87. package/dist/mqttPacket/pubrel.js +0 -20
  88. package/dist/mqttPacket/suback.js +0 -29
  89. package/dist/mqttPacket/subscribe.js +0 -52
  90. package/dist/mqttPacket/types.js +0 -1
  91. package/dist/mqttPacket/unsuback.js +0 -20
  92. package/dist/mqttPacket/unsubscribe.js +0 -36
  93. package/dist/mqttPacket/validators.js +0 -15
  94. package/dist/node/tcpClient.js +0 -81
  95. package/dist/node/tcpServer.js +0 -43
  96. package/dist/node/wrapNodeSocket.js +0 -47
  97. package/dist/persistence/deps.js +0 -3
  98. package/dist/persistence/memory/memoryPersistence.js +0 -117
  99. package/dist/persistence/persistence.js +0 -1
  100. package/dist/persistence/store.js +0 -1
  101. package/dist/server/context.js +0 -100
  102. package/dist/server/deps.js +0 -5
  103. package/dist/server/handlers/handleConnect.js +0 -46
  104. package/dist/server/handlers/handleDisconnect.js +0 -4
  105. package/dist/server/handlers/handlePacket.js +0 -58
  106. package/dist/server/handlers/handlePingreq.js +0 -6
  107. package/dist/server/handlers/handlePuback.js +0 -8
  108. package/dist/server/handlers/handlePubcomp.js +0 -8
  109. package/dist/server/handlers/handlePublish.js +0 -41
  110. package/dist/server/handlers/handlePubrec.js +0 -15
  111. package/dist/server/handlers/handlePubrel.js +0 -18
  112. package/dist/server/handlers/handleSubscribe.js +0 -33
  113. package/dist/server/handlers/handleUnsubscribe.js +0 -12
  114. package/dist/server/mod.js +0 -7
  115. package/dist/server/server.js +0 -47
  116. package/dist/socket/socket.js +0 -36
  117. package/dist/timer/timer.js +0 -40
  118. package/dist/trie/trie.js +0 -95
  119. package/dist/tsconfig.tsbuildinfo +0 -1
  120. package/dist/utils/args.js +0 -75
  121. package/dist/utils/assert.js +0 -20
  122. package/dist/utils/asyncQueue.js +0 -67
  123. package/dist/utils/deferred.js +0 -14
  124. package/dist/utils/logger.js +0 -58
  125. package/dist/utils/mod.js +0 -11
  126. package/dist/utils/nextTick.js +0 -6
  127. package/dist/utils/platform.js +0 -7
  128. package/tsconfig.json +0 -22
@@ -1,7 +0,0 @@
1
- // The UNSUBACK Packet is sent by the Server to the Client to confirm receipt
2
- // of an UNSUBSCRIBE Packet.
3
- export function handleUnsuback(ctx, packet) {
4
- const id = packet.id;
5
- ctx.store.pendingOutgoing.delete(id);
6
- ctx.receiveUnsuback(id);
7
- }
@@ -1,5 +0,0 @@
1
- /**
2
- * This module provides an MQTT Client interface see the /bin folder for examples
3
- * @module
4
- */
5
- export { Client, DEFAULT_URL } from "./client.js";
@@ -1 +0,0 @@
1
- export { assert } from "../../utils/mod.js";
@@ -1,36 +0,0 @@
1
- import { assert } from "./deps.js";
2
- import { maxPacketId, } from "./store.js";
3
- export class MemoryStore {
4
- packetId;
5
- pendingIncoming;
6
- pendingOutgoing;
7
- pendingAckOutgoing;
8
- constructor() {
9
- this.packetId = 0;
10
- this.pendingIncoming = new Map();
11
- this.pendingOutgoing = new Map();
12
- this.pendingAckOutgoing = new Map();
13
- }
14
- nextId() {
15
- const currentId = this.packetId;
16
- do {
17
- this.packetId++;
18
- if (this.packetId > maxPacketId) {
19
- this.packetId = 1;
20
- }
21
- } while ((this.pendingIncoming.has(this.packetId) ||
22
- this.pendingOutgoing.has(this.packetId) ||
23
- this.pendingAckOutgoing.has(this.packetId)) &&
24
- this.packetId !== currentId);
25
- assert(this.packetId !== currentId, "No unused packetId available");
26
- return this.packetId;
27
- }
28
- async *pendingOutgoingPackets() {
29
- for (const [_id, packet] of this.pendingAckOutgoing) {
30
- yield packet;
31
- }
32
- for (const [_id, packet] of this.pendingOutgoing) {
33
- yield packet;
34
- }
35
- }
36
- }
@@ -1 +0,0 @@
1
- export const maxPacketId = 0xffff;
@@ -1,104 +0,0 @@
1
- import { decodePayload, encode, getLengthDecoder, } from "../mqttPacket/mod.js";
2
- import { assert } from "../utils/mod.js";
3
- import { Conn } from "../socket/socket.js";
4
- export const MqttConnError = {
5
- invalidPacket: "Invalid Packet",
6
- packetTooLarge: "Packet too large",
7
- UnexpectedEof: "Unexpected EOF",
8
- };
9
- async function readByte(conn) {
10
- const buf = new Uint8Array(1);
11
- const bytesRead = await conn.read(buf);
12
- assert(bytesRead !== null, MqttConnError.UnexpectedEof);
13
- assert(bytesRead !== 0, MqttConnError.UnexpectedEof);
14
- return buf[0];
15
- }
16
- async function readFull(conn, buf) {
17
- let bytesRead = 0;
18
- while (bytesRead < buf.length) {
19
- const read = await conn.read(buf.subarray(bytesRead));
20
- assert(read !== null, MqttConnError.UnexpectedEof);
21
- assert(read !== 0, MqttConnError.UnexpectedEof);
22
- bytesRead += read;
23
- }
24
- }
25
- /** Read MQTT packet
26
- * @throws `Error` if packet is invalid
27
- */
28
- export async function readPacket(conn, maxPacketSize) {
29
- // fixed header is 1 byte of type + flags
30
- // + a maximum of 4 bytes to encode the remaining length
31
- const decodeLength = getLengthDecoder();
32
- const firstByte = await readByte(conn);
33
- let result;
34
- do {
35
- const byte = await readByte(conn);
36
- result = decodeLength(byte);
37
- } while (!result.done);
38
- const remainingLength = result.length;
39
- assert(remainingLength < maxPacketSize - 1, MqttConnError.packetTooLarge);
40
- const packetBuf = new Uint8Array(remainingLength);
41
- // read the rest of the packet
42
- await readFull(conn, packetBuf);
43
- const packet = decodePayload(firstByte, packetBuf);
44
- assert(packet !== null, MqttConnError.UnexpectedEof);
45
- return packet;
46
- }
47
- export class MqttConn {
48
- conn;
49
- maxPacketSize;
50
- _reason = undefined;
51
- _isClosed = false;
52
- constructor({ conn, maxPacketSize, }) {
53
- this.conn = new Conn(conn);
54
- this.maxPacketSize = maxPacketSize || 2 * 1024 * 1024;
55
- }
56
- get reason() {
57
- return this._reason;
58
- }
59
- async *[Symbol.asyncIterator]() {
60
- while (!this._isClosed) {
61
- try {
62
- yield await readPacket(this.conn, this.maxPacketSize);
63
- }
64
- catch (err) {
65
- if (err instanceof Error) {
66
- if (err.name === "PartialReadError") {
67
- err.message = MqttConnError.UnexpectedEof;
68
- }
69
- this._reason = err.message;
70
- }
71
- // packet too large, malformed packet or connection closed
72
- this.close();
73
- break;
74
- }
75
- }
76
- }
77
- async send(data) {
78
- try {
79
- await this.conn.write(encode(data));
80
- }
81
- catch (err) {
82
- if (err instanceof Error) {
83
- this._reason = err.message;
84
- }
85
- this.close();
86
- }
87
- }
88
- get isClosed() {
89
- return this._isClosed;
90
- }
91
- close() {
92
- if (this.isClosed)
93
- return;
94
- try {
95
- this.conn.close();
96
- }
97
- catch (e) {
98
- console.error(e);
99
- }
100
- finally {
101
- this._isClosed = true;
102
- }
103
- }
104
- }
@@ -1,16 +0,0 @@
1
- /**
2
- * Possible MQTT authentication results
3
- */
4
- export const AuthenticationResult = {
5
- ok: 0,
6
- unacceptableProtocol: 1,
7
- rejectedUsername: 2,
8
- serverUnavailable: 3,
9
- badUsernameOrPassword: 4,
10
- notAuthorized: 5,
11
- };
12
- /**
13
- * Reverse lookup for AuthenticationResult
14
- */
15
- export const AuthenticationResultByNumber = Object
16
- .fromEntries(Object.entries(AuthenticationResult).map(([k, v]) => [v, k]));
@@ -1,10 +0,0 @@
1
- export const BitMask = {
2
- bit0: 2 ** 0,
3
- bit1: 2 ** 1,
4
- bit2: 2 ** 2,
5
- bit3: 2 ** 3,
6
- bit4: 2 ** 4,
7
- bit5: 2 ** 5,
8
- bit6: 2 ** 6,
9
- bit7: 2 ** 7,
10
- };
@@ -1,18 +0,0 @@
1
- export const PacketType = {
2
- reserved: 0,
3
- connect: 1,
4
- connack: 2,
5
- publish: 3,
6
- puback: 4,
7
- pubrec: 5,
8
- pubrel: 6,
9
- pubcomp: 7,
10
- subscribe: 8,
11
- suback: 9,
12
- unsubscribe: 10,
13
- unsuback: 11,
14
- pingreq: 12,
15
- pingres: 13,
16
- disconnect: 14,
17
- };
18
- export const PacketNameByType = Object.fromEntries(Object.entries(PacketType).map(([k, v]) => [v, k]));
@@ -1,27 +0,0 @@
1
- import { PacketType } from "./PacketType.js";
2
- import { BitMask } from "./BitMask.js";
3
- import { booleanFlag, Decoder, DecoderError } from "./decoder.js";
4
- import { AuthenticationResultByNumber } from "./AuthenticationResult.js";
5
- export const connack = {
6
- encode(packet) {
7
- const flags = 0;
8
- return {
9
- flags,
10
- bytes: [packet.sessionPresent ? 1 : 0, packet.returnCode || 0],
11
- };
12
- },
13
- decode(buffer, _flags) {
14
- const decoder = new Decoder(buffer);
15
- const sessionPresent = booleanFlag(decoder.getByte(), BitMask.bit0);
16
- const returnCode = decoder.getByte();
17
- decoder.done();
18
- if (!AuthenticationResultByNumber[returnCode]) {
19
- throw new DecoderError("Invalid return code");
20
- }
21
- return {
22
- type: PacketType.connack,
23
- sessionPresent,
24
- returnCode,
25
- };
26
- },
27
- };
@@ -1,115 +0,0 @@
1
- import { PacketType } from "./PacketType.js";
2
- import { BitMask } from "./BitMask.js";
3
- import { Encoder } from "./encoder.js";
4
- import { booleanFlag, Decoder, DecoderError, hasEmptyFlags, } from "./decoder.js";
5
- function invalidProtocolName(version, name) {
6
- if (version === 4 && name !== "MQTT") {
7
- return true;
8
- }
9
- return false;
10
- }
11
- export const connect = {
12
- encode(packet) {
13
- const flags = 0;
14
- const protocolLevel = 4;
15
- const protocolName = protocolLevel === 4 ? "MQTT" : "MQIsdp";
16
- const clientId = packet.clientId || "";
17
- const usernameFlag = !!packet.username;
18
- const passwordFlag = !!packet.password;
19
- const willRetain = !!packet.will?.retain;
20
- const willQoS = packet.will?.qos || 0;
21
- const willFlag = !!packet.will;
22
- const cleanSession = packet.clean !== false;
23
- const connectFlags = (usernameFlag ? BitMask.bit7 : 0) +
24
- (passwordFlag ? BitMask.bit6 : 0) +
25
- (willRetain ? BitMask.bit5 : 0) +
26
- (willQoS & 2 ? BitMask.bit4 : 0) +
27
- (willQoS & 1 ? BitMask.bit3 : 0) +
28
- (willFlag ? BitMask.bit2 : 0) +
29
- (cleanSession ? BitMask.bit1 : 0);
30
- const keepAlive = packet.keepAlive || 0;
31
- const encoder = new Encoder();
32
- encoder
33
- .setUtf8String(protocolName)
34
- .setByte(protocolLevel)
35
- .setByte(connectFlags)
36
- .setInt16(keepAlive)
37
- .setUtf8String(clientId);
38
- if (packet.will) {
39
- encoder.setTopic(packet.will.topic).setByteArray(packet.will.payload);
40
- }
41
- if (packet.username) {
42
- encoder.setUtf8String(packet.username);
43
- }
44
- if (packet.password) {
45
- encoder.setByteArray(packet.password);
46
- }
47
- return { flags, bytes: encoder.done() };
48
- },
49
- decode(buffer, flags) {
50
- const decoder = new Decoder(buffer);
51
- const protocolName = decoder.getUtf8String();
52
- const protocolLevel = decoder.getByte();
53
- if (invalidProtocolName(protocolLevel, protocolName)) {
54
- throw new DecoderError("Invalid protocol name");
55
- }
56
- const connectFlags = decoder.getByte();
57
- const usernameFlag = booleanFlag(connectFlags, BitMask.bit7);
58
- const passwordFlag = booleanFlag(connectFlags, BitMask.bit6);
59
- const willRetain = booleanFlag(connectFlags, BitMask.bit5);
60
- const willQoS = (connectFlags & (BitMask.bit4 + BitMask.bit3)) >> 3;
61
- const willFlag = booleanFlag(connectFlags, BitMask.bit2);
62
- const cleanSession = booleanFlag(connectFlags, BitMask.bit1);
63
- const reservedBit = booleanFlag(connectFlags, BitMask.bit0);
64
- hasEmptyFlags(flags);
65
- // The Server MUST validate that the reserved flag in the CONNECT Control Packet
66
- // is set to zero and disconnect the Client if it is not zero [MQTT-3.1.2-3].
67
- if (reservedBit) {
68
- throw new DecoderError("Invalid reserved bit");
69
- }
70
- if (willQoS !== 0 && willQoS !== 1 && willQoS !== 2) {
71
- throw new DecoderError("Invalid will qos");
72
- }
73
- const keepAlive = decoder.getInt16();
74
- const clientId = decoder.getUtf8String();
75
- let willTopic;
76
- let willPayload;
77
- if (willFlag) {
78
- willTopic = decoder.getTopic();
79
- willPayload = decoder.getByteArray();
80
- }
81
- let username;
82
- let password;
83
- if (usernameFlag) {
84
- username = decoder.getUtf8String();
85
- }
86
- if (passwordFlag) {
87
- password = decoder.getByteArray();
88
- }
89
- decoder.done();
90
- if (!willFlag && (willQoS !== 0 || willRetain === true)) {
91
- throw new DecoderError("Will QoS must be 0 and Will retain to false when Will flag is false");
92
- }
93
- if (clientId.length === 0 && cleanSession === false) {
94
- throw new DecoderError("Clean session must be true if clientID is empty");
95
- }
96
- return {
97
- type: PacketType.connect,
98
- protocolName: protocolName,
99
- protocolLevel,
100
- clientId: clientId,
101
- username: username ? username : undefined,
102
- password: password ? password : undefined,
103
- will: willFlag
104
- ? {
105
- topic: willTopic || "",
106
- payload: willPayload || Uint8Array.from([0]),
107
- retain: willRetain,
108
- qos: willQoS,
109
- }
110
- : undefined,
111
- clean: cleanSession,
112
- keepAlive,
113
- };
114
- },
115
- };
@@ -1,89 +0,0 @@
1
- import { invalidTopic, invalidTopicFilter } from "./validators.js";
2
- const utf8Decoder = new TextDecoder("utf-8");
3
- export function booleanFlag(byte, mask) {
4
- return !!(byte & mask);
5
- }
6
- export function isEmptyBuf(buf) {
7
- if (buf.length > 0) {
8
- throw new DecoderError("Packet too long");
9
- }
10
- }
11
- export function hasEmptyFlags(flags) {
12
- if (flags !== 0) {
13
- throw new DecoderError("Invalid fixed header flags");
14
- }
15
- }
16
- export class DecoderError extends Error {
17
- constructor(message) {
18
- super(message);
19
- this.name = "DecoderError";
20
- }
21
- }
22
- export class Decoder {
23
- buf;
24
- pos;
25
- len;
26
- constructor(buf, pos = 0) {
27
- this.buf = buf;
28
- this.pos = pos;
29
- this.len = buf.length;
30
- }
31
- checkpos(pos) {
32
- if (pos > this.len) {
33
- throw new DecoderError("Packet too short");
34
- }
35
- }
36
- getByte() {
37
- this.checkpos(this.pos);
38
- return this.buf[this.pos++];
39
- }
40
- getInt16() {
41
- const msb = this.getByte();
42
- const lsb = this.getByte();
43
- return (msb << 8) | lsb;
44
- }
45
- getByteArray() {
46
- const len = this.getInt16();
47
- const start = this.pos;
48
- const end = this.pos + len;
49
- this.pos = end;
50
- this.checkpos(end);
51
- return this.buf.subarray(start, end);
52
- }
53
- getUtf8String() {
54
- const str = utf8Decoder.decode(this.getByteArray());
55
- return str;
56
- }
57
- getTopic() {
58
- const topic = this.getUtf8String();
59
- if (invalidTopic(topic)) {
60
- throw new DecoderError("Topic must contain valid UTF-8 and contain more than 1 byte and no wildcards");
61
- }
62
- return topic;
63
- }
64
- getTopicFilter() {
65
- const topicFilter = this.getUtf8String();
66
- if (invalidTopicFilter(topicFilter)) {
67
- throw new DecoderError("Topicfilter must contain valid UTF-8 and contain more than 1 byte and valid wildcards");
68
- }
69
- return topicFilter;
70
- }
71
- getRemainder() {
72
- const start = this.pos;
73
- const end = this.len;
74
- this.pos = end;
75
- return this.buf.subarray(start, end);
76
- }
77
- atEnd() {
78
- if (this.len === this.pos) {
79
- return true;
80
- }
81
- return false;
82
- }
83
- done() {
84
- if (this.atEnd()) {
85
- return true;
86
- }
87
- throw new DecoderError("Packet too long");
88
- }
89
- }
@@ -1,14 +0,0 @@
1
- import { PacketType } from "./PacketType.js";
2
- import { isEmptyBuf } from "./decoder.js";
3
- export const disconnect = {
4
- encode(_packet) {
5
- const flags = 0;
6
- return { flags, bytes: [] };
7
- },
8
- decode(buffer, _flags) {
9
- isEmptyBuf(buffer);
10
- return {
11
- type: PacketType.disconnect,
12
- };
13
- },
14
- };
@@ -1,56 +0,0 @@
1
- const utf8Encoder = new TextEncoder();
2
- import { invalidTopic, invalidTopicFilter } from "./validators.js";
3
- export class EncoderError extends Error {
4
- constructor(message) {
5
- super(message);
6
- this.name = "EncoderError";
7
- }
8
- }
9
- export class Encoder {
10
- buffer;
11
- constructor() {
12
- this.buffer = [];
13
- }
14
- setByte(value) {
15
- this.buffer.push(value);
16
- return this;
17
- }
18
- setInt16(value) {
19
- this.setByte(value >> 8);
20
- this.setByte(value & 0xff);
21
- return this;
22
- }
23
- setByteArray(value) {
24
- if (value.length > 0xffff) {
25
- throw new EncoderError("More than 0xffff bytes of data");
26
- }
27
- this.setInt16(value.length);
28
- this.buffer.push(...value);
29
- return this;
30
- }
31
- setUtf8String(value) {
32
- this.setByteArray(utf8Encoder.encode(value));
33
- return this;
34
- }
35
- setTopic(value) {
36
- if (invalidTopic(value)) {
37
- throw new EncoderError("Topic must contain valid UTF-8 and contain more than 1 byte and no wildcards");
38
- }
39
- this.setUtf8String(value);
40
- return this;
41
- }
42
- setTopicFilter(value) {
43
- if (invalidTopicFilter(value)) {
44
- throw new EncoderError("Topicfilter must contain valid UTF-8 and contain more than 1 byte and valid wildcards");
45
- }
46
- this.setUtf8String(value);
47
- return this;
48
- }
49
- setRemainder(value) {
50
- this.buffer.push(...value);
51
- return this;
52
- }
53
- done() {
54
- return this.buffer;
55
- }
56
- }
@@ -1,43 +0,0 @@
1
- export function encodeLength(n) {
2
- const output = [];
3
- let x = n;
4
- do {
5
- let encodedByte = x % 0x80;
6
- x = Math.floor(x / 0x80);
7
- if (x > 0) {
8
- encodedByte = encodedByte | 0x80;
9
- }
10
- output.push(encodedByte);
11
- } while (x > 0);
12
- if (output.length > 4) {
13
- throw Error("length encoding failed");
14
- }
15
- return output;
16
- }
17
- export function decodeLength(buf, start) {
18
- const decode = getLengthDecoder();
19
- const lenBuf = buf.subarray(start);
20
- for (const byte of lenBuf) {
21
- const { done, length, numLengthBytes } = decode(byte);
22
- if (done) {
23
- return { length, numLengthBytes };
24
- }
25
- }
26
- throw Error("length decoding failed");
27
- }
28
- export function getLengthDecoder() {
29
- let numLengthBytes = 1;
30
- let length = 0;
31
- let multiplier = 1;
32
- return function addLengthByte(encodedByte) {
33
- length += (encodedByte & 0x7f) * multiplier;
34
- multiplier *= 0x80;
35
- if ((encodedByte & 0x80) === 0) {
36
- return { done: true, length, numLengthBytes };
37
- }
38
- if (numLengthBytes++ >= 4) {
39
- throw Error("length decoding failed");
40
- }
41
- return { done: false, length, numLengthBytes };
42
- };
43
- }
@@ -1,76 +0,0 @@
1
- /**
2
- * This module provides the encoding and decoding of MQTT packets
3
- * it is used by the server and client modules
4
- * @module
5
- */
6
- import { PacketNameByType, PacketType } from "./PacketType.js";
7
- import { invalidTopic, invalidTopicFilter, invalidUTF8 } from "./validators.js";
8
- import { decodeLength, encodeLength } from "./length.js";
9
- import { connect } from "./connect.js";
10
- import { connack } from "./connack.js";
11
- import { AuthenticationResult, AuthenticationResultByNumber, } from "./AuthenticationResult.js";
12
- import { publish } from "./publish.js";
13
- import { puback } from "./puback.js";
14
- import { pubrec } from "./pubrec.js";
15
- import { pubrel } from "./pubrel.js";
16
- import { pubcomp } from "./pubcomp.js";
17
- import { subscribe } from "./subscribe.js";
18
- import { suback } from "./suback.js";
19
- import { unsubscribe } from "./unsubscribe.js";
20
- import { unsuback } from "./unsuback.js";
21
- import { pingreq } from "./pingreq.js";
22
- import { pingres } from "./pingres.js";
23
- import { disconnect } from "./disconnect.js";
24
- import { DecoderError } from "./decoder.js";
25
- export { AuthenticationResult, AuthenticationResultByNumber, decodeLength, encodeLength, invalidTopic, invalidTopicFilter, invalidUTF8, PacketNameByType, PacketType, };
26
- export const packetsByType = [
27
- null,
28
- connect, // 1
29
- connack, // 2
30
- publish, // 3
31
- puback, // 4
32
- pubrec, // 5
33
- pubrel, // 6
34
- pubcomp, // 7
35
- subscribe, // 8
36
- suback, // 9
37
- unsubscribe, // 10
38
- unsuback, // 11
39
- pingreq, // 12
40
- pingres, // 13
41
- disconnect, // 14
42
- ];
43
- export function encode(packet) {
44
- const packetType = packet.type;
45
- // deno-lint-ignore no-explicit-any
46
- const pkt = packet;
47
- const encoded = packetsByType[packetType]?.encode(pkt);
48
- if (!encoded) {
49
- throw Error("Packet encoding failed");
50
- }
51
- const { flags, bytes } = encoded;
52
- return Uint8Array.from([
53
- (packetType << 4) | flags,
54
- ...encodeLength(bytes.length),
55
- ...bytes,
56
- ]);
57
- }
58
- export function decodePayload(firstByte, buffer) {
59
- const packetType = firstByte >> 4;
60
- const flags = firstByte & 0x0f;
61
- const packet = packetsByType[packetType]?.decode(buffer, flags);
62
- if (packet !== undefined) {
63
- return packet;
64
- }
65
- throw new Error("packet decoding failed");
66
- }
67
- export function decode(buffer) {
68
- if (buffer.length < 2) {
69
- throw new DecoderError("Packet decoding failed");
70
- }
71
- const { length, numLengthBytes } = decodeLength(buffer, 1);
72
- const start = numLengthBytes + 1;
73
- const end = start + length;
74
- return decodePayload(buffer[0], buffer.subarray(start, end));
75
- }
76
- export { getLengthDecoder } from "../mqttPacket/length.js";
@@ -1,15 +0,0 @@
1
- import { PacketType } from "./PacketType.js";
2
- import { hasEmptyFlags, isEmptyBuf } from "./decoder.js";
3
- export const pingreq = {
4
- encode(_packet) {
5
- const flags = 0;
6
- return { flags, bytes: [] };
7
- },
8
- decode(buffer, flags) {
9
- hasEmptyFlags(flags);
10
- isEmptyBuf(buffer);
11
- return {
12
- type: PacketType.pingreq,
13
- };
14
- },
15
- };
@@ -1,14 +0,0 @@
1
- import { PacketType } from "./PacketType.js";
2
- import { isEmptyBuf } from "./decoder.js";
3
- export const pingres = {
4
- encode(_packet) {
5
- const flags = 0;
6
- return { flags, bytes: [] };
7
- },
8
- decode(buffer) {
9
- isEmptyBuf(buffer);
10
- return {
11
- type: PacketType.pingres,
12
- };
13
- },
14
- };
@@ -1,20 +0,0 @@
1
- import { PacketType } from "./PacketType.js";
2
- import { Decoder } from "./decoder.js";
3
- import { Encoder } from "./encoder.js";
4
- export const puback = {
5
- encode(packet) {
6
- const flags = 0;
7
- const encoder = new Encoder();
8
- encoder.setInt16(packet.id);
9
- return { flags, bytes: encoder.done() };
10
- },
11
- decode(buffer) {
12
- const decoder = new Decoder(buffer);
13
- const id = decoder.getInt16();
14
- decoder.done();
15
- return {
16
- type: PacketType.puback,
17
- id,
18
- };
19
- },
20
- };