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.
Files changed (108) hide show
  1. package/cjs/basic-v4.cjs +194 -243
  2. package/cjs/basic-v4.cjs.map +1 -1
  3. package/cjs/basic-v5.cjs +247 -368
  4. package/cjs/basic-v5.cjs.map +1 -1
  5. package/cjs/full-v4.cjs +342 -384
  6. package/cjs/full-v4.cjs.map +1 -1
  7. package/cjs/full-v5.cjs +395 -507
  8. package/cjs/full-v5.cjs.map +1 -1
  9. package/cjs/index.cjs +292 -399
  10. package/cjs/index.cjs.map +1 -1
  11. package/cjs/v4.cjs +239 -274
  12. package/cjs/v4.cjs.map +1 -1
  13. package/cjs/v5.cjs +292 -399
  14. package/cjs/v5.cjs.map +1 -1
  15. package/code/router_path.jsy +39 -28
  16. package/code/with_topic_router.jsy +4 -1
  17. package/esm/basic-v4.js +194 -243
  18. package/esm/basic-v4.js.map +1 -1
  19. package/esm/basic-v5.js +247 -368
  20. package/esm/basic-v5.js.map +1 -1
  21. package/esm/deno/basic-v4.js +194 -243
  22. package/esm/deno/basic-v4.js.map +1 -1
  23. package/esm/deno/basic-v5.js +247 -368
  24. package/esm/deno/basic-v5.js.map +1 -1
  25. package/esm/deno/full-v4.js +342 -384
  26. package/esm/deno/full-v4.js.map +1 -1
  27. package/esm/deno/full-v5.js +395 -507
  28. package/esm/deno/full-v5.js.map +1 -1
  29. package/esm/deno/index.js +292 -399
  30. package/esm/deno/index.js.map +1 -1
  31. package/esm/deno/v4.js +239 -274
  32. package/esm/deno/v4.js.map +1 -1
  33. package/esm/deno/v5.js +292 -399
  34. package/esm/deno/v5.js.map +1 -1
  35. package/esm/full-v4.js +342 -384
  36. package/esm/full-v4.js.map +1 -1
  37. package/esm/full-v5.js +395 -507
  38. package/esm/full-v5.js.map +1 -1
  39. package/esm/index.js +292 -399
  40. package/esm/index.js.map +1 -1
  41. package/esm/node/basic-v4.js +194 -243
  42. package/esm/node/basic-v4.js.map +1 -1
  43. package/esm/node/basic-v4.mjs +194 -243
  44. package/esm/node/basic-v4.mjs.map +1 -1
  45. package/esm/node/basic-v5.js +247 -368
  46. package/esm/node/basic-v5.js.map +1 -1
  47. package/esm/node/basic-v5.mjs +247 -368
  48. package/esm/node/basic-v5.mjs.map +1 -1
  49. package/esm/node/full-v4.js +342 -384
  50. package/esm/node/full-v4.js.map +1 -1
  51. package/esm/node/full-v4.mjs +342 -384
  52. package/esm/node/full-v4.mjs.map +1 -1
  53. package/esm/node/full-v5.js +395 -507
  54. package/esm/node/full-v5.js.map +1 -1
  55. package/esm/node/full-v5.mjs +395 -507
  56. package/esm/node/full-v5.mjs.map +1 -1
  57. package/esm/node/index.js +292 -399
  58. package/esm/node/index.js.map +1 -1
  59. package/esm/node/index.mjs +292 -399
  60. package/esm/node/index.mjs.map +1 -1
  61. package/esm/node/v4.js +239 -274
  62. package/esm/node/v4.js.map +1 -1
  63. package/esm/node/v4.mjs +239 -274
  64. package/esm/node/v4.mjs.map +1 -1
  65. package/esm/node/v5.js +292 -399
  66. package/esm/node/v5.js.map +1 -1
  67. package/esm/node/v5.mjs +292 -399
  68. package/esm/node/v5.mjs.map +1 -1
  69. package/esm/v4.js +239 -274
  70. package/esm/v4.js.map +1 -1
  71. package/esm/v5.js +292 -399
  72. package/esm/v5.js.map +1 -1
  73. package/esm/web/basic-v4.js +194 -243
  74. package/esm/web/basic-v4.js.map +1 -1
  75. package/esm/web/basic-v4.min.js +1 -1
  76. package/esm/web/basic-v4.min.js.br +0 -0
  77. package/esm/web/basic-v4.min.js.gz +0 -0
  78. package/esm/web/basic-v5.js +247 -368
  79. package/esm/web/basic-v5.js.map +1 -1
  80. package/esm/web/basic-v5.min.js +1 -1
  81. package/esm/web/basic-v5.min.js.br +0 -0
  82. package/esm/web/basic-v5.min.js.gz +0 -0
  83. package/esm/web/full-v4.js +342 -384
  84. package/esm/web/full-v4.js.map +1 -1
  85. package/esm/web/full-v4.min.js +1 -1
  86. package/esm/web/full-v4.min.js.br +0 -0
  87. package/esm/web/full-v4.min.js.gz +0 -0
  88. package/esm/web/full-v5.js +395 -507
  89. package/esm/web/full-v5.js.map +1 -1
  90. package/esm/web/full-v5.min.js +1 -1
  91. package/esm/web/full-v5.min.js.br +0 -0
  92. package/esm/web/full-v5.min.js.gz +0 -0
  93. package/esm/web/index.js +292 -399
  94. package/esm/web/index.js.map +1 -1
  95. package/esm/web/index.min.js +1 -1
  96. package/esm/web/index.min.js.br +0 -0
  97. package/esm/web/index.min.js.gz +0 -0
  98. package/esm/web/v4.js +239 -274
  99. package/esm/web/v4.js.map +1 -1
  100. package/esm/web/v4.min.js +1 -1
  101. package/esm/web/v4.min.js.br +0 -0
  102. package/esm/web/v4.min.js.gz +0 -0
  103. package/esm/web/v5.js +292 -399
  104. package/esm/web/v5.js.map +1 -1
  105. package/esm/web/v5.min.js +1 -1
  106. package/esm/web/v5.min.js.br +0 -0
  107. package/esm/web/v5.min.js.gz +0 -0
  108. package/package.json +5 -5
