@seriousme/opifex 1.6.3 → 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 (91) hide show
  1. package/package.json +12 -2
  2. package/.github/dependabot.yml +0 -7
  3. package/.github/workflows/closeStale.yml +0 -15
  4. package/.github/workflows/codeql-analysis.yml +0 -71
  5. package/.github/workflows/deno-ci.yml +0 -16
  6. package/.github/workflows/nodejs-ci.yml +0 -23
  7. package/.github/workflows/publish.yml +0 -16
  8. package/.github/workflows/update-license-year.sh +0 -14
  9. package/.github/workflows/update-license-year.yml +0 -13
  10. package/CHANGELOG.md +0 -80
  11. package/deno.json +0 -16
  12. package/deno.lock +0 -34
  13. package/dist/bin/conformanceServer.js +0 -97
  14. package/dist/bin/demoServer.js +0 -96
  15. package/dist/bin/mqtt.js +0 -256
  16. package/dist/client/ConnectionState.js +0 -16
  17. package/dist/client/client.js +0 -187
  18. package/dist/client/context.js +0 -152
  19. package/dist/client/deps.js +0 -5
  20. package/dist/client/handlers/handleConnack.js +0 -24
  21. package/dist/client/handlers/handlePacket.js +0 -57
  22. package/dist/client/handlers/handlePuback.js +0 -13
  23. package/dist/client/handlers/handlePubcomp.js +0 -16
  24. package/dist/client/handlers/handlePublish.js +0 -33
  25. package/dist/client/handlers/handlePubrec.js +0 -26
  26. package/dist/client/handlers/handlePubrel.js +0 -31
  27. package/dist/client/handlers/handleSuback.js +0 -14
  28. package/dist/client/handlers/handleUnsuback.js +0 -15
  29. package/dist/client/mod.js +0 -5
  30. package/dist/client/store/deps.js +0 -1
  31. package/dist/client/store/memoryStore.js +0 -58
  32. package/dist/client/store/store.js +0 -4
  33. package/dist/mqttConn/mqttConn.js +0 -104
  34. package/dist/mqttPacket/AuthenticationResult.js +0 -16
  35. package/dist/mqttPacket/BitMask.js +0 -10
  36. package/dist/mqttPacket/PacketType.js +0 -18
  37. package/dist/mqttPacket/connack.js +0 -27
  38. package/dist/mqttPacket/connect.js +0 -115
  39. package/dist/mqttPacket/decoder.js +0 -89
  40. package/dist/mqttPacket/disconnect.js +0 -14
  41. package/dist/mqttPacket/encoder.js +0 -56
  42. package/dist/mqttPacket/length.js +0 -43
  43. package/dist/mqttPacket/mod.js +0 -76
  44. package/dist/mqttPacket/pingreq.js +0 -15
  45. package/dist/mqttPacket/pingres.js +0 -14
  46. package/dist/mqttPacket/puback.js +0 -20
  47. package/dist/mqttPacket/pubcomp.js +0 -20
  48. package/dist/mqttPacket/publish.js +0 -51
  49. package/dist/mqttPacket/pubrec.js +0 -20
  50. package/dist/mqttPacket/pubrel.js +0 -20
  51. package/dist/mqttPacket/suback.js +0 -29
  52. package/dist/mqttPacket/subscribe.js +0 -52
  53. package/dist/mqttPacket/types.js +0 -1
  54. package/dist/mqttPacket/unsuback.js +0 -20
  55. package/dist/mqttPacket/unsubscribe.js +0 -36
  56. package/dist/mqttPacket/validators.js +0 -15
  57. package/dist/node/tcpClient.js +0 -81
  58. package/dist/node/tcpServer.js +0 -50
  59. package/dist/node/wrapNodeSocket.js +0 -56
  60. package/dist/persistence/deps.js +0 -3
  61. package/dist/persistence/memory/memoryPersistence.js +0 -118
  62. package/dist/persistence/persistence.js +0 -1
  63. package/dist/persistence/store.js +0 -1
  64. package/dist/server/context.js +0 -100
  65. package/dist/server/deps.js +0 -5
  66. package/dist/server/handlers/handleConnect.js +0 -80
  67. package/dist/server/handlers/handleDisconnect.js +0 -9
  68. package/dist/server/handlers/handlePacket.js +0 -65
  69. package/dist/server/handlers/handlePingreq.js +0 -11
  70. package/dist/server/handlers/handlePuback.js +0 -16
  71. package/dist/server/handlers/handlePubcomp.js +0 -14
  72. package/dist/server/handlers/handlePublish.js +0 -54
  73. package/dist/server/handlers/handlePubrec.js +0 -23
  74. package/dist/server/handlers/handlePubrel.js +0 -27
  75. package/dist/server/handlers/handleSubscribe.js +0 -56
  76. package/dist/server/handlers/handleUnsubscribe.js +0 -18
  77. package/dist/server/mod.js +0 -7
  78. package/dist/server/server.js +0 -47
  79. package/dist/socket/socket.js +0 -36
  80. package/dist/timer/timer.js +0 -40
  81. package/dist/trie/trie.js +0 -95
  82. package/dist/tsconfig.tsbuildinfo +0 -1
  83. package/dist/utils/args.js +0 -75
  84. package/dist/utils/assert.js +0 -20
  85. package/dist/utils/asyncQueue.js +0 -69
  86. package/dist/utils/deferred.js +0 -14
  87. package/dist/utils/logger.js +0 -58
  88. package/dist/utils/mod.js +0 -11
  89. package/dist/utils/nextTick.js +0 -18
  90. package/dist/utils/platform.js +0 -7
  91. package/tsconfig.json +0 -22
