u8-mqtt 0.6.1 → 0.6.3

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 (106) 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 +264 -385
  4. package/cjs/basic-v5.cjs.map +1 -1
  5. package/cjs/full-v4.cjs +297 -353
  6. package/cjs/full-v4.cjs.map +1 -1
  7. package/cjs/full-v5.cjs +366 -492
  8. package/cjs/full-v5.cjs.map +1 -1
  9. package/cjs/index.cjs +263 -384
  10. package/cjs/index.cjs.map +1 -1
  11. package/cjs/v4.cjs +194 -243
  12. package/cjs/v4.cjs.map +1 -1
  13. package/cjs/v5.cjs +263 -384
  14. package/cjs/v5.cjs.map +1 -1
  15. package/esm/basic-v4.js +194 -243
  16. package/esm/basic-v4.js.map +1 -1
  17. package/esm/basic-v5.js +264 -385
  18. package/esm/basic-v5.js.map +1 -1
  19. package/esm/deno/basic-v4.js +194 -243
  20. package/esm/deno/basic-v4.js.map +1 -1
  21. package/esm/deno/basic-v5.js +264 -385
  22. package/esm/deno/basic-v5.js.map +1 -1
  23. package/esm/deno/full-v4.js +297 -353
  24. package/esm/deno/full-v4.js.map +1 -1
  25. package/esm/deno/full-v5.js +366 -492
  26. package/esm/deno/full-v5.js.map +1 -1
  27. package/esm/deno/index.js +263 -384
  28. package/esm/deno/index.js.map +1 -1
  29. package/esm/deno/v4.js +194 -243
  30. package/esm/deno/v4.js.map +1 -1
  31. package/esm/deno/v5.js +263 -384
  32. package/esm/deno/v5.js.map +1 -1
  33. package/esm/full-v4.js +297 -353
  34. package/esm/full-v4.js.map +1 -1
  35. package/esm/full-v5.js +366 -492
  36. package/esm/full-v5.js.map +1 -1
  37. package/esm/index.js +263 -384
  38. package/esm/index.js.map +1 -1
  39. package/esm/node/basic-v4.js +194 -243
  40. package/esm/node/basic-v4.js.map +1 -1
  41. package/esm/node/basic-v4.mjs +194 -243
  42. package/esm/node/basic-v4.mjs.map +1 -1
  43. package/esm/node/basic-v5.js +264 -385
  44. package/esm/node/basic-v5.js.map +1 -1
  45. package/esm/node/basic-v5.mjs +264 -385
  46. package/esm/node/basic-v5.mjs.map +1 -1
  47. package/esm/node/full-v4.js +297 -353
  48. package/esm/node/full-v4.js.map +1 -1
  49. package/esm/node/full-v4.mjs +297 -353
  50. package/esm/node/full-v4.mjs.map +1 -1
  51. package/esm/node/full-v5.js +366 -492
  52. package/esm/node/full-v5.js.map +1 -1
  53. package/esm/node/full-v5.mjs +366 -492
  54. package/esm/node/full-v5.mjs.map +1 -1
  55. package/esm/node/index.js +263 -384
  56. package/esm/node/index.js.map +1 -1
  57. package/esm/node/index.mjs +263 -384
  58. package/esm/node/index.mjs.map +1 -1
  59. package/esm/node/v4.js +194 -243
  60. package/esm/node/v4.js.map +1 -1
  61. package/esm/node/v4.mjs +194 -243
  62. package/esm/node/v4.mjs.map +1 -1
  63. package/esm/node/v5.js +263 -384
  64. package/esm/node/v5.js.map +1 -1
  65. package/esm/node/v5.mjs +263 -384
  66. package/esm/node/v5.mjs.map +1 -1
  67. package/esm/v4.js +194 -243
  68. package/esm/v4.js.map +1 -1
  69. package/esm/v5.js +263 -384
  70. package/esm/v5.js.map +1 -1
  71. package/esm/web/basic-v4.js +194 -243
  72. package/esm/web/basic-v4.js.map +1 -1
  73. package/esm/web/basic-v4.min.js +1 -1
  74. package/esm/web/basic-v4.min.js.br +0 -0
  75. package/esm/web/basic-v4.min.js.gz +0 -0
  76. package/esm/web/basic-v5.js +264 -385
  77. package/esm/web/basic-v5.js.map +1 -1
  78. package/esm/web/basic-v5.min.js +1 -1
  79. package/esm/web/basic-v5.min.js.br +0 -0
  80. package/esm/web/basic-v5.min.js.gz +0 -0
  81. package/esm/web/full-v4.js +297 -353
  82. package/esm/web/full-v4.js.map +1 -1
  83. package/esm/web/full-v4.min.js +1 -1
  84. package/esm/web/full-v4.min.js.br +0 -0
  85. package/esm/web/full-v4.min.js.gz +0 -0
  86. package/esm/web/full-v5.js +366 -492
  87. package/esm/web/full-v5.js.map +1 -1
  88. package/esm/web/full-v5.min.js +1 -1
  89. package/esm/web/full-v5.min.js.br +0 -0
  90. package/esm/web/full-v5.min.js.gz +0 -0
  91. package/esm/web/index.js +263 -384
  92. package/esm/web/index.js.map +1 -1
  93. package/esm/web/index.min.js +1 -1
  94. package/esm/web/index.min.js.br +0 -0
  95. package/esm/web/index.min.js.gz +0 -0
  96. package/esm/web/v4.js +194 -243
  97. package/esm/web/v4.js.map +1 -1
  98. package/esm/web/v4.min.js +1 -1
  99. package/esm/web/v4.min.js.br +0 -0
  100. package/esm/web/v4.min.js.gz +0 -0
  101. package/esm/web/v5.js +263 -384
  102. package/esm/web/v5.js.map +1 -1
  103. package/esm/web/v5.min.js +1 -1
  104. package/esm/web/v5.min.js.br +0 -0
  105. package/esm/web/v5.min.js.gz +0 -0
  106. package/package.json +2 -2