@@ -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
- do {
6
- const ni = n & 0x7f;
7
- n >>>= 7;
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
- export function decode_varint_loop(u8, i=0) {
16
- let i0 = i
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 U8_Reason extends Number {
87
- static of(v, pkt_kind, by_kind) {
88
- let self = new this(v);
89
- self.reason = by_kind?.[pkt_kind]?.get(v) || pkt_kind;
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 of(buf) { return this.prototype.of(buf) }
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 U8_Reason.of(v, pkt_kind, this._reasons_by)
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 mqtt_reader_info(mqtt_reader, ... info_fn_list) {
198
- mqtt_reader = class extends mqtt_reader {
199
- static reasons(pkt_type, ...reason_entries) {
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
- let lut = (proto._reasons_by[pkt_type] ||= new Map());
204
- for (let [u8, reason] of reason_entries)
205
- lut.set( u8, reason );
206
-
207
- return this
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
- return mqtt_reader
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 of() { return this.prototype.of() }
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.of(pkt);
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.of(pkt);
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.of(pkt);
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.of(pkt);
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.of(pkt);
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.of(pkt);
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.of(pkt);
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.of(pkt);
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.of(pkt);
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
- const mqtt_reader_v5 = /* #__PURE__ */
917
- mqtt_reader_info(
918
- mqtt_reader_v5$1,
919
- _connack_v5,
920
- _puback_v5,
921
- _pubxxx_v4,
922
- _suback_v5,
923
- _unsuback_v4,
924
- _disconnect_v5,
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
- mqtt_decode_suback,
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
- router.remove(topic_route, true);
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 rte = parse(as_topic_path(topic_route));
1104
-
1105
- rte.key = topic_route;
1106
- rte.tgt = fn;
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(topic_route, priority) {
1111
- let lst = pri_lsts[priority ? 0 : 1];
1112
- return _route_remove([lst], topic_route)}
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[1] = []; } }// null clears both lists
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, fn);}
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 {keys, pattern, tgt} of route_list) {
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 fn_match = route =>(
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 i = lst.findIndex(fn_match);
1158
- if (0 <= i) {
1159
- lst.splice(i,1);
1160
- return true} }
1161
- return false}
1162
-
1163
- /*
1164
- export function decode_varint_loop(u8, i=0) {
1165
- let i0 = i
1166
- let shift = 0, n = (u8[i] & 0x7f)
1167
- while ( 0x80 & u8[i++] )
1168
- n |= (u8[i] & 0x7f) << (shift += 7)
1169
-
1170
- return [n, i, i0]
1171
- }
1172
- */
1173
-
1174
-
1175
- function decode_varint(u8, i=0) {
1176
- let i0 = i;
1177
- // unrolled for a max of 4 chains
1178
- let n = (u8[i] & 0x7f) << 0;
1179
- if ( 0x80 & u8[i++] ) {
1180
- n |= (u8[i] & 0x7f) << 7;
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
- if ( u8.byteLength < len_pkt )
1203
- return res
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 = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
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
- return _encode_by_type[type]( mqtt_level, pkt ) },
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: { __proto__: 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.2-node';
1672
+ const version = '0.6.4-node';
1785
1673
 
1786
1674
  const MQTTClient_v4 = /* #__PURE__ */
1787
1675
  with_topic_path_router(