package/dist/bin/mqtt.js DELETED
@@ -1,256 +0,0 @@
1
- #!/usr/bin/env -S node --experimental-strip-types
2
- /**
3
- * @fileoverview MQTT command line interface that provides publish and subscribe functionality
4
- * @module mqtt-cli
5
- *
6
- * @description
7
- * This module implements a command line interface for MQTT operations:
8
- * - Publish messages to an MQTT broker
9
- * - Subscribe to topics on an MQTT broker
10
- *
11
- * Features:
12
- * - TLS support with custom certificates
13
- * - Authentication with username/password
14
- * - Configurable QoS levels (0-2)
15
- * - Message retention
16
- * - Session persistence
17
- * - Custom client IDs
18
- *
19
- * @example
20
- * # Publish a message
21
- * mqtt publish -t topic -m message
22
- *
23
- * # Subscribe to a topic
24
- * mqtt subscribe -t topic
25
- *
26
- * @requires node
27
- * @requires ../client/mod.ts
28
- * @requires ../node/tcpClient.ts
29
- * @requires ../utils/mod.ts
30
- */
31
- import { DEFAULT_URL } from "../client/mod.js";
32
- import { getFileData, TcpClient } from "../node/tcpClient.js";
33
- import { getArgs, logger, LogLevel, parseArgs } from "../utils/mod.js";
34
- const client = new TcpClient();
35
- const encoder = new TextEncoder();
36
- const decoder = new TextDecoder();
37
- logger.level(LogLevel.info);
38
- const MQTTHelp = `MQTT command line interface, available commands are:
39
-
40
- * publish publish a message to the broker
41
- * subscribe subscribe for updates from the broker
42
-
43
- Run 'mqtt [command] --help' to know more about the commands.`;
44
- const ConnectHelp = `
45
- -u/--url the URL to connect to: default is ${DEFAULT_URL}
46
- -i/--clientId the clientId to connect to the server
47
- -U/--username the username to connect to the server
48
- -P/--password the password to connect to the server
49
- -C/--caFile the path to a CA certificate file
50
- -c/--certFile the path to a certificate file
51
- -k/--keyFile the path to a key file
52
- -n/--noClean try to resume a previous session
53
- -h/--help this text
54
- `;
55
- const connectOpts = {
56
- string: [
57
- "url",
58
- "username",
59
- "password",
60
- "caFile",
61
- "certFile",
62
- "keyFile",
63
- "clientId",
64
- ],
65
- alias: {
66
- u: "url",
67
- U: "username",
68
- P: "password",
69
- C: "caFile",
70
- c: "certFile",
71
- k: "keyFile",
72
- i: "clientId",
73
- n: "noClean",
74
- h: "help",
75
- },
76
- boolean: ["noClean", "help"],
77
- default: {
78
- noClean: false,
79
- clientId: `Opifex-${crypto.randomUUID()}`,
80
- },
81
- };
82
- const SubscribeHelp = `Usage: mqtt subscribe <options>
83
-
84
- Where options are:
85
- -t/--topic the topic to use
86
- -q/--qos the QoS (0/1/2) to use, default is 0
87
- ${ConnectHelp}
88
- Example: mqtt subscribe -t hello`;
89
- const subscribeOpts = {
90
- string: ["topic"],
91
- alias: {
92
- t: "topic",
93
- q: "qos",
94
- },
95
- default: {
96
- qos: 0,
97
- topic: "",
98
- },
99
- };
100
- function parseQos(qosArg) {
101
- const qos = Number(qosArg);
102
- switch (qos) {
103
- case 0:
104
- return 0;
105
- case 1:
106
- return 1;
107
- case 2:
108
- return 2;
109
- default:
110
- break;
111
- }
112
- console.log("QoS must be between 0 and 2");
113
- return 0;
114
- }
115
- async function getTLSdata(connectArgs) {
116
- const caFileData = await getFileData(connectArgs.caFile);
117
- const caCerts = caFileData ? [caFileData] : undefined;
118
- const cert = await getFileData(connectArgs.certFile);
119
- const key = await getFileData(connectArgs.keyFile);
120
- return {
121
- caCerts,
122
- cert,
123
- key,
124
- };
125
- }
126
- async function subscribe() {
127
- const connectArgs = parseArgs(getArgs(), connectOpts);
128
- const { caCerts, cert, key, } = await getTLSdata(connectArgs);
129
- const subscribeArgs = parseArgs(getArgs(), subscribeOpts);
130
- if (connectArgs.help) {
131
- console.log(SubscribeHelp);
132
- return;
133
- }
134
- if (subscribeArgs.topic === undefined) {
135
- console.log("Missing `topic`");
136
- return;
137
- }
138
- try {
139
- await client.connect({
140
- url: connectArgs.url,
141
- caCerts,
142
- cert,
143
- key,
144
- options: {
145
- username: connectArgs.username,
146
- password: encoder.encode(connectArgs.password),
147
- clientId: connectArgs.clientId,
148
- clean: !connectArgs.noClean,
149
- keepAlive: 60,
150
- },
151
- });
152
- logger.debug("Connected !");
153
- client.subscribe({
154
- subscriptions: [
155
- {
156
- topicFilter: subscribeArgs.topic,
157
- qos: parseQos(subscribeArgs.qos),
158
- },
159
- ],
160
- });
161
- logger.debug("Subscribed!");
162
- for await (const message of client.messages()) {
163
- console.log(decoder.decode(message.payload));
164
- }
165
- }
166
- catch (err) {
167
- if (err instanceof Error) {
168
- // @ts-ignore the type spec of err is missing err.code
169
- logger.info(`Error: ${err.message || err.code}`);
170
- }
171
- }
172
- }
173
- const PublishHelp = `Usage: mqtt publish <options>
174
-
175
- Where options are:
176
- -t/--topic the topic to use
177
- -m/--message the message to send
178
- -q/--qos the QoS (0/1/2) to use, default is 0
179
- -r/--retain if the message should be retained, default is false
180
- ${ConnectHelp}
181
- Example: mqtt publish -t hello -m world`;
182
- const publishOpts = {
183
- string: ["topic", "message"],
184
- boolean: ["retain"],
185
- alias: {
186
- t: "topic",
187
- m: "message",
188
- q: "qos",
189
- r: "retain",
190
- },
191
- default: {
192
- qos: 0,
193
- dup: false,
194
- retain: false,
195
- topic: undefined,
196
- message: "",
197
- },
198
- };
199
- async function publish() {
200
- const connectArgs = parseArgs(getArgs(), connectOpts);
201
- const { caCerts, cert, key, } = await getTLSdata(connectArgs);
202
- const publishArgs = parseArgs(getArgs(), publishOpts);
203
- if (connectArgs.help) {
204
- console.log(PublishHelp);
205
- return;
206
- }
207
- if (publishArgs.topic === undefined) {
208
- console.log("Missing `topic`");
209
- return;
210
- }
211
- try {
212
- await client.connect({
213
- url: connectArgs.url,
214
- caCerts,
215
- cert,
216
- key,
217
- options: {
218
- username: connectArgs.username,
219
- password: encoder.encode(connectArgs.password),
220
- clientId: connectArgs.clientId,
221
- clean: !connectArgs.noClean,
222
- },
223
- });
224
- logger.debug("Connected !");
225
- await client.publish({
226
- topic: publishArgs.topic,
227
- payload: encoder.encode(publishArgs.message),
228
- retain: publishArgs.retain,
229
- qos: parseQos(publishArgs.qos),
230
- });
231
- logger.debug("Published!");
232
- client.disconnect();
233
- logger.debug("Disconnected !");
234
- }
235
- catch (err) {
236
- if (err instanceof Error) {
237
- // @ts-ignore the type spec of err is missing err.code
238
- logger.info(`Error: ${err.message || err.code}`);
239
- }
240
- }
241
- }
242
- function processArgs() {
243
- const { _: [cmd] } = parseArgs(getArgs());
244
- switch (cmd) {
245
- case "publish":
246
- publish();
247
- break;
248
- case "subscribe":
249
- subscribe();
250
- break;
251
- default:
252
- console.log(MQTTHelp);
253
- break;
254
- }
255
- }
256
- processArgs();
@@ -1,16 +0,0 @@
1
- /**
2
- * @description Object representing possible connection states
3
- * @readonly
4
- */
5
- export const ConnectionState = {
6
- /** System is offline and not attempting connection */
7
- offline: "offline",
8
- /** System is in the process of establishing a connection */
9
- connecting: "connecting",
10
- /** System has an active connection */
11
- connected: "connected",
12
- /** System is in the process of disconnecting */
13
- disconnecting: "disconnecting",
14
- /** System has been disconnected */
15
- disconnected: "disconnected",
16
- };
@@ -1,187 +0,0 @@
1
- import { Deferred, logger, MemoryStore, PacketType, } from "./deps.js";
2
- import { Context } from "./context.js";
3
- /**
4
- * Generates a random client ID with the given prefix
5
- * @param prefix - The prefix to use for the client ID
6
- * @returns A string containing the prefix followed by a random number
7
- */
8
- function generateClientId(prefix) {
9
- return `${prefix}-${Math.random().toString().slice(-10)}`;
10
- }
11
- /**
12
- * Implements exponential backoff sleep with optional randomization
13
- * based on https://dthain.blogspot.com/2009/02/exponential-backoff-in-distributed.html
14
- * @param random - Whether to add randomization to the delay
15
- * @param attempt - The attempt number (used to calculate delay)
16
- * @returns Promise that resolves after the calculated delay
17
- */
18
- function backOffSleep(random, attempt) {
19
- const factor = 1.5;
20
- const min = 1000;
21
- const max = 5000;
22
- const randomness = 1 + (random ? Math.random() : 0);
23
- const delay = Math.floor(Math.min(randomness * min * (factor ** attempt), max));
24
- logger.debug({ delay });
25
- return new Promise((resolve) => setTimeout(resolve, delay));
26
- }
27
- /** the default MQTT URL to connect to */
28
- export const DEFAULT_URL = "mqtt://localhost:1883/";
29
- const DEFAULT_KEEPALIVE = 60; // 60 seconds
30
- const DEFAULT_RETRIES = 3; // on first connect
31
- const CLIENTID_PREFIX = "opifex"; // on first connect
32
- /**
33
- * The Client class provides an MQTT Client that can be used to connect to
34
- * a MQTT broker and publish/subscribe messages.
35
- *
36
- * The Client class is not meant to be used directly, but
37
- * instead should be subclassed and the subclass should
38
- * override the createConn() method to provide a
39
- * connection type that is supported by the subclass.
40
- */
41
- export class Client {
42
- clientIdPrefix = CLIENTID_PREFIX;
43
- numberOfRetries = DEFAULT_RETRIES;
44
- url = new URL(DEFAULT_URL);
45
- keepAlive = DEFAULT_KEEPALIVE;
46
- autoReconnect = true;
47
- caCerts;
48
- cert;
49
- key;
50
- clientId;
51
- ctx = new Context(new MemoryStore());
52
- connectPacket;
53
- /**
54
- * Creates a new MQTT client instance
55
- */
56
- constructor() {
57
- this.clientId = generateClientId(this.clientIdPrefix);
58
- this.numberOfRetries = DEFAULT_RETRIES;
59
- }
60
- /**
61
- * Creates a new connection to the MQTT broker
62
- * @param protocol - The protocol to use (mqtt, mqtts, etc)
63
- * @param _hostname - The hostname to connect to
64
- * @param _port - The port to connect to
65
- * @param _caCerts - Optional CA certificates
66
- * @param _cert - Optional client certificate
67
- * @param _key - Optional client key
68
- * @returns Promise resolving to a SockConn connection
69
- */
70
- createConn(protocol, _hostname, _port, _caCerts, _cert, _key) {
71
- // if you need to support alternative connection types just
72
- // overload this method in your subclass
73
- throw `Unsupported protocol: ${protocol}`;
74
- }
75
- /**
76
- * Handles the connection process including retries and reconnection
77
- * @returns Promise that resolves when connection is established or fails
78
- */
79
- async doConnect() {
80
- if (!this.connectPacket) {
81
- return;
82
- }
83
- let isReconnect = false;
84
- let attempt = 1;
85
- let lastMessage = new Error();
86
- let tryConnect = true;
87
- while (tryConnect) {
88
- logger.debug(`${isReconnect ? "re" : ""}connecting`);
89
- try {
90
- const conn = await this.createConn(this.url.protocol, this.url.hostname, Number(this.url.port) ?? undefined, this.caCerts, this.cert, this.key);
91
- // if we get this far we have a connection
92
- tryConnect =
93
- (await this.ctx.handleConnection(conn, this.connectPacket)) &&
94
- this.autoReconnect;
95
- logger.debug({ tryConnect });
96
- isReconnect = true;
97
- this.connectPacket.clean = false;
98
- this.ctx.close();
99
- }
100
- catch (err) {
101
- if (err instanceof Error) {
102
- lastMessage = err;
103
- }
104
- logger.debug(lastMessage);
105
- if (!isReconnect && attempt > this.numberOfRetries) {
106
- tryConnect = false;
107
- }
108
- else {
109
- await backOffSleep(true, attempt++);
110
- }
111
- }
112
- }
113
- if (isReconnect === false) {
114
- this.ctx.unresolvedConnect?.reject(lastMessage);
115
- }
116
- }
117
- /**
118
- * Connects to the MQTT broker
119
- * @param params - Connection parameters
120
- * @returns Promise resolving to authentication result
121
- */
122
- connect(params = {}) {
123
- this.url = params?.url || this.url;
124
- this.numberOfRetries = params.numberOfRetries || this.numberOfRetries;
125
- this.caCerts = params?.caCerts;
126
- this.cert = params?.cert;
127
- this.key = params?.key;
128
- const options = Object.assign({
129
- keepAlive: this.keepAlive,
130
- clientId: this.clientId,
131
- }, params?.options);
132
- this.connectPacket = {
133
- type: PacketType.connect,
134
- ...options,
135
- };
136
- const deferred = new Deferred();
137
- this.ctx.unresolvedConnect = deferred;
138
- this.doConnect();
139
- return deferred.promise;
140
- }
141
- /**
142
- * Disconnects from the MQTT broker
143
- * @returns Promise that resolves when disconnected
144
- */
145
- async disconnect() {
146
- await this.ctx.disconnect();
147
- }
148
- /**
149
- * Publishes a message to the MQTT broker
150
- * @param params - Publish parameters including topic and payload
151
- * @returns Promise that resolves when published
152
- */
153
- async publish(params) {
154
- const packet = {
155
- type: PacketType.publish,
156
- ...params,
157
- };
158
- await this.ctx.publish(packet);
159
- }
160
- /**
161
- * Subscribes to topics on the MQTT broker
162
- * @param params - Subscribe parameters including topics
163
- * @returns Promise that resolves when subscribed
164
- */
165
- async subscribe(params) {
166
- const packet = {
167
- type: PacketType.subscribe,
168
- id: 0, //placeholder
169
- ...params,
170
- };
171
- await this.ctx.subscribe(packet);
172
- }
173
- /**
174
- * Gets an async iterator for received messages
175
- * @returns AsyncGenerator yielding received publish packets
176
- */
177
- async *messages() {
178
- yield* this.ctx.incoming;
179
- }
180
- /**
181
- * Closes the message stream
182
- * @param reason - Optional reason for closing
183
- */
184
- closeMessages(reason) {
185
- this.ctx.incoming.close(reason);
186
- }
187
- }
@@ -1,152 +0,0 @@
1
- import { AsyncQueue, Deferred, logger, MqttConn, PacketType, Timer, } from "./deps.js";
2
- import { handlePacket } from "./handlers/handlePacket.js";
3
- import { ConnectionState } from "./ConnectionState.js";
4
- export class Context {
5
- mqttConn;
6
- connectionState;
7
- pingTimer;
8
- unresolvedConnect;
9
- unresolvedPublish;
10
- unresolvedSubscribe;
11
- unresolvedUnSubscribe;
12
- store;
13
- incoming;
14
- constructor(store) {
15
- this.store = store;
16
- this.connectionState = ConnectionState.offline;
17
- this.incoming = new AsyncQueue();
18
- this.unresolvedPublish = new Map();
19
- this.unresolvedSubscribe = new Map();
20
- this.unresolvedUnSubscribe = new Map();
21
- }
22
- async connect(packet) {
23
- this.connectionState = ConnectionState.connecting;
24
- await this.mqttConn?.send(packet);
25
- const keepAlive = packet.keepAlive || 0;
26
- if (keepAlive > 0) {
27
- this.pingTimer = new Timer(this.sendPing.bind(this), keepAlive * 1000, true);
28
- }
29
- }
30
- async disconnect() {
31
- if (this.connectionState !== ConnectionState.connected) {
32
- throw "Not connected";
33
- }
34
- if (this.mqttConn) {
35
- this.connectionState = ConnectionState.disconnecting;
36
- await this.mqttConn.send({ type: PacketType.disconnect });
37
- this.mqttConn.close();
38
- }
39
- }
40
- async send(packet) {
41
- logger.debug({ send: packet });
42
- if (this.connectionState === ConnectionState.connected &&
43
- !this.mqttConn?.isClosed) {
44
- await this.mqttConn?.send(packet);
45
- this.pingTimer?.reset();
46
- return;
47
- }
48
- logger.debug("not connected");
49
- this.pingTimer?.clear();
50
- }
51
- sendPing() {
52
- this.send({ type: PacketType.pingreq });
53
- }
54
- async handleConnection(conn, connectPacket) {
55
- this.mqttConn = new MqttConn({ conn });
56
- if (this.mqttConn === undefined) {
57
- return true;
58
- }
59
- logger.debug("Send connect packet");
60
- await this.connect(connectPacket);
61
- try {
62
- logger.debug("Accepting packets");
63
- for await (const packet of this.mqttConn) {
64
- handlePacket(this, packet);
65
- }
66
- logger.debug("No more packets");
67
- }
68
- catch (err) {
69
- logger.debug(err);
70
- if (this.mqttConn.isClosed) {
71
- this.mqttConn.close();
72
- }
73
- }
74
- if (this.connectionState === ConnectionState.disconnecting) {
75
- return false;
76
- }
77
- return true;
78
- }
79
- close() {
80
- logger.debug("closing connection");
81
- this.connectionState = ConnectionState.disconnected;
82
- this.pingTimer?.clear();
83
- }
84
- receivePublish(packet) {
85
- this.incoming.push(packet);
86
- }
87
- publish(packet) {
88
- const qos = packet.qos || 0;
89
- if (qos === 0) {
90
- packet.id = 0;
91
- this.send(packet);
92
- // return empty promise
93
- return Promise.resolve();
94
- }
95
- packet.id = this.store.nextId();
96
- this.store.pendingOutgoing.set(packet.id, packet);
97
- const deferred = new Deferred();
98
- this.unresolvedPublish.set(packet.id, deferred);
99
- this.send(packet);
100
- return deferred.promise;
101
- }
102
- subscribe(packet) {
103
- packet.id = this.store.nextId();
104
- this.store.pendingOutgoing.set(packet.id, packet);
105
- const deferred = new Deferred();
106
- this.unresolvedSubscribe.set(packet.id, deferred);
107
- this.send(packet);
108
- return deferred.promise;
109
- }
110
- unsubscribe(packet) {
111
- packet.id = this.store.nextId();
112
- this.store.pendingOutgoing.set(packet.id, packet);
113
- const deferred = new Deferred();
114
- this.unresolvedUnSubscribe.set(packet.id, deferred);
115
- this.send(packet);
116
- return deferred.promise;
117
- }
118
- receivePuback(id) {
119
- const unresolvedMap = this.unresolvedPublish;
120
- if (unresolvedMap.has(id)) {
121
- const deferred = unresolvedMap.get(id);
122
- unresolvedMap.delete(id);
123
- deferred?.resolve();
124
- return true;
125
- }
126
- return false;
127
- }
128
- // just an alias to clarify protocol flow
129
- receivePubcomp(id) {
130
- return this.receivePuback(id);
131
- }
132
- receiveSuback(id, returnCodes) {
133
- const unresolvedMap = this.unresolvedSubscribe;
134
- if (unresolvedMap.has(id)) {
135
- const deferred = unresolvedMap.get(id);
136
- unresolvedMap.delete(id);
137
- deferred?.resolve(returnCodes);
138
- return true;
139
- }
140
- return false;
141
- }
142
- receiveUnsuback(id) {
143
- const unresolvedMap = this.unresolvedUnSubscribe;
144
- if (unresolvedMap.has(id)) {
145
- const deferred = unresolvedMap.get(id);
146
- unresolvedMap.delete(id);
147
- deferred?.resolve();
148
- return true;
149
- }
150
- return false;
151
- }
152
- }
@@ -1,5 +0,0 @@
1
- export { AuthenticationResult, AuthenticationResultByNumber, decodePayload, encode, PacketNameByType, PacketType, } from "../mqttPacket/mod.js";
2
- export { MqttConn } from "../mqttConn/mqttConn.js";
3
- export { Timer } from "../timer/timer.js";
4
- export { AsyncQueue, Deferred, logger } from "../utils/mod.js";
5
- export { MemoryStore } from "./store/memoryStore.js";
@@ -1,24 +0,0 @@
1
- import { ConnectionState } from "../ConnectionState.js";
2
- import { AuthenticationResultByNumber } from "../deps.js";
3
- /**
4
- * Handles the CONNACK packet received from the MQTT broker
5
- * @param packet - The CONNACK packet containing the connection acknowledgment
6
- * @param ctx - The connection context
7
- * @returns Promise that resolves when handling is complete
8
- */
9
- export async function handleConnack(packet, ctx) {
10
- if (packet.returnCode === 0) {
11
- ctx.connectionState = ConnectionState.connected;
12
- ctx.pingTimer?.reset();
13
- ctx.unresolvedConnect?.resolve(packet.returnCode);
14
- // start transmitting packets that were queued before
15
- for await (const packet of ctx.store.pendingOutgoingPackets()) {
16
- ctx.send(packet);
17
- }
18
- return;
19
- }
20
- const err = new Error(`Connect failed: ${AuthenticationResultByNumber[packet.returnCode]}`);
21
- ctx.connectionState = ConnectionState.disconnecting;
22
- ctx.pingTimer?.clear();
23
- ctx.unresolvedConnect?.reject(err);
24
- }
@@ -1,57 +0,0 @@
1
- import { ConnectionState } from "../ConnectionState.js";
2
- import { handleConnack } from "./handleConnack.js";
3
- import { handlePublish } from "./handlePublish.js";
4
- import { handlePuback } from "./handlePuback.js";
5
- import { handlePubrec } from "./handlePubrec.js";
6
- import { handlePubrel } from "./handlePubrel.js";
7
- import { handlePubcomp } from "./handlePubcomp.js";
8
- import { handleSuback } from "./handleSuback.js";
9
- import { handleUnsuback } from "./handleUnsuback.js";
10
- import { logger, PacketNameByType, PacketType } from "../deps.js";
11
- /**
12
- * Handles incoming MQTT packets based on the connection state and packet type
13
- * @param ctx - The MQTT client context containing connection state and other information
14
- * @param packet - The MQTT packet to handle
15
- * @throws Error if an unexpected packet is received before connection is established
16
- * @throws Error if an unexpected packet type is received after connection
17
- */
18
- export async function handlePacket(ctx, packet) {
19
- logger.debug({ received: PacketNameByType[packet.type], packet });
20
- if (ctx.connectionState !== ConnectionState.connected) {
21
- if (packet.type === PacketType.connack) {
22
- handleConnack(packet, ctx);
23
- }
24
- else {
25
- throw new Error(`Received ${PacketNameByType[packet.type]} packet before connect`);
26
- }
27
- }
28
- else {
29
- switch (packet.type) {
30
- case PacketType.pingres:
31
- break;
32
- case PacketType.publish:
33
- await handlePublish(ctx, packet);
34
- break;
35
- case PacketType.puback:
36
- await handlePuback(ctx, packet);
37
- break;
38
- case PacketType.pubrel:
39
- await handlePubrel(ctx, packet);
40
- break;
41
- case PacketType.pubrec:
42
- await handlePubrec(ctx, packet);
43
- break;
44
- case PacketType.pubcomp:
45
- await handlePubcomp(ctx, packet);
46
- break;
47
- case PacketType.suback:
48
- await handleSuback(ctx, packet);
49
- break;
50
- case PacketType.unsuback:
51
- handleUnsuback(ctx, packet);
52
- break;
53
- default:
54
- throw new Error(`Received unexpected ${PacketNameByType[packet.type]} packet after connect`);
55
- }
56
- }
57
- }