package/esm/index.js CHANGED
@@ -1,48 +1,31 @@
1
1
  function encode_varint(n, a=[]) {
2
- do {
3
- const ni = n & 0x7f;
4
- n >>>= 7;
5
- a.push( ni | (0===n ? 0 : 0x80) );
6
- } while (n > 0)
2
+ a.push((n<0x80 ? 0 : 0x80) | (n & 0x7f));
3
+ for(; ( n>>>=7 ) > 0 ;)
4
+ a.push((n<0x80 ? 0 : 0x80) | (n & 0x7f));
7
5
  return a
8
6
  }
9
7
 
8
+ function decode_varint$1(u8, i0=0, invalid) {
9
+ let shift=0, i=i0, b=u8[i++], n=(b & 0x7f);
10
+ for(; b & 0x80;)
11
+ n |= ((b=u8[i++]) & 0x7f) << (shift += 7);
10
12
 
11
- /*
12
- export function decode_varint_loop(u8, i=0) {
13
- let i0 = i
14
- let shift = 0, n = (u8[i] & 0x7f)
15
- while ( 0x80 & u8[i++] )
16
- n |= (u8[i] & 0x7f) << (shift += 7)
17
-
18
- return [n, i, i0]
13
+ return (u8.length < i)
14
+ ? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
15
+ : [n, i, i0] // successful value
19
16
  }
20
- */
21
-
22
17
 
23
- function decode_varint$1(u8, i=0) {
24
- let i0 = i;
25
- // unrolled for a max of 4 chains
26
- let n = (u8[i] & 0x7f) << 0;
27
- if ( 0x80 & u8[i++] ) {
28
- n |= (u8[i] & 0x7f) << 7;
29
- if ( 0x80 & u8[i++] ) {
30
- n |= (u8[i] & 0x7f) << 14;
31
- if ( 0x80 & u8[i++] ) {
32
- n |= (u8[i] & 0x7f) << 21;
33
- }
34
- }
18
+ function add_mqtt_props(mqtt_props, entries) {
19
+ for (let [id, type, name, obj] of entries) {
20
+ obj = {id, type, name, ...obj};
21
+ mqtt_props.set(id, obj).set(name, obj);
35
22
  }
36
- return [n, i, i0]
23
+ return mqtt_props
37
24
  }
38
25
 
39
- const mqtt_props = /* #__PURE__ */
40
- init_mqtt_props();
41
-
42
- function init_mqtt_props() {
43
- let mqtt_props = new Map();
44
26
 
45
- let entries = [
27
+ const init_mqtt_props = () =>
28
+ add_mqtt_props(new Map(), [
46
29
  [ 0x01, 'u8', 'payload_format_indicator'],
47
30
  [ 0x02, 'u32', 'message_expiry_interval'],
48
31
  [ 0x03, 'utf8', 'content_type'],
@@ -70,30 +53,24 @@ function init_mqtt_props() {
70
53
  [ 0x28, 'u8', 'wildcard_subscription_available'],
71
54
  [ 0x29, 'u8', 'subscription_identifiers_available', {op: 'u8_vec'}],
72
55
  [ 0x2A, 'u8', 'shared_subscription_available'],
73
- ];
56
+ ]);
74
57
 
75
- for (let [id, type, name, extra] of entries) {
76
- let prop_obj = {id, type, name, ...extra};
77
- mqtt_props.set(prop_obj.id, prop_obj);
78
- mqtt_props.set(prop_obj.name, prop_obj);
79
- }
80
58
 
81
- return mqtt_props
82
- }
59
+ const mqtt_props = /* #__PURE__ */
60
+ init_mqtt_props();
83
61
 
84
- class U8_Reason extends Number {
85
- static of(v, pkt_kind, by_kind) {
86
- let self = new this(v);
87
- self.reason = by_kind?.[pkt_kind]?.get(v) || pkt_kind;
88
- return self
62
+ class mqtt_reason extends Number {
63
+ constructor(v, reason) {
64
+ super(v);
65
+ this.reason = `:${(this.ok = v<0x80) ? 'ok' : 'fail'}:${reason}`;
89
66
  }
90
67
  }
91
68
 
92
69
  class mqtt_reader_v4 {
93
- static of(buf) { return this.prototype.of(buf) }
94
- of(buf) {
70
+ static for(pkt, u8_body) { return new this().of(u8_body, {pkt}) }
71
+ of(buf, opt) {
95
72
  let step = (width, k) => (k=0|step.k, step.k=k+width, k);
96
- return {__proto__: this, buf, step}
73
+ return {__proto__: this, buf, step, ...opt}
97
74
  }
98
75
 
99
76
  has_more() {
@@ -136,7 +113,7 @@ class mqtt_reader_v4 {
136
113
  reason(pkt_kind) {
137
114
  let v = this.buf[this.step(1)];
138
115
  if (null != v)
139
- return U8_Reason.of(v, pkt_kind, this._reasons_by)
116
+ return new mqtt_reason(v, this._reason_for?.(v, pkt_kind))
140
117
  }
141
118
 
142
119
  flush() {
@@ -150,24 +127,22 @@ class mqtt_reader_v4 {
150
127
  let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
151
128
  props() {
152
129
  let {buf, step} = this;
153
- let [n, vi, vi0] = decode_varint$1(buf, step.k|0);
130
+ let [n, vi, vi0] = decode_varint$1(buf, step.k|0, 0);
154
131
  step(n + vi - vi0);
155
132
  if (0 === n) return null
156
133
 
157
134
  let res={}, fork = this.of(buf.subarray(vi, step.k|0));
158
135
  while (fork.has_more()) {
159
136
  let v, pk = fork.u8(), pt = mqtt_props.get( pk );
160
-
161
137
  if (!pt) {
162
- res.error = `Unknown mqtt_prop enum ${pk}`;
163
- return res
138
+ res._unknown_ = pk;
139
+ this.warn?.(`unknown property: ${pk}`);
140
+ break
164
141
  }
165
142
 
166
143
  v = fork[pt.type]();
167
- if (pt.op) // accumulate operation
168
- v = fork[pt.op](res[pt.name], v);
169
-
170
- res[pt.name] = v;
144
+ res[pt.name] = !pt.op ? v
145
+ : fork[pt.op](res[pt.name], v); // accumulate operation
171
146
  }
172
147
  return res
173
148
  }
@@ -192,28 +167,99 @@ let mqtt_reader_v5$1 = class mqtt_reader_v5 extends mqtt_reader_v4 {
192
167
  */
193
168
  };
194
169
 
195
- function mqtt_reader_info(mqtt_reader, ... info_fn_list) {
196
- mqtt_reader = class extends mqtt_reader {
197
- static reasons(pkt_type, ...reason_entries) {
198
- let proto = this.prototype;
199
- proto._reasons_by = {... proto._reasons_by};
170
+ function with_reasons(mqtt_reader, by_kind) {
171
+ for (let [k,lut] of Object.entries(by_kind))
172
+ by_kind[k] = new Map(lut);
200
173
 
201
- let lut = (proto._reasons_by[pkt_type] ||= new Map());
202
- for (let [u8, reason] of reason_entries)
203
- lut.set( u8, reason );
204
-
205
- return this
174
+ return class extends mqtt_reader {
175
+ _reason_for(v, pkt_kind) {
176
+ return by_kind[pkt_kind]?.get(v) || by_kind.all.get(v)
177
+ }
178
+ warn(msg) {
179
+ let pkt = this.pkt;
180
+ pkt.warn ? pkt.warn(msg, pkt)
181
+ : console.warn('[u8-mqtt-packet] '+msg);
206
182
  }
207
- };
183
+ }
184
+ }
208
185
 
209
- for (let fn_info of info_fn_list)
210
- fn_info(mqtt_reader);
211
186
 
212
- return mqtt_reader
213
- }
187
+ const reasons_v4 = {
188
+ connack: [
189
+ [ 0x01, 'conn refused: unacceptable protocol version'],
190
+ [ 0x02, 'conn refused: identifier rejected'],
191
+ [ 0x03, 'conn refused: server unavailable'],
192
+ [ 0x04, 'conn refused: bad user name or password'],
193
+ [ 0x05, 'conn refused: not authorized'],
194
+ ],
195
+ suback: [
196
+ [ 0x00, 'qos=0'],
197
+ [ 0x01, 'qos=1'],
198
+ [ 0x02, 'qos=2'],
199
+ ],
200
+ unsuback: [
201
+ [ 0x11, 'no subscription existed'],
202
+ ],
203
+ puback: [
204
+ [ 0x10, 'no matching subscribers'],
205
+ ],
206
+ all: [
207
+ [ 0, ''], // Success
208
+ [ 0x80, 'unspecified error'], // disconnect puback suback unsuback
209
+ [ 0x83, 'implementation specific error'], // connack disconnect puback suback unsuback
210
+ [ 0x87, 'not authorized'], // connack disconnect puback suback unsuback
211
+ [ 0x8F, 'topic filter invalid'], // disconnect suback unsuback
212
+ [ 0x91, 'packet identifier in use'], // puback suback unsuback
213
+ [ 0x92, 'packet identifier not found' ], // pubxxx
214
+ ]};
215
+
216
+ const reasons_v5 = {
217
+ ... reasons_v4,
218
+ auth: [
219
+ [ 0x18, 'continue authentication' ],
220
+ [ 0x19, 're-authenticate' ],
221
+ ],
222
+ disconnect: [
223
+ [ 0x04, 'disconnect with will message'],
224
+ ],
225
+ all: [
226
+ ... reasons_v4.all,
227
+ [ 0x81, 'malformed packet'], // connack disconnect
228
+ [ 0x82, 'protocol error'], // connack disconnect
229
+ [ 0x84, 'unsupported protocol version'], // connack
230
+ [ 0x85, 'client identifier not valid'], // connack
231
+ [ 0x86, 'bad user name or password'], // connack
232
+ [ 0x88, 'server unavailable'], // connack
233
+ [ 0x89, 'server busy'], // connack disconnect
234
+ [ 0x8A, 'banned'], // connack
235
+ [ 0x8B, 'server shutting down'], // disconnect
236
+ [ 0x8C, 'bad authentication method'], // connack
237
+ [ 0x8D, 'keep alive timeout'], // disconnect
238
+ [ 0x8E, 'session taken over'], // disconnect
239
+ [ 0x90, 'topic name invalid'], // connack disconnect puback
240
+ [ 0x93, 'receive maximum exceeded'], // disconnect
241
+ [ 0x94, 'topic alias invalid'], // disconnect
242
+ [ 0x95, 'packet too large'], // connack disconnect
243
+ [ 0x96, 'message rate too high'], // disconnect
244
+ [ 0x97, 'quota exceeded'], // connack disconnect puback suback
245
+ [ 0x98, 'administrative action'], // disconnect
246
+ [ 0x99, 'payload format invalid'], // connack disconnect puback
247
+ [ 0x9A, 'retain not supported'], // connack disconnect
248
+ [ 0x9B, 'qoS not supported'], // connack disconnect
249
+ [ 0x9C, 'use another server'], // connack disconnect
250
+ [ 0x9D, 'server moved'], // connack disconnect
251
+ [ 0x9E, 'shared subscriptions not supported'], // disconnect suback
252
+ [ 0x9F, 'connection rate exceeded'], // connack disconnect
253
+ [ 0xA0, 'maximum connect time'], // disconnect
254
+ [ 0xA1, 'subscription identifiers not supported'], // disconnect suback
255
+ [ 0xA2, 'wildcard subscriptions not supported'], // disconnect suback
256
+ ]};
257
+
258
+ const mqtt_reader_v5 = /* #__PURE__ */
259
+ with_reasons(mqtt_reader_v5$1, reasons_v5);
214
260
 
215
261
  class mqtt_writer_v4 {
216
- static of() { return this.prototype.of() }
262
+ static for(pkt) { return new this().of() }
217
263
  of() { return {__proto__: this, $:[]} }
218
264
 
219
265
  static init() { return this }
@@ -302,7 +348,8 @@ class mqtt_writer_v5 extends mqtt_writer_v4 {
302
348
  for (let [name, value] of props) {
303
349
  let pt = mqtt_props.get(name);
304
350
  if (!pt)
305
- throw new Error(`Unknown mqtt_prop "${name}"`)
351
+ throw new Error(`MQTT unknown property "${name}"`)
352
+
306
353
  fork[pt.op || 'one'](value, pt);
307
354
  }
308
355
  this.push(fork.pack());
@@ -326,245 +373,6 @@ class mqtt_writer_v5 extends mqtt_writer_v4 {
326
373
  }
327
374
  }
328
375
 
329
- function mqtt_decode_connack(ns, mqtt_reader) {
330
- class _connack_flags_ extends Number {
331
- get session_present() { return this & 0x01 !== 0 }
332
- }
333
-
334
- return ns[0x2] = (pkt, u8_body) => {
335
- let rdr = mqtt_reader.of(u8_body);
336
-
337
- pkt.flags =
338
- rdr.flags(_connack_flags_);
339
-
340
- pkt.reason = rdr.reason(pkt.type);
341
- if (5 <= pkt.mqtt_level)
342
- pkt.props = rdr.props();
343
- return pkt }
344
- }
345
-
346
-
347
- function _connack_v4(mqtt_reader) {
348
- mqtt_reader.reasons('connack',
349
- // MQTT 3.1.1
350
- [ 0x00, 'Success'],
351
- [ 0x01, 'Connection refused, unacceptable protocol version'],
352
- [ 0x02, 'Connection refused, identifier rejected'],
353
- [ 0x03, 'Connection refused, server unavailable'],
354
- [ 0x04, 'Connection refused, bad user name or password'],
355
- [ 0x05, 'Connection refused, not authorized'],
356
- );
357
- }
358
-
359
- function _connack_v5(mqtt_reader) {
360
- _connack_v4(mqtt_reader);
361
-
362
- mqtt_reader.reasons('connack',
363
- // MQTT 5.0
364
- [ 0x81, 'Malformed Packet'],
365
- [ 0x82, 'Protocol Error'],
366
- [ 0x83, 'Implementation specific error'],
367
- [ 0x84, 'Unsupported Protocol Version'],
368
- [ 0x85, 'Client Identifier not valid'],
369
- [ 0x86, 'Bad User Name or Password'],
370
- [ 0x87, 'Not authorized'],
371
- [ 0x88, 'Server unavailable'],
372
- [ 0x89, 'Server busy'],
373
- [ 0x8A, 'Banned'],
374
- [ 0x8C, 'Bad authentication method'],
375
- [ 0x90, 'Topic Name invalid'],
376
- [ 0x95, 'Packet too large'],
377
- [ 0x97, 'Quota exceeded'],
378
- [ 0x99, 'Payload format invalid'],
379
- [ 0x9A, 'Retain not supported'],
380
- [ 0x9B, 'QoS not supported'],
381
- [ 0x9C, 'Use another server'],
382
- [ 0x9D, 'Server moved'],
383
- [ 0x9F, 'Connection rate exceeded'],
384
- );
385
- }
386
-
387
- function mqtt_decode_publish(ns, mqtt_reader) {
388
- return ns[0x3] = (pkt, u8_body) => {
389
- let {hdr} = pkt;
390
- pkt.dup = Boolean(hdr & 0x8);
391
- pkt.retain = Boolean(hdr & 0x1);
392
- let qos = pkt.qos = (hdr>>1) & 0x3;
393
-
394
- let rdr = mqtt_reader.of(u8_body);
395
- pkt.topic = rdr.utf8();
396
- if (0 !== qos)
397
- pkt.pkt_id = rdr.u16();
398
-
399
- if (5 <= pkt.mqtt_level)
400
- pkt.props = rdr.props();
401
-
402
- pkt.payload = rdr.flush();
403
- return pkt }
404
- }
405
-
406
- function mqtt_decode_puback(ns, mqtt_reader) {
407
- return ns[0x4] = (pkt, u8_body) => {
408
- let rdr = mqtt_reader.of(u8_body);
409
-
410
- pkt.pkt_id = rdr.u16();
411
- if (5 <= pkt.mqtt_level) {
412
- pkt.reason = rdr.reason(pkt.type);
413
- pkt.props = rdr.props();
414
- }
415
-
416
- return pkt }
417
- }
418
-
419
-
420
- function _puback_v5(mqtt_reader) {
421
- mqtt_reader.reasons('puback',
422
- // MQTT 5.0
423
- [ 0x00, 'Success'],
424
- [ 0x10, 'No matching subscribers'],
425
- [ 0x80, 'Unspecified error'],
426
- [ 0x83, 'Implementation specific error'],
427
- [ 0x87, 'Not authorized'],
428
- [ 0x90, 'Topic Name invalid'],
429
- [ 0x91, 'Packet identifier in use'],
430
- [ 0x97, 'Quota exceeded'],
431
- [ 0x99, 'Payload format invalid'],
432
- );
433
- }
434
-
435
- function _mqtt_decode_suback(mqtt_reader) {
436
- return (pkt, u8_body) => {
437
- let rdr = mqtt_reader.of(u8_body);
438
-
439
- pkt.pkt_id = rdr.u16();
440
- if (5 <= pkt.mqtt_level)
441
- pkt.props = rdr.props();
442
-
443
- let answers = pkt.answers = [];
444
- while (rdr.has_more())
445
- answers.push(
446
- rdr.reason(pkt.type) );
447
-
448
- return pkt }
449
- }
450
-
451
- function mqtt_decode_suback(ns, mqtt_reader) {
452
- return ns[0x9] = _mqtt_decode_suback(mqtt_reader)
453
- }
454
-
455
- function _suback_v4(mqtt_reader) {
456
- mqtt_reader.reasons('suback',
457
- // MQTT 3.1.1
458
- [ 0x00, 'Granted QoS 0'],
459
- [ 0x01, 'Granted QoS 1'],
460
- [ 0x02, 'Granted QoS 2'],
461
- );
462
- }
463
-
464
- function _suback_v5(mqtt_reader) {
465
- _suback_v4(mqtt_reader);
466
-
467
- mqtt_reader.reasons('suback',
468
- // MQTT 5.0
469
- [ 0x80, 'Unspecified error'],
470
- [ 0x83, 'Implementation specific error'],
471
- [ 0x87, 'Not authorized'],
472
- [ 0x8F, 'Topic Filter invalid'],
473
- [ 0x91, 'Packet Identifier in use'],
474
- [ 0x97, 'Quota exceeded'],
475
- [ 0x9E, 'Shared Subscriptions not supported'],
476
- [ 0xA1, 'Subscription Identifiers not supported'],
477
- [ 0xA2, 'Wildcard Subscriptions not supported'],
478
- );
479
- }
480
-
481
- function mqtt_decode_unsuback(ns, mqtt_reader) {
482
- return ns[0xb] = _mqtt_decode_suback(mqtt_reader)
483
- }
484
-
485
- function _unsuback_v4(mqtt_reader) {
486
- mqtt_reader.reasons('unsuback',
487
- // MQTT 3.1.1
488
- [ 0x00, 'Success'],
489
- [ 0x11, 'No subscription existed'],
490
- [ 0x80, 'Unspecified error'],
491
- [ 0x83, 'Implementation specific error'],
492
- [ 0x87, 'Not authorized'],
493
- [ 0x8F, 'Topic Filter invalid'],
494
- [ 0x91, 'Packet Identifier in use'],
495
- );
496
- }
497
-
498
- function mqtt_decode_pingxxx(ns) {
499
- return ns[0xc] = ns[0xd] = pkt => pkt
500
- }
501
-
502
- function mqtt_decode_disconnect(ns, mqtt_reader) {
503
- return ns[0xe] = (pkt, u8_body) => {
504
- if (u8_body && 5 <= pkt.mqtt_level) {
505
- let rdr = mqtt_reader.of(u8_body);
506
- pkt.reason = rdr.reason(pkt.type);
507
- pkt.props = rdr.props();
508
- }
509
- return pkt }
510
- }
511
-
512
-
513
- function _disconnect_v5(mqtt_reader) {
514
- mqtt_reader.reasons('disconnect',
515
- // MQTT 5.0
516
- [ 0x00, 'Normal disconnection'],
517
- [ 0x04, 'Disconnect with Will Message'],
518
- [ 0x80, 'Unspecified error'],
519
- [ 0x81, 'Malformed Packet'],
520
- [ 0x82, 'Protocol Error'],
521
- [ 0x83, 'Implementation specific error'],
522
- [ 0x87, 'Not authorized'],
523
- [ 0x89, 'Server busy'],
524
- [ 0x8B, 'Server shutting down'],
525
- [ 0x8D, 'Keep Alive timeout'],
526
- [ 0x8E, 'Session taken over'],
527
- [ 0x8F, 'Topic Filter invalid'],
528
- [ 0x90, 'Topic Name invalid'],
529
- [ 0x93, 'Receive Maximum exceeded'],
530
- [ 0x94, 'Topic Alias invalid'],
531
- [ 0x95, 'Packet too large'],
532
- [ 0x96, 'Message rate too high'],
533
- [ 0x97, 'Quota exceeded'],
534
- [ 0x98, 'Administrative action'],
535
- [ 0x99, 'Payload format invalid'],
536
- [ 0x9A, 'Retain not supported'],
537
- [ 0x9B, 'QoS not supported'],
538
- [ 0x9C, 'Use another server'],
539
- [ 0x9D, 'Server moved'],
540
- [ 0x9E, 'Shared Subscriptions not supported'],
541
- [ 0x9F, 'Connection rate exceeded'],
542
- [ 0xA0, 'Maximum connect time'],
543
- [ 0xA1, 'Subscription Identifiers not supported'],
544
- [ 0xA2, 'Wildcard Subscriptions not supported'],
545
- );
546
- }
547
-
548
- function mqtt_decode_auth(ns, mqtt_reader) {
549
- return ns[0xf] = (pkt, u8_body) => {
550
- if ( 5 <= pkt.mqtt_level ) {
551
- let rdr = mqtt_reader.of(u8_body);
552
- pkt.reason = rdr.reason(pkt.type);
553
- pkt.props = rdr.props();
554
- }
555
- return pkt }
556
- }
557
-
558
-
559
- function _auth_v5(mqtt_reader) {
560
- mqtt_reader.reasons('auth',
561
- // MQTT 5.0
562
- [ 0x00, 'Success' ],
563
- [ 0x18, 'Continue authentication' ],
564
- [ 0x19, 'Re-authenticate' ],
565
- );
566
- }
567
-
568
376
  function mqtt_encode_connect(ns, mqtt_writer) {
569
377
  const _c_mqtt_proto = new Uint8Array([
570
378
  0, 4, 0x4d, 0x51, 0x54, 0x54 ]);
@@ -583,7 +391,7 @@ function mqtt_encode_connect(ns, mqtt_writer) {
583
391
  | ( will.retain ? 0x20 : 0 );
584
392
 
585
393
  return ns.connect = ( mqtt_level, pkt ) => {
586
- let wrt = mqtt_writer.of(pkt);
394
+ let wrt = mqtt_writer.for(pkt);
587
395
 
588
396
  wrt.push(_c_mqtt_proto);
589
397
  wrt.u8( mqtt_level );
@@ -621,10 +429,27 @@ function mqtt_encode_connect(ns, mqtt_writer) {
621
429
  }
622
430
  }
623
431
 
432
+ function mqtt_decode_connack(ns, mqtt_reader) {
433
+ class _connack_flags_ extends Number {
434
+ get session_present() { return this & 0x01 !== 0 }
435
+ }
436
+
437
+ return ns[0x2] = (pkt, u8_body) => {
438
+ let rdr = mqtt_reader.for(pkt, u8_body);
439
+
440
+ pkt.flags =
441
+ rdr.flags(_connack_flags_);
442
+
443
+ pkt.reason = rdr.reason(pkt.type);
444
+ if (5 <= pkt.mqtt_level)
445
+ pkt.props = rdr.props();
446
+ return pkt }
447
+ }
448
+
624
449
  function mqtt_encode_publish(ns, mqtt_writer) {
625
450
  return ns.publish = ( mqtt_level, pkt ) => {
626
451
  let qos = (pkt.qos & 0x3) << 1;
627
- let wrt = mqtt_writer.of(pkt);
452
+ let wrt = mqtt_writer.for(pkt);
628
453
 
629
454
  wrt.utf8(pkt.topic);
630
455
  if (0 !== qos)
@@ -642,9 +467,28 @@ function mqtt_encode_publish(ns, mqtt_writer) {
642
467
  }
643
468
  }
644
469
 
470
+ function mqtt_decode_publish(ns, mqtt_reader) {
471
+ return ns[0x3] = (pkt, u8_body) => {
472
+ let {hdr} = pkt;
473
+ pkt.dup = Boolean(hdr & 0x8);
474
+ pkt.retain = Boolean(hdr & 0x1);
475
+ let qos = pkt.qos = (hdr>>1) & 0x3;
476
+
477
+ let rdr = mqtt_reader.for(pkt, u8_body);
478
+ pkt.topic = rdr.utf8();
479
+ if (0 !== qos)
480
+ pkt.pkt_id = rdr.u16();
481
+
482
+ if (5 <= pkt.mqtt_level)
483
+ pkt.props = rdr.props();
484
+
485
+ pkt.payload = rdr.flush();
486
+ return pkt }
487
+ }
488
+
645
489
  function mqtt_encode_puback(ns, mqtt_writer) {
646
490
  return ns.puback = ( mqtt_level, pkt ) => {
647
- let wrt = mqtt_writer.of(pkt);
491
+ let wrt = mqtt_writer.for(pkt);
648
492
 
649
493
  wrt.u16(pkt.pkt_id);
650
494
  if (5 <= mqtt_level) {
@@ -656,6 +500,20 @@ function mqtt_encode_puback(ns, mqtt_writer) {
656
500
  }
657
501
  }
658
502
 
503
+
504
+ function mqtt_decode_puback(ns, mqtt_reader) {
505
+ return ns[0x4] = (pkt, u8_body) => {
506
+ let rdr = mqtt_reader.for(pkt, u8_body);
507
+
508
+ pkt.pkt_id = rdr.u16();
509
+ if (5 <= pkt.mqtt_level) {
510
+ pkt.reason = rdr.reason(pkt.type);
511
+ pkt.props = rdr.props();
512
+ }
513
+
514
+ return pkt }
515
+ }
516
+
659
517
  function mqtt_encode_subscribe(ns, mqtt_writer) {
660
518
  const _enc_subscribe_flags = opts => 0
661
519
  | ( opts.qos & 0x3 )
@@ -663,7 +521,7 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
663
521
  | ( (opts.retain_handling & 0x3) << 2 );
664
522
 
665
523
  return ns.subscribe = ( mqtt_level, pkt ) => {
666
- let wrt = mqtt_writer.of(pkt);
524
+ let wrt = mqtt_writer.for(pkt);
667
525
 
668
526
  wrt.u16(pkt.pkt_id);
669
527
  if (5 <= mqtt_level)
@@ -689,9 +547,25 @@ function mqtt_encode_subscribe(ns, mqtt_writer) {
689
547
  }
690
548
  }
691
549
 
550
+ function mqtt_decode_xxsuback(ns, mqtt_reader) {
551
+ return ns[0x9] = ns[0xb] = (pkt, u8_body) => {
552
+ let rdr = mqtt_reader.for(pkt, u8_body);
553
+
554
+ pkt.pkt_id = rdr.u16();
555
+ if (5 <= pkt.mqtt_level)
556
+ pkt.props = rdr.props();
557
+
558
+ let answers = pkt.answers = [];
559
+ while (rdr.has_more())
560
+ answers.push(
561
+ rdr.reason(pkt.type) );
562
+
563
+ return pkt }
564
+ }
565
+
692
566
  function mqtt_encode_unsubscribe(ns, mqtt_writer) {
693
567
  return ns.unsubscribe = ( mqtt_level, pkt ) => {
694
- let wrt = mqtt_writer.of(pkt);
568
+ let wrt = mqtt_writer.for(pkt);
695
569
 
696
570
  wrt.u16(pkt.pkt_id);
697
571
  if (5 <= mqtt_level)
@@ -709,9 +583,14 @@ function mqtt_encode_pingxxx(ns) {
709
583
  ns.pingresp = () => new Uint8Array([ 0xd0, 0 ]);
710
584
  }
711
585
 
586
+
587
+ function mqtt_decode_pingxxx(ns) {
588
+ return ns[0xc] = ns[0xd] = pkt => pkt
589
+ }
590
+
712
591
  function mqtt_encode_disconnect(ns, mqtt_writer) {
713
592
  return ns.disconnect = ( mqtt_level, pkt ) => {
714
- let wrt = mqtt_writer.of(pkt);
593
+ let wrt = mqtt_writer.for(pkt);
715
594
 
716
595
  if (pkt && 5 <= mqtt_level) {
717
596
  if (pkt.reason || pkt.props) {
@@ -724,6 +603,17 @@ function mqtt_encode_disconnect(ns, mqtt_writer) {
724
603
  }
725
604
  }
726
605
 
606
+
607
+ function mqtt_decode_disconnect(ns, mqtt_reader) {
608
+ return ns[0xe] = (pkt, u8_body) => {
609
+ if (u8_body && 5 <= pkt.mqtt_level) {
610
+ let rdr = mqtt_reader.for(pkt, u8_body);
611
+ pkt.reason = rdr.reason(pkt.type);
612
+ pkt.props = rdr.props();
613
+ }
614
+ return pkt }
615
+ }
616
+
727
617
  function mqtt_encode_auth(ns, mqtt_writer) {
728
618
  return ns.auth = ( mqtt_level, pkt ) => {
729
619
  if (5 > mqtt_level)
@@ -738,12 +628,21 @@ function mqtt_encode_auth(ns, mqtt_writer) {
738
628
  }
739
629
  }
740
630
 
631
+ function mqtt_decode_auth(ns, mqtt_reader) {
632
+ return ns[0xf] = (pkt, u8_body) => {
633
+ if ( 5 <= pkt.mqtt_level ) {
634
+ let rdr = mqtt_reader.of(u8_body);
635
+ pkt.reason = rdr.reason(pkt.type);
636
+ pkt.props = rdr.props();
637
+ }
638
+ return pkt }
639
+ }
640
+
741
641
  const mqtt_decode_v5 = [
742
642
  mqtt_decode_connack,
743
643
  mqtt_decode_publish,
744
644
  mqtt_decode_puback,
745
- mqtt_decode_suback,
746
- mqtt_decode_unsuback,
645
+ mqtt_decode_xxsuback,
747
646
  mqtt_decode_pingxxx,
748
647
  mqtt_decode_disconnect,
749
648
  mqtt_decode_auth,
@@ -761,18 +660,6 @@ const mqtt_encode_v5 = [
761
660
  mqtt_encode_auth,
762
661
  ];
763
662
 
764
- const mqtt_reader_v5 = /* #__PURE__ */
765
- mqtt_reader_info(
766
- mqtt_reader_v5$1,
767
- _connack_v5,
768
- _puback_v5,
769
- _suback_v5,
770
- _unsuback_v4,
771
- _disconnect_v5,
772
- _auth_v5,
773
- );
774
-
775
-
776
663
  const mqtt_opts_v5 =
777
664
  { decode_fns: mqtt_decode_v5,
778
665
  mqtt_reader: mqtt_reader_v5,
@@ -977,47 +864,38 @@ function _route_remove(all_route_lists, query) {
977
864
  return true} }
978
865
  return false}
979
866
 
980
- /*
981
- export function decode_varint_loop(u8, i=0) {
982
- let i0 = i
983
- let shift = 0, n = (u8[i] & 0x7f)
984
- while ( 0x80 & u8[i++] )
985
- n |= (u8[i] & 0x7f) << (shift += 7)
986
-
987
- return [n, i, i0]
988
- }
989
- */
867
+ function decode_varint(u8, i0=0, invalid) {
868
+ let shift=0, i=i0, b=u8[i++], n=(b & 0x7f);
869
+ for(; b & 0x80;)
870
+ n |= ((b=u8[i++]) & 0x7f) << (shift += 7);
990
871
 
991
-
992
- function decode_varint(u8, i=0) {
993
- let i0 = i;
994
- // unrolled for a max of 4 chains
995
- let n = (u8[i] & 0x7f) << 0;
996
- if ( 0x80 & u8[i++] ) {
997
- n |= (u8[i] & 0x7f) << 7;
998
- if ( 0x80 & u8[i++] ) {
999
- n |= (u8[i] & 0x7f) << 14;
1000
- if ( 0x80 & u8[i++] ) {
1001
- n |= (u8[i] & 0x7f) << 21;
1002
- }
1003
- }
1004
- }
1005
- return [n, i, i0]
872
+ return (u8.length < i)
873
+ ? [invalid, i0, i0] // fail: insuffecient u8 bytes to decode
874
+ : [n, i, i0] // successful value
1006
875
  }
1007
876
 
1008
877
  function mqtt_raw_dispatch(opt) {
1009
- let u8 = new Uint8Array(0);
878
+ let u8 = new Uint8Array(0), len_tip=0;
1010
879
  return u8_buf => {
1011
880
  u8 = 0 === u8.byteLength
1012
881
  ? u8_buf : _u8_join(u8, u8_buf);
1013
882
 
1014
883
  let res = [];
1015
- while (1) {
1016
- let [len_body, len_vh] = decode_varint(u8, 1);
1017
- let len_pkt = len_body + len_vh;
1018
884
 
1019
- if ( u8.byteLength < len_pkt )
1020
- return res
885
+ // wait for at least len_tip bytes for next (tip) message
886
+ while ( u8.byteLength >= len_tip ) {
887
+
888
+ // if varint is incomplete, return len_body=NaN
889
+ let [len_body, len_vh] = decode_varint(u8, 1, NaN);
890
+ let len_pkt = len_body + len_vh; // may be NaN
891
+
892
+ if (!( len_pkt <= u8.byteLength )) {
893
+ // incomplete packet cases:
894
+ // - len_pkt is less than available bytes
895
+ // - len_pkt is NaN from decode_varint() due to lack of data
896
+ len_tip = len_pkt || 0; // 0 when NaN
897
+ break
898
+ }
1021
899
 
1022
900
  let b0 = u8[0];
1023
901
  let u8_body = 0 === len_body ? null
@@ -1029,6 +907,8 @@ function mqtt_raw_dispatch(opt) {
1029
907
  if (null != pkt)
1030
908
  res.push( pkt );
1031
909
  }
910
+
911
+ return res
1032
912
  }
1033
913
  }
1034
914
 
@@ -1039,16 +919,17 @@ function _u8_join(a, b) {
1039
919
  return r
1040
920
  }
1041
921
 
1042
- const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
922
+ const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
923
+
924
+
925
+ function mqtt_pkt_ctx(mqtt_level, opts, pkt_api=opts.pkt_ctx) {
926
+ let _as_pkt_ctx = pkt_api => ({
927
+ __proto__: pkt_api,
928
+ get hdr() { return this.b0 & 0xf },
929
+ get id() { return this.b0 >>> 4 },
930
+ get type() { return _pkt_types[this.b0 >>> 4] },
931
+ mqtt_level });
1043
932
 
1044
- function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
1045
- pkt_ctx = {
1046
- __proto__: pkt_ctx || opts.pkt_ctx,
1047
- mqtt_level,
1048
- get hdr() { return this.b0 & 0xf },
1049
- get id() { return this.b0 >>> 4 },
1050
- get type() { return _pkt_types[this.b0 >>> 4] },
1051
- };
1052
933
 
1053
934
  let op, _decode_by_id=[], _encode_by_type={};
1054
935
  for (op of opts.encode_fns)
@@ -1057,10 +938,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
1057
938
  op(_decode_by_id, opts.mqtt_reader);
1058
939
 
1059
940
  return {
1060
- pkt_ctx,
941
+ pkt_api, pkt_ctx: _as_pkt_ctx(pkt_api),
1061
942
 
1062
- encode_pkt(type, pkt) {
1063
- return _encode_by_type[type]( mqtt_level, pkt ) },
943
+ encode_pkt: (type, pkt) =>
944
+ _encode_by_type[type]( mqtt_level, pkt ),
1064
945
 
1065
946
  decode_pkt(b0, u8_body) {
1066
947
  if (b0.map) // Uint8Array in first arg
@@ -1069,12 +950,10 @@ function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
1069
950
  let fn_decode = _decode_by_id[b0>>>4] || _decode_by_id[0];
1070
951
  return fn_decode?.({__proto__: this.pkt_ctx, b0}, u8_body) },
1071
952
 
1072
- mqtt_stream() {
1073
- let self = { __proto__: this, pkt_ctx: { __proto__: pkt_ctx } };
1074
- self.pkt_ctx._base_ = self.pkt_ctx;
953
+ mqtt_stream(pkt_api=this.pkt_api) {
954
+ let self = { __proto__: this, pkt_ctx: _as_pkt_ctx(pkt_api) };
1075
955
  self.decode = mqtt_raw_dispatch(self);
1076
- return self
1077
- },
956
+ return self },
1078
957
  }
1079
958
  }
1080
959
 
@@ -1598,7 +1477,7 @@ class MQTTCore extends MQTTBase {
1598
1477
 
1599
1478
  return this} }
1600
1479
 
1601
- const version = '0.6.1';
1480
+ const version = '0.6.3';
1602
1481
 
1603
1482
  const MQTTClient_v4 = /* #__PURE__ */
1604
1483
  with_topic_path_router(