u8-mqtt 0.6.2 → 0.6.4
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/cjs/basic-v4.cjs +194 -243
- package/cjs/basic-v4.cjs.map +1 -1
- package/cjs/basic-v5.cjs +247 -368
- package/cjs/basic-v5.cjs.map +1 -1
- package/cjs/full-v4.cjs +342 -384
- package/cjs/full-v4.cjs.map +1 -1
- package/cjs/full-v5.cjs +395 -507
- package/cjs/full-v5.cjs.map +1 -1
- package/cjs/index.cjs +292 -399
- package/cjs/index.cjs.map +1 -1
- package/cjs/v4.cjs +239 -274
- package/cjs/v4.cjs.map +1 -1
- package/cjs/v5.cjs +292 -399
- package/cjs/v5.cjs.map +1 -1
- package/code/router_path.jsy +39 -28
- package/code/with_topic_router.jsy +4 -1
- package/esm/basic-v4.js +194 -243
- package/esm/basic-v4.js.map +1 -1
- package/esm/basic-v5.js +247 -368
- package/esm/basic-v5.js.map +1 -1
- package/esm/deno/basic-v4.js +194 -243
- package/esm/deno/basic-v4.js.map +1 -1
- package/esm/deno/basic-v5.js +247 -368
- package/esm/deno/basic-v5.js.map +1 -1
- package/esm/deno/full-v4.js +342 -384
- package/esm/deno/full-v4.js.map +1 -1
- package/esm/deno/full-v5.js +395 -507
- package/esm/deno/full-v5.js.map +1 -1
- package/esm/deno/index.js +292 -399
- package/esm/deno/index.js.map +1 -1
- package/esm/deno/v4.js +239 -274
- package/esm/deno/v4.js.map +1 -1
- package/esm/deno/v5.js +292 -399
- package/esm/deno/v5.js.map +1 -1
- package/esm/full-v4.js +342 -384
- package/esm/full-v4.js.map +1 -1
- package/esm/full-v5.js +395 -507
- package/esm/full-v5.js.map +1 -1
- package/esm/index.js +292 -399
- package/esm/index.js.map +1 -1
- package/esm/node/basic-v4.js +194 -243
- package/esm/node/basic-v4.js.map +1 -1
- package/esm/node/basic-v4.mjs +194 -243
- package/esm/node/basic-v4.mjs.map +1 -1
- package/esm/node/basic-v5.js +247 -368
- package/esm/node/basic-v5.js.map +1 -1
- package/esm/node/basic-v5.mjs +247 -368
- package/esm/node/basic-v5.mjs.map +1 -1
- package/esm/node/full-v4.js +342 -384
- package/esm/node/full-v4.js.map +1 -1
- package/esm/node/full-v4.mjs +342 -384
- package/esm/node/full-v4.mjs.map +1 -1
- package/esm/node/full-v5.js +395 -507
- package/esm/node/full-v5.js.map +1 -1
- package/esm/node/full-v5.mjs +395 -507
- package/esm/node/full-v5.mjs.map +1 -1
- package/esm/node/index.js +292 -399
- package/esm/node/index.js.map +1 -1
- package/esm/node/index.mjs +292 -399
- package/esm/node/index.mjs.map +1 -1
- package/esm/node/v4.js +239 -274
- package/esm/node/v4.js.map +1 -1
- package/esm/node/v4.mjs +239 -274
- package/esm/node/v4.mjs.map +1 -1
- package/esm/node/v5.js +292 -399
- package/esm/node/v5.js.map +1 -1
- package/esm/node/v5.mjs +292 -399
- package/esm/node/v5.mjs.map +1 -1
- package/esm/v4.js +239 -274
- package/esm/v4.js.map +1 -1
- package/esm/v5.js +292 -399
- package/esm/v5.js.map +1 -1
- package/esm/web/basic-v4.js +194 -243
- package/esm/web/basic-v4.js.map +1 -1
- package/esm/web/basic-v4.min.js +1 -1
- package/esm/web/basic-v4.min.js.br +0 -0
- package/esm/web/basic-v4.min.js.gz +0 -0
- package/esm/web/basic-v5.js +247 -368
- package/esm/web/basic-v5.js.map +1 -1
- package/esm/web/basic-v5.min.js +1 -1
- package/esm/web/basic-v5.min.js.br +0 -0
- package/esm/web/basic-v5.min.js.gz +0 -0
- package/esm/web/full-v4.js +342 -384
- package/esm/web/full-v4.js.map +1 -1
- package/esm/web/full-v4.min.js +1 -1
- package/esm/web/full-v4.min.js.br +0 -0
- package/esm/web/full-v4.min.js.gz +0 -0
- package/esm/web/full-v5.js +395 -507
- package/esm/web/full-v5.js.map +1 -1
- package/esm/web/full-v5.min.js +1 -1
- package/esm/web/full-v5.min.js.br +0 -0
- package/esm/web/full-v5.min.js.gz +0 -0
- package/esm/web/index.js +292 -399
- package/esm/web/index.js.map +1 -1
- package/esm/web/index.min.js +1 -1
- package/esm/web/index.min.js.br +0 -0
- package/esm/web/index.min.js.gz +0 -0
- package/esm/web/v4.js +239 -274
- package/esm/web/v4.js.map +1 -1
- package/esm/web/v4.min.js +1 -1
- package/esm/web/v4.min.js.br +0 -0
- package/esm/web/v4.min.js.gz +0 -0
- package/esm/web/v5.js +292 -399
- package/esm/web/v5.js.map +1 -1
- package/esm/web/v5.min.js +1 -1
- package/esm/web/v5.min.js.br +0 -0
- package/esm/web/v5.min.js.gz +0 -0
- package/package.json +5 -5
package/esm/node/full-v5.mjs
CHANGED
|
@@ -2,41 +2,20 @@ import { connect } from 'node:net';
|
|
|
2
2
|
import { connect as connect$1 } from 'node:tls';
|
|
3
3
|
|
|
4
4
|
function encode_varint(n, a=[]) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
n
|
|
8
|
-
a.push( ni | (0===n ? 0 : 0x80) );
|
|
9
|
-
} while (n > 0)
|
|
5
|
+
a.push((n<0x80 ? 0 : 0x80) | (n & 0x7f));
|
|
6
|
+
for(; ( n>>>=7 ) > 0 ;)
|
|
7
|
+
a.push((n<0x80 ? 0 : 0x80) | (n & 0x7f));
|
|
10
8
|
return a
|
|
11
9
|
}
|
|
12
10
|
|
|
11
|
+
function decode_varint$1(u8, i0=0, invalid) {
|
|
12
|
+
let shift=0, i=i0, b=u8[i++], n=(b & 0x7f);
|
|
13
|
+
for(; b & 0x80;)
|
|
14
|
+
n |= ((b=u8[i++]) & 0x7f) << (shift += 7);
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
let shift = 0, n = (u8[i] & 0x7f)
|
|
18
|
-
while ( 0x80 & u8[i++] )
|
|
19
|
-
n |= (u8[i] & 0x7f) << (shift += 7)
|
|
20
|
-
|
|
21
|
-
return [n, i, i0]
|
|
22
|
-
}
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
function decode_varint$1(u8, i=0) {
|
|
27
|
-
let i0 = i;
|
|
28
|
-
// unrolled for a max of 4 chains
|
|
29
|
-
let n = (u8[i] & 0x7f) << 0;
|
|
30
|
-
if ( 0x80 & u8[i++] ) {
|
|
31
|
-
n |= (u8[i] & 0x7f) << 7;
|
|
32
|
-
if ( 0x80 & u8[i++] ) {
|
|
33
|
-
n |= (u8[i] & 0x7f) << 14;
|
|
34
|
-
if ( 0x80 & u8[i++] ) {
|
|
35
|
-
n |= (u8[i] & 0x7f) << 21;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return [n, i, i0]
|
|
16
|
+
return (u8.length < i)
|
|
17
|
+
? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
|
|
18
|
+
: [n, i, i0] // successful value
|
|
40
19
|
}
|
|
41
20
|
|
|
42
21
|
function add_mqtt_props(mqtt_props, entries) {
|
|
@@ -83,19 +62,18 @@ const init_mqtt_props = () =>
|
|
|
83
62
|
const mqtt_props = /* #__PURE__ */
|
|
84
63
|
init_mqtt_props();
|
|
85
64
|
|
|
86
|
-
class
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return self
|
|
65
|
+
class mqtt_reason extends Number {
|
|
66
|
+
constructor(v, reason) {
|
|
67
|
+
super(v);
|
|
68
|
+
this.reason = `:${(this.ok = v<0x80) ? 'ok' : 'fail'}:${reason}`;
|
|
91
69
|
}
|
|
92
70
|
}
|
|
93
71
|
|
|
94
72
|
class mqtt_reader_v4 {
|
|
95
|
-
static
|
|
96
|
-
of(buf) {
|
|
73
|
+
static for(pkt, u8_body) { return new this().of(u8_body, {pkt}) }
|
|
74
|
+
of(buf, opt) {
|
|
97
75
|
let step = (width, k) => (k=0|step.k, step.k=k+width, k);
|
|
98
|
-
return {__proto__: this, buf, step}
|
|
76
|
+
return {__proto__: this, buf, step, ...opt}
|
|
99
77
|
}
|
|
100
78
|
|
|
101
79
|
has_more() {
|
|
@@ -138,7 +116,7 @@ class mqtt_reader_v4 {
|
|
|
138
116
|
reason(pkt_kind) {
|
|
139
117
|
let v = this.buf[this.step(1)];
|
|
140
118
|
if (null != v)
|
|
141
|
-
return
|
|
119
|
+
return new mqtt_reason(v, this._reason_for?.(v, pkt_kind))
|
|
142
120
|
}
|
|
143
121
|
|
|
144
122
|
flush() {
|
|
@@ -152,7 +130,7 @@ class mqtt_reader_v4 {
|
|
|
152
130
|
let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
|
|
153
131
|
props() {
|
|
154
132
|
let {buf, step} = this;
|
|
155
|
-
let [n, vi, vi0] = decode_varint$1(buf, step.k|0);
|
|
133
|
+
let [n, vi, vi0] = decode_varint$1(buf, step.k|0, 0);
|
|
156
134
|
step(n + vi - vi0);
|
|
157
135
|
if (0 === n) return null
|
|
158
136
|
|
|
@@ -161,7 +139,7 @@ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
|
|
|
161
139
|
let v, pk = fork.u8(), pt = mqtt_props.get( pk );
|
|
162
140
|
if (!pt) {
|
|
163
141
|
res._unknown_ = pk;
|
|
164
|
-
this.warn(`unknown property: ${pk}`);
|
|
142
|
+
this.warn?.(`unknown property: ${pk}`);
|
|
165
143
|
break
|
|
166
144
|
}
|
|
167
145
|
|
|
@@ -181,8 +159,6 @@ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
|
|
|
181
159
|
return vec
|
|
182
160
|
}
|
|
183
161
|
|
|
184
|
-
warn(msg) { console.warn('[u8-mqtt-packet] '+msg); }
|
|
185
|
-
|
|
186
162
|
/*
|
|
187
163
|
vbuf() {
|
|
188
164
|
let {buf, step} = this
|
|
@@ -194,28 +170,99 @@ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
|
|
|
194
170
|
*/
|
|
195
171
|
};
|
|
196
172
|
|
|
197
|
-
function
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
let proto = this.prototype;
|
|
201
|
-
proto._reasons_by = {... proto._reasons_by};
|
|
173
|
+
function with_reasons(mqtt_reader, by_kind) {
|
|
174
|
+
for (let [k,lut] of Object.entries(by_kind))
|
|
175
|
+
by_kind[k] = new Map(lut);
|
|
202
176
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
177
|
+
return class extends mqtt_reader {
|
|
178
|
+
_reason_for(v, pkt_kind) {
|
|
179
|
+
return by_kind[pkt_kind]?.get(v) || by_kind.all.get(v)
|
|
180
|
+
}
|
|
181
|
+
warn(msg) {
|
|
182
|
+
let pkt = this.pkt;
|
|
183
|
+
pkt.warn ? pkt.warn(msg, pkt)
|
|
184
|
+
: console.warn('[u8-mqtt-packet] '+msg);
|
|
208
185
|
}
|
|
209
|
-
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
210
188
|
|
|
211
|
-
for (let fn_info of info_fn_list)
|
|
212
|
-
fn_info(mqtt_reader);
|
|
213
189
|
|
|
214
|
-
|
|
215
|
-
|
|
190
|
+
const reasons_v4 = {
|
|
191
|
+
connack: [
|
|
192
|
+
[ 0x01, 'conn refused: unacceptable protocol version'],
|
|
193
|
+
[ 0x02, 'conn refused: identifier rejected'],
|
|
194
|
+
[ 0x03, 'conn refused: server unavailable'],
|
|
195
|
+
[ 0x04, 'conn refused: bad user name or password'],
|
|
196
|
+
[ 0x05, 'conn refused: not authorized'],
|
|
197
|
+
],
|
|
198
|
+
suback: [
|
|
199
|
+
[ 0x00, 'qos=0'],
|
|
200
|
+
[ 0x01, 'qos=1'],
|
|
201
|
+
[ 0x02, 'qos=2'],
|
|
202
|
+
],
|
|
203
|
+
unsuback: [
|
|
204
|
+
[ 0x11, 'no subscription existed'],
|
|
205
|
+
],
|
|
206
|
+
puback: [
|
|
207
|
+
[ 0x10, 'no matching subscribers'],
|
|
208
|
+
],
|
|
209
|
+
all: [
|
|
210
|
+
[ 0, ''], // Success
|
|
211
|
+
[ 0x80, 'unspecified error'], // disconnect puback suback unsuback
|
|
212
|
+
[ 0x83, 'implementation specific error'], // connack disconnect puback suback unsuback
|
|
213
|
+
[ 0x87, 'not authorized'], // connack disconnect puback suback unsuback
|
|
214
|
+
[ 0x8F, 'topic filter invalid'], // disconnect suback unsuback
|
|
215
|
+
[ 0x91, 'packet identifier in use'], // puback suback unsuback
|
|
216
|
+
[ 0x92, 'packet identifier not found' ], // pubxxx
|
|
217
|
+
]};
|
|
218
|
+
|
|
219
|
+
const reasons_v5 = {
|
|
220
|
+
... reasons_v4,
|
|
221
|
+
auth: [
|
|
222
|
+
[ 0x18, 'continue authentication' ],
|
|
223
|
+
[ 0x19, 're-authenticate' ],
|
|
224
|
+
],
|
|
225
|
+
disconnect: [
|
|
226
|
+
[ 0x04, 'disconnect with will message'],
|
|
227
|
+
],
|
|
228
|
+
all: [
|
|
229
|
+
... reasons_v4.all,
|
|
230
|
+
[ 0x81, 'malformed packet'], // connack disconnect
|
|
231
|
+
[ 0x82, 'protocol error'], // connack disconnect
|
|
232
|
+
[ 0x84, 'unsupported protocol version'], // connack
|
|
233
|
+
[ 0x85, 'client identifier not valid'], // connack
|
|
234
|
+
[ 0x86, 'bad user name or password'], // connack
|
|
235
|
+
[ 0x88, 'server unavailable'], // connack
|
|
236
|
+
[ 0x89, 'server busy'], // connack disconnect
|
|
237
|
+
[ 0x8A, 'banned'], // connack
|
|
238
|
+
[ 0x8B, 'server shutting down'], // disconnect
|
|
239
|
+
[ 0x8C, 'bad authentication method'], // connack
|
|
240
|
+
[ 0x8D, 'keep alive timeout'], // disconnect
|
|
241
|
+
[ 0x8E, 'session taken over'], // disconnect
|
|
242
|
+
[ 0x90, 'topic name invalid'], // connack disconnect puback
|
|
243
|
+
[ 0x93, 'receive maximum exceeded'], // disconnect
|
|
244
|
+
[ 0x94, 'topic alias invalid'], // disconnect
|
|
245
|
+
[ 0x95, 'packet too large'], // connack disconnect
|
|
246
|
+
[ 0x96, 'message rate too high'], // disconnect
|
|
247
|
+
[ 0x97, 'quota exceeded'], // connack disconnect puback suback
|
|
248
|
+
[ 0x98, 'administrative action'], // disconnect
|
|
249
|
+
[ 0x99, 'payload format invalid'], // connack disconnect puback
|
|
250
|
+
[ 0x9A, 'retain not supported'], // connack disconnect
|
|
251
|
+
[ 0x9B, 'qoS not supported'], // connack disconnect
|
|
252
|
+
[ 0x9C, 'use another server'], // connack disconnect
|
|
253
|
+
[ 0x9D, 'server moved'], // connack disconnect
|
|
254
|
+
[ 0x9E, 'shared subscriptions not supported'], // disconnect suback
|
|
255
|
+
[ 0x9F, 'connection rate exceeded'], // connack disconnect
|
|
256
|
+
[ 0xA0, 'maximum connect time'], // disconnect
|
|
257
|
+
[ 0xA1, 'subscription identifiers not supported'], // disconnect suback
|
|
258
|
+
[ 0xA2, 'wildcard subscriptions not supported'], // disconnect suback
|
|
259
|
+
]};
|
|
260
|
+
|
|
261
|
+
const mqtt_reader_v5 = /* #__PURE__ */
|
|
262
|
+
with_reasons(mqtt_reader_v5$1, reasons_v5);
|
|
216
263
|
|
|
217
264
|
class mqtt_writer_v4 {
|
|
218
|
-
static
|
|
265
|
+
static for(pkt) { return new this().of() }
|
|
219
266
|
of() { return {__proto__: this, $:[]} }
|
|
220
267
|
|
|
221
268
|
static init() { return this }
|
|
@@ -329,351 +376,6 @@ class mqtt_writer_v5 extends mqtt_writer_v4 {
|
|
|
329
376
|
}
|
|
330
377
|
}
|
|
331
378
|
|
|
332
|
-
function mqtt_decode_connect(ns, mqtt_reader) {
|
|
333
|
-
class _connect_flags_ extends Number {
|
|
334
|
-
get reserved() { return this & 0x01 !== 0 }
|
|
335
|
-
get clean_start() { return this & 0x02 !== 0 }
|
|
336
|
-
get will_flag() { return this & 0x04 !== 0 }
|
|
337
|
-
get will_qos() { return (this >>> 3) & 0x3 }
|
|
338
|
-
get will_retain() { return this & 0x20 !== 0 }
|
|
339
|
-
get password() { return this & 0x40 !== 0 }
|
|
340
|
-
get username() { return this & 0x80 !== 0 }
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
return ns[0x1] = (pkt, u8_body) => {
|
|
344
|
-
let rdr = mqtt_reader.of(u8_body);
|
|
345
|
-
if ('MQTT' !== rdr.utf8())
|
|
346
|
-
throw new Error('Invalid mqtt_connect packet')
|
|
347
|
-
|
|
348
|
-
pkt._base_.mqtt_level = pkt.mqtt_level = rdr.u8();
|
|
349
|
-
|
|
350
|
-
let flags = pkt.flags =
|
|
351
|
-
rdr.flags(_connect_flags_);
|
|
352
|
-
|
|
353
|
-
pkt.keep_alive = rdr.u16();
|
|
354
|
-
|
|
355
|
-
if (5 <= pkt.mqtt_level)
|
|
356
|
-
pkt.props = rdr.props();
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
pkt.client_id = rdr.utf8();
|
|
361
|
-
if (flags.will_flag) {
|
|
362
|
-
let will = pkt.will = {};
|
|
363
|
-
if (5 <= pkt.mqtt_level)
|
|
364
|
-
will.props = rdr.props();
|
|
365
|
-
|
|
366
|
-
will.topic = rdr.utf8();
|
|
367
|
-
will.payload = rdr.bin();
|
|
368
|
-
will.qos = flags.will_qos;
|
|
369
|
-
will.retain = flags.will_retain;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
if (flags.username)
|
|
373
|
-
pkt.username = rdr.utf8();
|
|
374
|
-
|
|
375
|
-
if (flags.password)
|
|
376
|
-
pkt.password = rdr.bin();
|
|
377
|
-
return pkt }
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
function mqtt_decode_connack(ns, mqtt_reader) {
|
|
381
|
-
class _connack_flags_ extends Number {
|
|
382
|
-
get session_present() { return this & 0x01 !== 0 }
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
return ns[0x2] = (pkt, u8_body) => {
|
|
386
|
-
let rdr = mqtt_reader.of(u8_body);
|
|
387
|
-
|
|
388
|
-
pkt.flags =
|
|
389
|
-
rdr.flags(_connack_flags_);
|
|
390
|
-
|
|
391
|
-
pkt.reason = rdr.reason(pkt.type);
|
|
392
|
-
if (5 <= pkt.mqtt_level)
|
|
393
|
-
pkt.props = rdr.props();
|
|
394
|
-
return pkt }
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
function _connack_v4(mqtt_reader) {
|
|
399
|
-
mqtt_reader.reasons('connack',
|
|
400
|
-
// MQTT 3.1.1
|
|
401
|
-
[ 0x00, 'Success'],
|
|
402
|
-
[ 0x01, 'Connection refused, unacceptable protocol version'],
|
|
403
|
-
[ 0x02, 'Connection refused, identifier rejected'],
|
|
404
|
-
[ 0x03, 'Connection refused, server unavailable'],
|
|
405
|
-
[ 0x04, 'Connection refused, bad user name or password'],
|
|
406
|
-
[ 0x05, 'Connection refused, not authorized'],
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
function _connack_v5(mqtt_reader) {
|
|
411
|
-
_connack_v4(mqtt_reader);
|
|
412
|
-
|
|
413
|
-
mqtt_reader.reasons('connack',
|
|
414
|
-
// MQTT 5.0
|
|
415
|
-
[ 0x81, 'Malformed Packet'],
|
|
416
|
-
[ 0x82, 'Protocol Error'],
|
|
417
|
-
[ 0x83, 'Implementation specific error'],
|
|
418
|
-
[ 0x84, 'Unsupported Protocol Version'],
|
|
419
|
-
[ 0x85, 'Client Identifier not valid'],
|
|
420
|
-
[ 0x86, 'Bad User Name or Password'],
|
|
421
|
-
[ 0x87, 'Not authorized'],
|
|
422
|
-
[ 0x88, 'Server unavailable'],
|
|
423
|
-
[ 0x89, 'Server busy'],
|
|
424
|
-
[ 0x8A, 'Banned'],
|
|
425
|
-
[ 0x8C, 'Bad authentication method'],
|
|
426
|
-
[ 0x90, 'Topic Name invalid'],
|
|
427
|
-
[ 0x95, 'Packet too large'],
|
|
428
|
-
[ 0x97, 'Quota exceeded'],
|
|
429
|
-
[ 0x99, 'Payload format invalid'],
|
|
430
|
-
[ 0x9A, 'Retain not supported'],
|
|
431
|
-
[ 0x9B, 'QoS not supported'],
|
|
432
|
-
[ 0x9C, 'Use another server'],
|
|
433
|
-
[ 0x9D, 'Server moved'],
|
|
434
|
-
[ 0x9F, 'Connection rate exceeded'],
|
|
435
|
-
);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
function mqtt_decode_publish(ns, mqtt_reader) {
|
|
439
|
-
return ns[0x3] = (pkt, u8_body) => {
|
|
440
|
-
let {hdr} = pkt;
|
|
441
|
-
pkt.dup = Boolean(hdr & 0x8);
|
|
442
|
-
pkt.retain = Boolean(hdr & 0x1);
|
|
443
|
-
let qos = pkt.qos = (hdr>>1) & 0x3;
|
|
444
|
-
|
|
445
|
-
let rdr = mqtt_reader.of(u8_body);
|
|
446
|
-
pkt.topic = rdr.utf8();
|
|
447
|
-
if (0 !== qos)
|
|
448
|
-
pkt.pkt_id = rdr.u16();
|
|
449
|
-
|
|
450
|
-
if (5 <= pkt.mqtt_level)
|
|
451
|
-
pkt.props = rdr.props();
|
|
452
|
-
|
|
453
|
-
pkt.payload = rdr.flush();
|
|
454
|
-
return pkt }
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
function mqtt_decode_puback(ns, mqtt_reader) {
|
|
458
|
-
return ns[0x4] = (pkt, u8_body) => {
|
|
459
|
-
let rdr = mqtt_reader.of(u8_body);
|
|
460
|
-
|
|
461
|
-
pkt.pkt_id = rdr.u16();
|
|
462
|
-
if (5 <= pkt.mqtt_level) {
|
|
463
|
-
pkt.reason = rdr.reason(pkt.type);
|
|
464
|
-
pkt.props = rdr.props();
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
return pkt }
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
function _puback_v5(mqtt_reader) {
|
|
472
|
-
mqtt_reader.reasons('puback',
|
|
473
|
-
// MQTT 5.0
|
|
474
|
-
[ 0x00, 'Success'],
|
|
475
|
-
[ 0x10, 'No matching subscribers'],
|
|
476
|
-
[ 0x80, 'Unspecified error'],
|
|
477
|
-
[ 0x83, 'Implementation specific error'],
|
|
478
|
-
[ 0x87, 'Not authorized'],
|
|
479
|
-
[ 0x90, 'Topic Name invalid'],
|
|
480
|
-
[ 0x91, 'Packet identifier in use'],
|
|
481
|
-
[ 0x97, 'Quota exceeded'],
|
|
482
|
-
[ 0x99, 'Payload format invalid'],
|
|
483
|
-
);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
function mqtt_decode_pubxxx(ns, mqtt_reader) {
|
|
487
|
-
return ns[0x5] = ns[0x6] = ns[0x7] = (pkt, u8_body) => {
|
|
488
|
-
let rdr = mqtt_reader.of(u8_body);
|
|
489
|
-
|
|
490
|
-
pkt.pkt_id = rdr.u16();
|
|
491
|
-
pkt.reason = rdr.reason('pubxxx', mqtt_reader);
|
|
492
|
-
if (5 <= pkt.mqtt_level)
|
|
493
|
-
pkt.props = rdr.props();
|
|
494
|
-
return pkt }
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
function _pubxxx_v4(mqtt_reader) {
|
|
498
|
-
mqtt_reader.reasons('pubxxx',
|
|
499
|
-
// MQTT 3.1.1
|
|
500
|
-
[ 0x00, 'Success' ],
|
|
501
|
-
[ 0x92, 'Packet Identifier not found' ],
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
function mqtt_decode_subscribe(ns, mqtt_reader) {
|
|
506
|
-
class _subscription_options_ extends Number {
|
|
507
|
-
get qos() { return this & 0x3 }
|
|
508
|
-
get retain() { return this & 0x4 !== 0 }
|
|
509
|
-
get retain_handling() { return (this >> 2) & 0x3 }
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
return ns[0x8] = (pkt, u8_body) => {
|
|
513
|
-
let rdr = mqtt_reader.of(u8_body);
|
|
514
|
-
|
|
515
|
-
pkt.pkt_id = rdr.u16();
|
|
516
|
-
if (5 <= pkt.mqtt_level)
|
|
517
|
-
pkt.props = rdr.props();
|
|
518
|
-
|
|
519
|
-
let topic, opts, topic_list = pkt.topics = [];
|
|
520
|
-
while (rdr.has_more()) {
|
|
521
|
-
topic = rdr.utf8();
|
|
522
|
-
opts = rdr.flags(_subscription_options_);
|
|
523
|
-
topic_list.push({topic, opts});
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
return pkt }
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
function _mqtt_decode_suback(mqtt_reader) {
|
|
530
|
-
return (pkt, u8_body) => {
|
|
531
|
-
let rdr = mqtt_reader.of(u8_body);
|
|
532
|
-
|
|
533
|
-
pkt.pkt_id = rdr.u16();
|
|
534
|
-
if (5 <= pkt.mqtt_level)
|
|
535
|
-
pkt.props = rdr.props();
|
|
536
|
-
|
|
537
|
-
let answers = pkt.answers = [];
|
|
538
|
-
while (rdr.has_more())
|
|
539
|
-
answers.push(
|
|
540
|
-
rdr.reason(pkt.type) );
|
|
541
|
-
|
|
542
|
-
return pkt }
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
function mqtt_decode_suback(ns, mqtt_reader) {
|
|
546
|
-
return ns[0x9] = _mqtt_decode_suback(mqtt_reader)
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
function _suback_v4(mqtt_reader) {
|
|
550
|
-
mqtt_reader.reasons('suback',
|
|
551
|
-
// MQTT 3.1.1
|
|
552
|
-
[ 0x00, 'Granted QoS 0'],
|
|
553
|
-
[ 0x01, 'Granted QoS 1'],
|
|
554
|
-
[ 0x02, 'Granted QoS 2'],
|
|
555
|
-
);
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
function _suback_v5(mqtt_reader) {
|
|
559
|
-
_suback_v4(mqtt_reader);
|
|
560
|
-
|
|
561
|
-
mqtt_reader.reasons('suback',
|
|
562
|
-
// MQTT 5.0
|
|
563
|
-
[ 0x80, 'Unspecified error'],
|
|
564
|
-
[ 0x83, 'Implementation specific error'],
|
|
565
|
-
[ 0x87, 'Not authorized'],
|
|
566
|
-
[ 0x8F, 'Topic Filter invalid'],
|
|
567
|
-
[ 0x91, 'Packet Identifier in use'],
|
|
568
|
-
[ 0x97, 'Quota exceeded'],
|
|
569
|
-
[ 0x9E, 'Shared Subscriptions not supported'],
|
|
570
|
-
[ 0xA1, 'Subscription Identifiers not supported'],
|
|
571
|
-
[ 0xA2, 'Wildcard Subscriptions not supported'],
|
|
572
|
-
);
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
function mqtt_decode_unsubscribe(ns, mqtt_reader) {
|
|
576
|
-
return ns[0xa] = (pkt, u8_body) => {
|
|
577
|
-
let rdr = mqtt_reader.of(u8_body);
|
|
578
|
-
|
|
579
|
-
pkt.pkt_id = rdr.u16();
|
|
580
|
-
if (5 <= pkt.mqtt_level)
|
|
581
|
-
pkt.props = rdr.props();
|
|
582
|
-
|
|
583
|
-
let topic_list = pkt.topics = [];
|
|
584
|
-
while (rdr.has_more())
|
|
585
|
-
topic_list.push(rdr.utf8());
|
|
586
|
-
|
|
587
|
-
return pkt }
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
function mqtt_decode_unsuback(ns, mqtt_reader) {
|
|
591
|
-
return ns[0xb] = _mqtt_decode_suback(mqtt_reader)
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
function _unsuback_v4(mqtt_reader) {
|
|
595
|
-
mqtt_reader.reasons('unsuback',
|
|
596
|
-
// MQTT 3.1.1
|
|
597
|
-
[ 0x00, 'Success'],
|
|
598
|
-
[ 0x11, 'No subscription existed'],
|
|
599
|
-
[ 0x80, 'Unspecified error'],
|
|
600
|
-
[ 0x83, 'Implementation specific error'],
|
|
601
|
-
[ 0x87, 'Not authorized'],
|
|
602
|
-
[ 0x8F, 'Topic Filter invalid'],
|
|
603
|
-
[ 0x91, 'Packet Identifier in use'],
|
|
604
|
-
);
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
function mqtt_decode_pingxxx(ns) {
|
|
608
|
-
return ns[0xc] = ns[0xd] = pkt => pkt
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
function mqtt_decode_disconnect(ns, mqtt_reader) {
|
|
612
|
-
return ns[0xe] = (pkt, u8_body) => {
|
|
613
|
-
if (u8_body && 5 <= pkt.mqtt_level) {
|
|
614
|
-
let rdr = mqtt_reader.of(u8_body);
|
|
615
|
-
pkt.reason = rdr.reason(pkt.type);
|
|
616
|
-
pkt.props = rdr.props();
|
|
617
|
-
}
|
|
618
|
-
return pkt }
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
function _disconnect_v5(mqtt_reader) {
|
|
623
|
-
mqtt_reader.reasons('disconnect',
|
|
624
|
-
// MQTT 5.0
|
|
625
|
-
[ 0x00, 'Normal disconnection'],
|
|
626
|
-
[ 0x04, 'Disconnect with Will Message'],
|
|
627
|
-
[ 0x80, 'Unspecified error'],
|
|
628
|
-
[ 0x81, 'Malformed Packet'],
|
|
629
|
-
[ 0x82, 'Protocol Error'],
|
|
630
|
-
[ 0x83, 'Implementation specific error'],
|
|
631
|
-
[ 0x87, 'Not authorized'],
|
|
632
|
-
[ 0x89, 'Server busy'],
|
|
633
|
-
[ 0x8B, 'Server shutting down'],
|
|
634
|
-
[ 0x8D, 'Keep Alive timeout'],
|
|
635
|
-
[ 0x8E, 'Session taken over'],
|
|
636
|
-
[ 0x8F, 'Topic Filter invalid'],
|
|
637
|
-
[ 0x90, 'Topic Name invalid'],
|
|
638
|
-
[ 0x93, 'Receive Maximum exceeded'],
|
|
639
|
-
[ 0x94, 'Topic Alias invalid'],
|
|
640
|
-
[ 0x95, 'Packet too large'],
|
|
641
|
-
[ 0x96, 'Message rate too high'],
|
|
642
|
-
[ 0x97, 'Quota exceeded'],
|
|
643
|
-
[ 0x98, 'Administrative action'],
|
|
644
|
-
[ 0x99, 'Payload format invalid'],
|
|
645
|
-
[ 0x9A, 'Retain not supported'],
|
|
646
|
-
[ 0x9B, 'QoS not supported'],
|
|
647
|
-
[ 0x9C, 'Use another server'],
|
|
648
|
-
[ 0x9D, 'Server moved'],
|
|
649
|
-
[ 0x9E, 'Shared Subscriptions not supported'],
|
|
650
|
-
[ 0x9F, 'Connection rate exceeded'],
|
|
651
|
-
[ 0xA0, 'Maximum connect time'],
|
|
652
|
-
[ 0xA1, 'Subscription Identifiers not supported'],
|
|
653
|
-
[ 0xA2, 'Wildcard Subscriptions not supported'],
|
|
654
|
-
);
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
function mqtt_decode_auth(ns, mqtt_reader) {
|
|
658
|
-
return ns[0xf] = (pkt, u8_body) => {
|
|
659
|
-
if ( 5 <= pkt.mqtt_level ) {
|
|
660
|
-
let rdr = mqtt_reader.of(u8_body);
|
|
661
|
-
pkt.reason = rdr.reason(pkt.type);
|
|
662
|
-
pkt.props = rdr.props();
|
|
663
|
-
}
|
|
664
|
-
return pkt }
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
function _auth_v5(mqtt_reader) {
|
|
669
|
-
mqtt_reader.reasons('auth',
|
|
670
|
-
// MQTT 5.0
|
|
671
|
-
[ 0x00, 'Success' ],
|
|
672
|
-
[ 0x18, 'Continue authentication' ],
|
|
673
|
-
[ 0x19, 'Re-authenticate' ],
|
|
674
|
-
);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
379
|
function mqtt_encode_connect(ns, mqtt_writer) {
|
|
678
380
|
const _c_mqtt_proto = new Uint8Array([
|
|
679
381
|
0, 4, 0x4d, 0x51, 0x54, 0x54 ]);
|
|
@@ -692,7 +394,7 @@ function mqtt_encode_connect(ns, mqtt_writer) {
|
|
|
692
394
|
| ( will.retain ? 0x20 : 0 );
|
|
693
395
|
|
|
694
396
|
return ns.connect = ( mqtt_level, pkt ) => {
|
|
695
|
-
let wrt = mqtt_writer.
|
|
397
|
+
let wrt = mqtt_writer.for(pkt);
|
|
696
398
|
|
|
697
399
|
wrt.push(_c_mqtt_proto);
|
|
698
400
|
wrt.u8( mqtt_level );
|
|
@@ -730,12 +432,61 @@ function mqtt_encode_connect(ns, mqtt_writer) {
|
|
|
730
432
|
}
|
|
731
433
|
}
|
|
732
434
|
|
|
435
|
+
function mqtt_decode_connect(ns, mqtt_reader) {
|
|
436
|
+
class _connect_flags_ extends Number {
|
|
437
|
+
get reserved() { return this & 0x01 !== 0 }
|
|
438
|
+
get clean_start() { return this & 0x02 !== 0 }
|
|
439
|
+
get will_flag() { return this & 0x04 !== 0 }
|
|
440
|
+
get will_qos() { return (this >>> 3) & 0x3 }
|
|
441
|
+
get will_retain() { return this & 0x20 !== 0 }
|
|
442
|
+
get password() { return this & 0x40 !== 0 }
|
|
443
|
+
get username() { return this & 0x80 !== 0 }
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return ns[0x1] = (pkt, u8_body) => {
|
|
447
|
+
let rdr = mqtt_reader.for(pkt, u8_body);
|
|
448
|
+
if ('MQTT' !== rdr.utf8())
|
|
449
|
+
throw new Error('Invalid mqtt_connect packet')
|
|
450
|
+
|
|
451
|
+
pkt.__proto__.mqtt_level =
|
|
452
|
+
pkt.mqtt_level = rdr.u8();
|
|
453
|
+
|
|
454
|
+
let flags = pkt.flags =
|
|
455
|
+
rdr.flags(_connect_flags_);
|
|
456
|
+
|
|
457
|
+
pkt.keep_alive = rdr.u16();
|
|
458
|
+
|
|
459
|
+
if (5 <= pkt.mqtt_level)
|
|
460
|
+
pkt.props = rdr.props();
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
pkt.client_id = rdr.utf8();
|
|
465
|
+
if (flags.will_flag) {
|
|
466
|
+
let will = pkt.will = {};
|
|
467
|
+
if (5 <= pkt.mqtt_level)
|
|
468
|
+
will.props = rdr.props();
|
|
469
|
+
|
|
470
|
+
will.topic = rdr.utf8();
|
|
471
|
+
will.payload = rdr.bin();
|
|
472
|
+
will.qos = flags.will_qos;
|
|
473
|
+
will.retain = flags.will_retain;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (flags.username)
|
|
477
|
+
pkt.username = rdr.utf8();
|
|
478
|
+
|
|
479
|
+
if (flags.password)
|
|
480
|
+
pkt.password = rdr.bin();
|
|
481
|
+
return pkt }
|
|
482
|
+
}
|
|
483
|
+
|
|
733
484
|
function mqtt_encode_connack(ns, mqtt_writer) {
|
|
734
485
|
const _enc_flags_connack = flags =>
|
|
735
486
|
flags.session_present ? 1 : 0;
|
|
736
487
|
|
|
737
488
|
return ns.connack = (mqtt_level, pkt) => {
|
|
738
|
-
let wrt = mqtt_writer.
|
|
489
|
+
let wrt = mqtt_writer.for(pkt);
|
|
739
490
|
|
|
740
491
|
wrt.flags( pkt.flags, _enc_flags_connack );
|
|
741
492
|
|
|
@@ -751,10 +502,28 @@ function mqtt_encode_connack(ns, mqtt_writer) {
|
|
|
751
502
|
}
|
|
752
503
|
}
|
|
753
504
|
|
|
505
|
+
|
|
506
|
+
function mqtt_decode_connack(ns, mqtt_reader) {
|
|
507
|
+
class _connack_flags_ extends Number {
|
|
508
|
+
get session_present() { return this & 0x01 !== 0 }
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
return ns[0x2] = (pkt, u8_body) => {
|
|
512
|
+
let rdr = mqtt_reader.for(pkt, u8_body);
|
|
513
|
+
|
|
514
|
+
pkt.flags =
|
|
515
|
+
rdr.flags(_connack_flags_);
|
|
516
|
+
|
|
517
|
+
pkt.reason = rdr.reason(pkt.type);
|
|
518
|
+
if (5 <= pkt.mqtt_level)
|
|
519
|
+
pkt.props = rdr.props();
|
|
520
|
+
return pkt }
|
|
521
|
+
}
|
|
522
|
+
|
|
754
523
|
function mqtt_encode_publish(ns, mqtt_writer) {
|
|
755
524
|
return ns.publish = ( mqtt_level, pkt ) => {
|
|
756
525
|
let qos = (pkt.qos & 0x3) << 1;
|
|
757
|
-
let wrt = mqtt_writer.
|
|
526
|
+
let wrt = mqtt_writer.for(pkt);
|
|
758
527
|
|
|
759
528
|
wrt.utf8(pkt.topic);
|
|
760
529
|
if (0 !== qos)
|
|
@@ -772,9 +541,28 @@ function mqtt_encode_publish(ns, mqtt_writer) {
|
|
|
772
541
|
}
|
|
773
542
|
}
|
|
774
543
|
|
|
544
|
+
function mqtt_decode_publish(ns, mqtt_reader) {
|
|
545
|
+
return ns[0x3] = (pkt, u8_body) => {
|
|
546
|
+
let {hdr} = pkt;
|
|
547
|
+
pkt.dup = Boolean(hdr & 0x8);
|
|
548
|
+
pkt.retain = Boolean(hdr & 0x1);
|
|
549
|
+
let qos = pkt.qos = (hdr>>1) & 0x3;
|
|
550
|
+
|
|
551
|
+
let rdr = mqtt_reader.for(pkt, u8_body);
|
|
552
|
+
pkt.topic = rdr.utf8();
|
|
553
|
+
if (0 !== qos)
|
|
554
|
+
pkt.pkt_id = rdr.u16();
|
|
555
|
+
|
|
556
|
+
if (5 <= pkt.mqtt_level)
|
|
557
|
+
pkt.props = rdr.props();
|
|
558
|
+
|
|
559
|
+
pkt.payload = rdr.flush();
|
|
560
|
+
return pkt }
|
|
561
|
+
}
|
|
562
|
+
|
|
775
563
|
function mqtt_encode_puback(ns, mqtt_writer) {
|
|
776
564
|
return ns.puback = ( mqtt_level, pkt ) => {
|
|
777
|
-
let wrt = mqtt_writer.
|
|
565
|
+
let wrt = mqtt_writer.for(pkt);
|
|
778
566
|
|
|
779
567
|
wrt.u16(pkt.pkt_id);
|
|
780
568
|
if (5 <= mqtt_level) {
|
|
@@ -786,6 +574,20 @@ function mqtt_encode_puback(ns, mqtt_writer) {
|
|
|
786
574
|
}
|
|
787
575
|
}
|
|
788
576
|
|
|
577
|
+
|
|
578
|
+
function mqtt_decode_puback(ns, mqtt_reader) {
|
|
579
|
+
return ns[0x4] = (pkt, u8_body) => {
|
|
580
|
+
let rdr = mqtt_reader.for(pkt, u8_body);
|
|
581
|
+
|
|
582
|
+
pkt.pkt_id = rdr.u16();
|
|
583
|
+
if (5 <= pkt.mqtt_level) {
|
|
584
|
+
pkt.reason = rdr.reason(pkt.type);
|
|
585
|
+
pkt.props = rdr.props();
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
return pkt }
|
|
589
|
+
}
|
|
590
|
+
|
|
789
591
|
function mqtt_encode_pubxxx(ns, mqtt_writer) {
|
|
790
592
|
ns.pubrec = _enc_pubxxx(0x50);
|
|
791
593
|
ns.pubrel = _enc_pubxxx(0x62);
|
|
@@ -794,7 +596,7 @@ function mqtt_encode_pubxxx(ns, mqtt_writer) {
|
|
|
794
596
|
|
|
795
597
|
function _enc_pubxxx(hdr) {
|
|
796
598
|
return ( mqtt_level, pkt ) => {
|
|
797
|
-
let wrt = mqtt_writer.
|
|
599
|
+
let wrt = mqtt_writer.for(pkt);
|
|
798
600
|
|
|
799
601
|
wrt.u16(pkt.pkt_id);
|
|
800
602
|
if (5 <= mqtt_level) {
|
|
@@ -810,6 +612,17 @@ function mqtt_encode_pubxxx(ns, mqtt_writer) {
|
|
|
810
612
|
}
|
|
811
613
|
}
|
|
812
614
|
|
|
615
|
+
function mqtt_decode_pubxxx(ns, mqtt_reader) {
|
|
616
|
+
return ns[0x5] = ns[0x6] = ns[0x7] = (pkt, u8_body) => {
|
|
617
|
+
let rdr = mqtt_reader.for(pkt, u8_body);
|
|
618
|
+
|
|
619
|
+
pkt.pkt_id = rdr.u16();
|
|
620
|
+
pkt.reason = rdr.reason('pubxxx', mqtt_reader);
|
|
621
|
+
if (5 <= pkt.mqtt_level)
|
|
622
|
+
pkt.props = rdr.props();
|
|
623
|
+
return pkt }
|
|
624
|
+
}
|
|
625
|
+
|
|
813
626
|
function mqtt_encode_subscribe(ns, mqtt_writer) {
|
|
814
627
|
const _enc_subscribe_flags = opts => 0
|
|
815
628
|
| ( opts.qos & 0x3 )
|
|
@@ -817,7 +630,7 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
|
|
|
817
630
|
| ( (opts.retain_handling & 0x3) << 2 );
|
|
818
631
|
|
|
819
632
|
return ns.subscribe = ( mqtt_level, pkt ) => {
|
|
820
|
-
let wrt = mqtt_writer.
|
|
633
|
+
let wrt = mqtt_writer.for(pkt);
|
|
821
634
|
|
|
822
635
|
wrt.u16(pkt.pkt_id);
|
|
823
636
|
if (5 <= mqtt_level)
|
|
@@ -843,6 +656,30 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
|
|
|
843
656
|
}
|
|
844
657
|
}
|
|
845
658
|
|
|
659
|
+
function mqtt_decode_subscribe(ns, mqtt_reader) {
|
|
660
|
+
class _subscription_options_ extends Number {
|
|
661
|
+
get qos() { return this & 0x3 }
|
|
662
|
+
get retain() { return this & 0x4 !== 0 }
|
|
663
|
+
get retain_handling() { return (this >> 2) & 0x3 }
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
return ns[0x8] = (pkt, u8_body) => {
|
|
667
|
+
let rdr = mqtt_reader.for(pkt, u8_body);
|
|
668
|
+
|
|
669
|
+
pkt.pkt_id = rdr.u16();
|
|
670
|
+
if (5 <= pkt.mqtt_level)
|
|
671
|
+
pkt.props = rdr.props();
|
|
672
|
+
|
|
673
|
+
let topic, opts, topic_list = pkt.topics = [];
|
|
674
|
+
while (rdr.has_more()) {
|
|
675
|
+
topic = rdr.utf8();
|
|
676
|
+
opts = rdr.flags(_subscription_options_);
|
|
677
|
+
topic_list.push({topic, opts});
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
return pkt }
|
|
681
|
+
}
|
|
682
|
+
|
|
846
683
|
function mqtt_encode_xxsuback(ns, mqtt_writer) {
|
|
847
684
|
ns.suback = _enc_xxsuback(0x90);
|
|
848
685
|
ns.unsuback = _enc_xxsuback(0xb0);
|
|
@@ -850,7 +687,7 @@ function mqtt_encode_xxsuback(ns, mqtt_writer) {
|
|
|
850
687
|
|
|
851
688
|
function _enc_xxsuback(hdr) {
|
|
852
689
|
return ( mqtt_level, pkt ) => {
|
|
853
|
-
let wrt = mqtt_writer.
|
|
690
|
+
let wrt = mqtt_writer.for(pkt);
|
|
854
691
|
|
|
855
692
|
wrt.u16(pkt.pkt_id);
|
|
856
693
|
if (5 <= mqtt_level)
|
|
@@ -864,9 +701,26 @@ function mqtt_encode_xxsuback(ns, mqtt_writer) {
|
|
|
864
701
|
}
|
|
865
702
|
}
|
|
866
703
|
|
|
704
|
+
|
|
705
|
+
function mqtt_decode_xxsuback(ns, mqtt_reader) {
|
|
706
|
+
return ns[0x9] = ns[0xb] = (pkt, u8_body) => {
|
|
707
|
+
let rdr = mqtt_reader.for(pkt, u8_body);
|
|
708
|
+
|
|
709
|
+
pkt.pkt_id = rdr.u16();
|
|
710
|
+
if (5 <= pkt.mqtt_level)
|
|
711
|
+
pkt.props = rdr.props();
|
|
712
|
+
|
|
713
|
+
let answers = pkt.answers = [];
|
|
714
|
+
while (rdr.has_more())
|
|
715
|
+
answers.push(
|
|
716
|
+
rdr.reason(pkt.type) );
|
|
717
|
+
|
|
718
|
+
return pkt }
|
|
719
|
+
}
|
|
720
|
+
|
|
867
721
|
function mqtt_encode_unsubscribe(ns, mqtt_writer) {
|
|
868
722
|
return ns.unsubscribe = ( mqtt_level, pkt ) => {
|
|
869
|
-
let wrt = mqtt_writer.
|
|
723
|
+
let wrt = mqtt_writer.for(pkt);
|
|
870
724
|
|
|
871
725
|
wrt.u16(pkt.pkt_id);
|
|
872
726
|
if (5 <= mqtt_level)
|
|
@@ -879,14 +733,34 @@ function mqtt_encode_unsubscribe(ns, mqtt_writer) {
|
|
|
879
733
|
}
|
|
880
734
|
}
|
|
881
735
|
|
|
736
|
+
function mqtt_decode_unsubscribe(ns, mqtt_reader) {
|
|
737
|
+
return ns[0xa] = (pkt, u8_body) => {
|
|
738
|
+
let rdr = mqtt_reader.for(pkt, u8_body);
|
|
739
|
+
|
|
740
|
+
pkt.pkt_id = rdr.u16();
|
|
741
|
+
if (5 <= pkt.mqtt_level)
|
|
742
|
+
pkt.props = rdr.props();
|
|
743
|
+
|
|
744
|
+
let topic_list = pkt.topics = [];
|
|
745
|
+
while (rdr.has_more())
|
|
746
|
+
topic_list.push(rdr.utf8());
|
|
747
|
+
|
|
748
|
+
return pkt }
|
|
749
|
+
}
|
|
750
|
+
|
|
882
751
|
function mqtt_encode_pingxxx(ns) {
|
|
883
752
|
ns.pingreq = () => new Uint8Array([ 0xc0, 0 ]);
|
|
884
753
|
ns.pingresp = () => new Uint8Array([ 0xd0, 0 ]);
|
|
885
754
|
}
|
|
886
755
|
|
|
756
|
+
|
|
757
|
+
function mqtt_decode_pingxxx(ns) {
|
|
758
|
+
return ns[0xc] = ns[0xd] = pkt => pkt
|
|
759
|
+
}
|
|
760
|
+
|
|
887
761
|
function mqtt_encode_disconnect(ns, mqtt_writer) {
|
|
888
762
|
return ns.disconnect = ( mqtt_level, pkt ) => {
|
|
889
|
-
let wrt = mqtt_writer.
|
|
763
|
+
let wrt = mqtt_writer.for(pkt);
|
|
890
764
|
|
|
891
765
|
if (pkt && 5 <= mqtt_level) {
|
|
892
766
|
if (pkt.reason || pkt.props) {
|
|
@@ -899,6 +773,17 @@ function mqtt_encode_disconnect(ns, mqtt_writer) {
|
|
|
899
773
|
}
|
|
900
774
|
}
|
|
901
775
|
|
|
776
|
+
|
|
777
|
+
function mqtt_decode_disconnect(ns, mqtt_reader) {
|
|
778
|
+
return ns[0xe] = (pkt, u8_body) => {
|
|
779
|
+
if (u8_body && 5 <= pkt.mqtt_level) {
|
|
780
|
+
let rdr = mqtt_reader.for(pkt, u8_body);
|
|
781
|
+
pkt.reason = rdr.reason(pkt.type);
|
|
782
|
+
pkt.props = rdr.props();
|
|
783
|
+
}
|
|
784
|
+
return pkt }
|
|
785
|
+
}
|
|
786
|
+
|
|
902
787
|
function mqtt_encode_auth(ns, mqtt_writer) {
|
|
903
788
|
return ns.auth = ( mqtt_level, pkt ) => {
|
|
904
789
|
if (5 > mqtt_level)
|
|
@@ -913,17 +798,15 @@ function mqtt_encode_auth(ns, mqtt_writer) {
|
|
|
913
798
|
}
|
|
914
799
|
}
|
|
915
800
|
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
_auth_v5,
|
|
926
|
-
);
|
|
801
|
+
function mqtt_decode_auth(ns, mqtt_reader) {
|
|
802
|
+
return ns[0xf] = (pkt, u8_body) => {
|
|
803
|
+
if ( 5 <= pkt.mqtt_level ) {
|
|
804
|
+
let rdr = mqtt_reader.of(u8_body);
|
|
805
|
+
pkt.reason = rdr.reason(pkt.type);
|
|
806
|
+
pkt.props = rdr.props();
|
|
807
|
+
}
|
|
808
|
+
return pkt }
|
|
809
|
+
}
|
|
927
810
|
|
|
928
811
|
const mqtt_decode_v5 = [
|
|
929
812
|
mqtt_decode_connect,
|
|
@@ -932,9 +815,8 @@ const mqtt_decode_v5 = [
|
|
|
932
815
|
mqtt_decode_puback,
|
|
933
816
|
mqtt_decode_pubxxx,
|
|
934
817
|
mqtt_decode_subscribe,
|
|
935
|
-
|
|
818
|
+
mqtt_decode_xxsuback,
|
|
936
819
|
mqtt_decode_unsubscribe,
|
|
937
|
-
mqtt_decode_unsuback,
|
|
938
820
|
mqtt_decode_pingxxx,
|
|
939
821
|
mqtt_decode_disconnect,
|
|
940
822
|
mqtt_decode_auth,
|
|
@@ -1047,7 +929,10 @@ const with_topic_router = mqtt_topic_router =>
|
|
|
1047
929
|
// alias: unsub_topic
|
|
1048
930
|
unsubscribe_topic(topic_route, ...args) {
|
|
1049
931
|
let router = this.router;
|
|
1050
|
-
|
|
932
|
+
|
|
933
|
+
let fn = args.at(-1)?.call ? args.pop() : null;
|
|
934
|
+
router.remove(topic_route, true, fn);
|
|
935
|
+
|
|
1051
936
|
let topic = router.mqtt_topic(topic_route);
|
|
1052
937
|
return this.unsubscribe(topic, ...args ) }// topic_prefix
|
|
1053
938
|
|
|
@@ -1100,34 +985,38 @@ function mqtt_topic_path_router() {
|
|
|
1100
985
|
if (fn) {throw new TypeError()}
|
|
1101
986
|
fn = _ignore;}
|
|
1102
987
|
|
|
1103
|
-
let
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
pri_lsts[priority ? 0 : 1].push(rte);
|
|
988
|
+
let route = parse(as_topic_path(topic_route));
|
|
989
|
+
route.topic = topic_route;
|
|
990
|
+
route.tgt = fn;
|
|
991
|
+
pri_lsts[priority ? 0 : 1].push(route);
|
|
1108
992
|
return this}
|
|
1109
993
|
|
|
1110
|
-
, remove(
|
|
1111
|
-
let lst = pri_lsts
|
|
1112
|
-
|
|
994
|
+
, remove(query, ...args) {
|
|
995
|
+
let lst = pri_lsts;
|
|
996
|
+
if ('boolean' === typeof args[0]) {
|
|
997
|
+
lst = [pri_lsts[args.shift() ? 0 : 1]];}
|
|
998
|
+
|
|
999
|
+
if ('string' === typeof query) {
|
|
1000
|
+
query ={topic: query, tgt: args.pop()}; }
|
|
1001
|
+
return _route_remove(lst, query)}
|
|
1113
1002
|
|
|
1114
1003
|
, clear(priority) {
|
|
1115
|
-
pri_lsts[priority ? 0 : 1] = [];
|
|
1116
1004
|
if (null == priority) {
|
|
1117
|
-
pri_lsts
|
|
1005
|
+
pri_lsts = [[],[]]; }// null clears both lists
|
|
1006
|
+
else {
|
|
1007
|
+
pri_lsts[priority ? 0 : 1] = [];} }
|
|
1118
1008
|
|
|
1119
1009
|
, async invoke(pkt, ctx) {
|
|
1120
1010
|
ctx.idx = 0;
|
|
1121
1011
|
ctx.rm = rm;
|
|
1122
1012
|
|
|
1123
|
-
for (let [fn, params] of find(pkt.topic)) {
|
|
1013
|
+
for (let [fn, params, route] of find(pkt.topic)) {
|
|
1124
1014
|
let res = await fn(pkt, params, ctx);
|
|
1125
1015
|
|
|
1126
1016
|
if (rm === res) {
|
|
1127
|
-
_route_remove(pri_lsts,
|
|
1017
|
+
_route_remove(pri_lsts, route);}
|
|
1128
1018
|
|
|
1129
|
-
if (ctx.done) {
|
|
1130
|
-
break}
|
|
1019
|
+
if (ctx.done) {break}
|
|
1131
1020
|
else ctx.idx++;}
|
|
1132
1021
|
|
|
1133
1022
|
if (1 === pkt.qos) {
|
|
@@ -1137,70 +1026,68 @@ function mqtt_topic_path_router() {
|
|
|
1137
1026
|
function * _routes_iter(all_route_lists, topic) {
|
|
1138
1027
|
topic = topic.replace(/^[\/]*/, '/'); // ensure '/' prefix for regexparam library
|
|
1139
1028
|
for (let route_list of all_route_lists) {
|
|
1140
|
-
for (let
|
|
1141
|
-
let match = pattern.exec(topic);
|
|
1029
|
+
for (let route of route_list) {
|
|
1030
|
+
let match = route.pattern.exec(topic);
|
|
1142
1031
|
if (match) {
|
|
1143
|
-
let params = keys
|
|
1144
|
-
? keys.reduce(
|
|
1032
|
+
let params = route.keys
|
|
1033
|
+
? route.keys.reduce(
|
|
1145
1034
|
(o, k, i) => (o[k] = match[1+i], o)
|
|
1146
1035
|
, {})
|
|
1147
1036
|
: match.groups ?? match;
|
|
1148
|
-
yield [tgt, params];} } } }
|
|
1037
|
+
yield [route.tgt, params, route];} } } }
|
|
1149
1038
|
|
|
1150
1039
|
|
|
1151
1040
|
function _route_remove(all_route_lists, query) {
|
|
1152
|
-
let
|
|
1153
|
-
route===query
|
|
1154
|
-
|| route.tgt===query
|
|
1155
|
-
|| route.key===query);
|
|
1041
|
+
let ans = false;
|
|
1156
1042
|
for (let lst of all_route_lists) {
|
|
1157
|
-
let
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
n
|
|
1181
|
-
if ( 0x80 & u8[i++] ) {
|
|
1182
|
-
n |= (u8[i] & 0x7f) << 14;
|
|
1183
|
-
if ( 0x80 & u8[i++] ) {
|
|
1184
|
-
n |= (u8[i] & 0x7f) << 21;
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
|
-
return [n, i, i0]
|
|
1043
|
+
let idx_tip = 0;
|
|
1044
|
+
for (let route of lst) {
|
|
1045
|
+
// skip matching routes to remove from compacted list
|
|
1046
|
+
if (route === query) continue
|
|
1047
|
+
if (route.topic === query.topic) {
|
|
1048
|
+
if (null == query.tgt) continue
|
|
1049
|
+
if (route.tgt === query.tgt) continue}
|
|
1050
|
+
|
|
1051
|
+
lst[idx_tip++] = route;}
|
|
1052
|
+
|
|
1053
|
+
// truncate remaining list
|
|
1054
|
+
if (lst.splice(idx_tip).length)
|
|
1055
|
+
ans = true;}
|
|
1056
|
+
|
|
1057
|
+
return ans}
|
|
1058
|
+
|
|
1059
|
+
function decode_varint(u8, i0=0, invalid) {
|
|
1060
|
+
let shift=0, i=i0, b=u8[i++], n=(b & 0x7f);
|
|
1061
|
+
for(; b & 0x80;)
|
|
1062
|
+
n |= ((b=u8[i++]) & 0x7f) << (shift += 7);
|
|
1063
|
+
|
|
1064
|
+
return (u8.length < i)
|
|
1065
|
+
? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
|
|
1066
|
+
: [n, i, i0] // successful value
|
|
1189
1067
|
}
|
|
1190
1068
|
|
|
1191
1069
|
function mqtt_raw_dispatch(opt) {
|
|
1192
|
-
let u8 = new Uint8Array(0);
|
|
1070
|
+
let u8 = new Uint8Array(0), len_tip=0;
|
|
1193
1071
|
return u8_buf => {
|
|
1194
1072
|
u8 = 0 === u8.byteLength
|
|
1195
1073
|
? u8_buf : _u8_join(u8, u8_buf);
|
|
1196
1074
|
|
|
1197
1075
|
let res = [];
|
|
1198
|
-
while (1) {
|
|
1199
|
-
let [len_body, len_vh] = decode_varint(u8, 1);
|
|
1200
|
-
let len_pkt = len_body + len_vh;
|
|
1201
1076
|
|
|
1202
|
-
|
|
1203
|
-
|
|
1077
|
+
// wait for at least len_tip bytes for next (tip) message
|
|
1078
|
+
while ( u8.byteLength >= len_tip ) {
|
|
1079
|
+
|
|
1080
|
+
// if varint is incomplete, return len_body=NaN
|
|
1081
|
+
let [len_body, len_vh] = decode_varint(u8, 1, NaN);
|
|
1082
|
+
let len_pkt = len_body + len_vh; // may be NaN
|
|
1083
|
+
|
|
1084
|
+
if (!( len_pkt <= u8.byteLength )) {
|
|
1085
|
+
// incomplete packet cases:
|
|
1086
|
+
// - len_pkt is less than available bytes
|
|
1087
|
+
// - len_pkt is NaN from decode_varint() due to lack of data
|
|
1088
|
+
len_tip = len_pkt || 0; // 0 when NaN
|
|
1089
|
+
break
|
|
1090
|
+
}
|
|
1204
1091
|
|
|
1205
1092
|
let b0 = u8[0];
|
|
1206
1093
|
let u8_body = 0 === len_body ? null
|
|
@@ -1212,6 +1099,8 @@ function mqtt_raw_dispatch(opt) {
|
|
|
1212
1099
|
if (null != pkt)
|
|
1213
1100
|
res.push( pkt );
|
|
1214
1101
|
}
|
|
1102
|
+
|
|
1103
|
+
return res
|
|
1215
1104
|
}
|
|
1216
1105
|
}
|
|
1217
1106
|
|
|
@@ -1222,16 +1111,17 @@ function _u8_join(a, b) {
|
|
|
1222
1111
|
return r
|
|
1223
1112
|
}
|
|
1224
1113
|
|
|
1225
|
-
const _pkt_types =
|
|
1114
|
+
const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
function mqtt_pkt_ctx(mqtt_level, opts, pkt_api=opts.pkt_ctx) {
|
|
1118
|
+
let _as_pkt_ctx = pkt_api => ({
|
|
1119
|
+
__proto__: pkt_api,
|
|
1120
|
+
get hdr() { return this.b0 & 0xf },
|
|
1121
|
+
get id() { return this.b0 >>> 4 },
|
|
1122
|
+
get type() { return _pkt_types[this.b0 >>> 4] },
|
|
1123
|
+
mqtt_level });
|
|
1226
1124
|
|
|
1227
|
-
function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
|
|
1228
|
-
pkt_ctx = {
|
|
1229
|
-
__proto__: pkt_ctx || opts.pkt_ctx,
|
|
1230
|
-
mqtt_level,
|
|
1231
|
-
get hdr() { return this.b0 & 0xf },
|
|
1232
|
-
get id() { return this.b0 >>> 4 },
|
|
1233
|
-
get type() { return _pkt_types[this.b0 >>> 4] },
|
|
1234
|
-
};
|
|
1235
1125
|
|
|
1236
1126
|
let op, _decode_by_id=[], _encode_by_type={};
|
|
1237
1127
|
for (op of opts.encode_fns)
|
|
@@ -1240,10 +1130,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
|
|
|
1240
1130
|
op(_decode_by_id, opts.mqtt_reader);
|
|
1241
1131
|
|
|
1242
1132
|
return {
|
|
1243
|
-
pkt_ctx,
|
|
1133
|
+
pkt_api, pkt_ctx: _as_pkt_ctx(pkt_api),
|
|
1244
1134
|
|
|
1245
|
-
encode_pkt(type, pkt)
|
|
1246
|
-
|
|
1135
|
+
encode_pkt: (type, pkt) =>
|
|
1136
|
+
_encode_by_type[type]( mqtt_level, pkt ),
|
|
1247
1137
|
|
|
1248
1138
|
decode_pkt(b0, u8_body) {
|
|
1249
1139
|
if (b0.map) // Uint8Array in first arg
|
|
@@ -1252,12 +1142,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
|
|
|
1252
1142
|
let fn_decode = _decode_by_id[b0>>>4] || _decode_by_id[0];
|
|
1253
1143
|
return fn_decode?.({__proto__: this.pkt_ctx, b0}, u8_body) },
|
|
1254
1144
|
|
|
1255
|
-
mqtt_stream() {
|
|
1256
|
-
let self = { __proto__: this, pkt_ctx:
|
|
1257
|
-
self.pkt_ctx._base_ = self.pkt_ctx;
|
|
1145
|
+
mqtt_stream(pkt_api=this.pkt_api) {
|
|
1146
|
+
let self = { __proto__: this, pkt_ctx: _as_pkt_ctx(pkt_api) };
|
|
1258
1147
|
self.decode = mqtt_raw_dispatch(self);
|
|
1259
|
-
return self
|
|
1260
|
-
},
|
|
1148
|
+
return self },
|
|
1261
1149
|
}
|
|
1262
1150
|
}
|
|
1263
1151
|
|
|
@@ -1781,7 +1669,7 @@ class MQTTCore extends MQTTBase {
|
|
|
1781
1669
|
|
|
1782
1670
|
return this} }
|
|
1783
1671
|
|
|
1784
|
-
const version = '0.6.
|
|
1672
|
+
const version = '0.6.4-node';
|
|
1785
1673
|
|
|
1786
1674
|
const MQTTClient_v4 = /* #__PURE__ */
|
|
1787
1675
|
with_topic_path_router(
|