u8-mqtt 0.1.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -55
- package/cjs/index.cjs +632 -557
- package/cjs/index.cjs.map +1 -1
- package/cjs/v4.cjs +479 -662
- package/cjs/v4.cjs.map +1 -1
- package/cjs/v5.cjs +631 -550
- package/cjs/v5.cjs.map +1 -1
- package/code/_conn.jsy +53 -54
- package/code/_router.jsy +15 -4
- package/code/base.jsy +35 -16
- package/code/core.jsy +78 -59
- package/code/index.mjs +4 -4
- package/code/v4.mjs +6 -6
- package/code/v5.mjs +14 -6
- package/esm/deno/index.js +635 -562
- package/esm/deno/index.js.map +1 -1
- package/esm/deno/v4.js +486 -669
- package/esm/deno/v4.js.map +1 -1
- package/esm/deno/v5.js +637 -558
- package/esm/deno/v5.js.map +1 -1
- package/esm/node/index.js +628 -555
- package/esm/node/index.js.map +1 -1
- package/esm/node/index.mjs +628 -555
- package/esm/node/index.mjs.map +1 -1
- package/esm/node/v4.js +479 -662
- package/esm/node/v4.js.map +1 -1
- package/esm/node/v4.mjs +479 -662
- package/esm/node/v4.mjs.map +1 -1
- package/esm/node/v5.js +630 -551
- package/esm/node/v5.js.map +1 -1
- package/esm/node/v5.mjs +630 -551
- package/esm/node/v5.mjs.map +1 -1
- package/esm/web/index.js +630 -557
- package/esm/web/index.js.map +1 -1
- package/esm/web/index.min.js +1 -0
- package/esm/web/index.min.js.br +0 -0
- package/esm/web/index.min.js.gz +0 -0
- package/esm/web/v4.js +481 -664
- package/esm/web/v4.js.map +1 -1
- package/esm/web/v4.min.js +1 -0
- package/esm/web/v4.min.js.br +0 -0
- package/esm/web/v4.min.js.gz +0 -0
- package/esm/web/v5.js +632 -553
- package/esm/web/v5.js.map +1 -1
- package/esm/web/v5.min.js +1 -0
- package/esm/web/v5.min.js.br +0 -0
- package/esm/web/v5.min.js.gz +0 -0
- package/package.json +23 -12
- package/code/session.mjs +0 -65
- package/esm/deno/index.mjs +0 -1502
- package/esm/deno/index.mjs.map +0 -1
- package/esm/deno/v4.mjs +0 -1496
- package/esm/deno/v4.mjs.map +0 -1
- package/esm/deno/v5.mjs +0 -1496
- package/esm/deno/v5.mjs.map +0 -1
- package/esm/web/index.min.mjs +0 -1
- package/esm/web/index.mjs +0 -1502
- package/esm/web/index.mjs.map +0 -1
- package/esm/web/v4.min.mjs +0 -1
- package/esm/web/v4.mjs +0 -1496
- package/esm/web/v4.mjs.map +0 -1
- package/esm/web/v5.min.mjs +0 -1
- package/esm/web/v5.mjs +0 -1496
- package/esm/web/v5.mjs.map +0 -1
package/cjs/index.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var node_net = require('node:net');
|
|
6
6
|
|
|
7
7
|
function encode_varint(n, a=[]) {
|
|
8
8
|
do {
|
|
@@ -26,7 +26,7 @@ export function decode_varint_loop(u8, i=0) {
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
function decode_varint(u8, i=0) {
|
|
29
|
+
function decode_varint$1(u8, i=0) {
|
|
30
30
|
let i0 = i;
|
|
31
31
|
// unrolled for a max of 4 chains
|
|
32
32
|
let n = (u8[i] & 0x7f) << 0;
|
|
@@ -42,45 +42,13 @@ function decode_varint(u8, i=0) {
|
|
|
42
42
|
return [n, i, i0]
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return u8_buf => {
|
|
48
|
-
u8 = 0 === u8.byteLength
|
|
49
|
-
? u8_buf : _u8_join(u8, u8_buf);
|
|
50
|
-
|
|
51
|
-
const res = [];
|
|
52
|
-
while (1) {
|
|
53
|
-
const [len_body, len_vh] = decode_varint(u8, 1);
|
|
54
|
-
const len_pkt = len_body + len_vh;
|
|
45
|
+
const mqtt_props = /* #__PURE__ */
|
|
46
|
+
init_mqtt_props();
|
|
55
47
|
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
function init_mqtt_props() {
|
|
49
|
+
let mqtt_props = new Map();
|
|
58
50
|
|
|
59
|
-
|
|
60
|
-
let u8_body = 0 === len_body ? null
|
|
61
|
-
: u8.subarray(len_vh, len_pkt);
|
|
62
|
-
|
|
63
|
-
u8 = u8.subarray(len_pkt);
|
|
64
|
-
|
|
65
|
-
const pkt = decode_raw_pkt(b0, u8_body);
|
|
66
|
-
if (undefined !== pkt && null !== pkt)
|
|
67
|
-
res.push( pkt );
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function _u8_join(a, b) {
|
|
73
|
-
const alen = a.byteLength;
|
|
74
|
-
const r = new Uint8Array(alen + b.byteLength);
|
|
75
|
-
r.set(a, 0);
|
|
76
|
-
r.set(b, alen);
|
|
77
|
-
return r
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const mqtt_props = new Map();
|
|
81
|
-
|
|
82
|
-
{
|
|
83
|
-
const entries = [
|
|
51
|
+
let entries = [
|
|
84
52
|
[ 0x01, 'u8', 'payload_format_indicator'],
|
|
85
53
|
[ 0x02, 'u32', 'message_expiry_interval'],
|
|
86
54
|
[ 0x03, 'utf8', 'content_type'],
|
|
@@ -101,140 +69,279 @@ const mqtt_props = new Map();
|
|
|
101
69
|
[ 0x21, 'u16', 'receive_maximum'],
|
|
102
70
|
[ 0x22, 'u16', 'topic_alias_maximum'],
|
|
103
71
|
[ 0x23, 'u16', 'topic_alias'],
|
|
104
|
-
[ 0x24, 'u8', '
|
|
72
|
+
[ 0x24, 'u8', 'maximum_qos'],
|
|
105
73
|
[ 0x25, 'u8', 'retain_available'],
|
|
106
|
-
[ 0x26, 'pair', 'user_properties',
|
|
74
|
+
[ 0x26, 'pair', 'user_properties', {op: 'kv_obj'}],
|
|
107
75
|
[ 0x27, 'u32', 'maximum_packet_size'],
|
|
108
76
|
[ 0x28, 'u8', 'wildcard_subscription_available'],
|
|
109
|
-
[ 0x29, 'u8', 'subscription_identifiers_available',
|
|
77
|
+
[ 0x29, 'u8', 'subscription_identifiers_available', {op: 'u8_vec'}],
|
|
110
78
|
[ 0x2A, 'u8', 'shared_subscription_available'],
|
|
111
79
|
];
|
|
112
80
|
|
|
113
|
-
for (
|
|
114
|
-
|
|
115
|
-
if (plural) prop_obj.plural = plural;
|
|
81
|
+
for (let [id, type, name, extra] of entries) {
|
|
82
|
+
let prop_obj = {id, type, name, ...extra};
|
|
116
83
|
mqtt_props.set(prop_obj.id, prop_obj);
|
|
117
84
|
mqtt_props.set(prop_obj.name, prop_obj);
|
|
118
85
|
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const as_utf8 = u8 =>
|
|
122
|
-
new TextDecoder('utf-8').decode(u8);
|
|
123
86
|
|
|
124
|
-
|
|
125
|
-
|
|
87
|
+
return mqtt_props
|
|
88
|
+
}
|
|
126
89
|
|
|
127
|
-
class
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
90
|
+
class U8_Reason extends Number {
|
|
91
|
+
static of(v, pkt_kind, by_kind) {
|
|
92
|
+
let self = new this(v);
|
|
93
|
+
self.reason = by_kind?.[pkt_kind]?.get(v) || pkt_kind;
|
|
94
|
+
return self
|
|
131
95
|
}
|
|
96
|
+
}
|
|
132
97
|
|
|
133
|
-
|
|
134
|
-
|
|
98
|
+
class mqtt_reader_v4 {
|
|
99
|
+
static of(buf) { return this.prototype.of(buf) }
|
|
100
|
+
of(buf) {
|
|
101
|
+
let step = (width, k) => (k=0|step.k, step.k=k+width, k);
|
|
102
|
+
return {__proto__: this, buf, step}
|
|
135
103
|
}
|
|
136
104
|
|
|
137
105
|
has_more() {
|
|
138
|
-
|
|
139
|
-
return buf.byteLength > step(0)
|
|
106
|
+
return this.buf.byteLength > (this.step.k|0)
|
|
140
107
|
}
|
|
141
108
|
|
|
142
109
|
u8() {
|
|
143
|
-
|
|
144
|
-
return buf[step(1)]
|
|
110
|
+
return this.buf[this.step(1)]
|
|
145
111
|
}
|
|
146
112
|
|
|
147
113
|
u16() {
|
|
148
|
-
|
|
149
|
-
const i = step(2);
|
|
114
|
+
let {buf, step} = this, i = step(2);
|
|
150
115
|
return (buf[i]<<8) | buf[i+1]
|
|
151
116
|
}
|
|
152
117
|
|
|
153
118
|
u32() {
|
|
154
|
-
|
|
155
|
-
const i = step(4);
|
|
119
|
+
let {buf, step} = this, i = step(4);
|
|
156
120
|
return (buf[i]<<24) | (buf[i+1]<<16) | (buf[i+2]<<8) | buf[i+3]
|
|
157
121
|
}
|
|
158
122
|
|
|
159
123
|
vint() {
|
|
160
|
-
|
|
161
|
-
|
|
124
|
+
let {buf, step} = this;
|
|
125
|
+
let [n, vi, vi0] = decode_varint$1(buf, step.k|0);
|
|
162
126
|
step(vi - vi0);
|
|
163
127
|
return n
|
|
164
128
|
}
|
|
165
129
|
|
|
166
|
-
vbuf() {
|
|
167
|
-
const {buf, step} = this;
|
|
168
|
-
const [n, vi, vi0] = decode_varint(buf, step(0));
|
|
169
|
-
step(n + vi - vi0);
|
|
170
|
-
return 0 === n ? null
|
|
171
|
-
: buf.subarray(vi, step(0))
|
|
172
|
-
}
|
|
173
|
-
|
|
174
130
|
bin() {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return buf.subarray(i0, i0+len)
|
|
131
|
+
let {buf, step} = this, i = step(2);
|
|
132
|
+
let len = (buf[i]<<8) | buf[i+1];
|
|
133
|
+
i = step(len);
|
|
134
|
+
return buf.subarray(i, i+len)
|
|
180
135
|
}
|
|
181
136
|
|
|
182
|
-
utf8() { return
|
|
183
|
-
pair() { return [
|
|
137
|
+
utf8() { return new TextDecoder('utf-8').decode(this.bin()) }
|
|
138
|
+
pair() { return [ this.utf8(), this.utf8() ] }
|
|
184
139
|
|
|
185
|
-
|
|
186
|
-
const {buf, step} = this;
|
|
187
|
-
return new FlagsType(buf[step(1)])
|
|
188
|
-
}
|
|
140
|
+
flags(FlagsType) { return new FlagsType(this.buf[this.step(1)]) }
|
|
189
141
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
142
|
+
reason(pkt_kind) {
|
|
143
|
+
let v = this.buf[this.step(1)];
|
|
144
|
+
if (null != v)
|
|
145
|
+
return U8_Reason.of(v, pkt_kind, this._reasons_by)
|
|
193
146
|
}
|
|
194
147
|
|
|
195
148
|
flush() {
|
|
196
|
-
|
|
149
|
+
let {buf, step} = this;
|
|
197
150
|
this.step = this.buf = null;
|
|
198
|
-
return buf.subarray(step
|
|
151
|
+
return buf.subarray(step.k|0)
|
|
199
152
|
}
|
|
200
153
|
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
class mqtt_reader_v5$1 extends mqtt_reader_v4 {
|
|
201
157
|
props() {
|
|
202
|
-
let
|
|
203
|
-
|
|
204
|
-
|
|
158
|
+
let {buf, step} = this;
|
|
159
|
+
let [n, vi, vi0] = decode_varint$1(buf, step.k|0);
|
|
160
|
+
step(n + vi - vi0);
|
|
161
|
+
if (0 === n) return null
|
|
162
|
+
|
|
163
|
+
let res={}, fork = this.of(buf.subarray(vi, step.k|0));
|
|
164
|
+
while (fork.has_more()) {
|
|
165
|
+
let pt = mqtt_props.get( fork.u8() )
|
|
166
|
+
, value = fork[pt.type]();
|
|
167
|
+
res[pt.name] = ! pt.op ? value
|
|
168
|
+
: fork[pt.op](res[pt.name], value);
|
|
169
|
+
}
|
|
170
|
+
return res
|
|
205
171
|
}
|
|
206
172
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
let p = mqtt_props.get( k );
|
|
211
|
-
let v = this[p.type]();
|
|
212
|
-
lst.push([p.name, v]);
|
|
213
|
-
}
|
|
214
|
-
return lst
|
|
173
|
+
kv_obj(obj=Object.create(null), [k,v]) {
|
|
174
|
+
obj[k] = v;
|
|
175
|
+
return obj
|
|
215
176
|
}
|
|
177
|
+
u8_vec(vec=[], u8) {
|
|
178
|
+
vec.push(u8);
|
|
179
|
+
return vec
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/*
|
|
183
|
+
vbuf() {
|
|
184
|
+
let {buf, step} = this
|
|
185
|
+
let [n, vi, vi0] = decode_varint(buf, step.k|0)
|
|
186
|
+
step(n + vi - vi0)
|
|
187
|
+
return 0 === n ? null
|
|
188
|
+
: buf.subarray(vi, step.k|0)
|
|
189
|
+
}
|
|
190
|
+
*/
|
|
216
191
|
}
|
|
217
192
|
|
|
193
|
+
function mqtt_reader_info(mqtt_reader, ... info_fn_list) {
|
|
194
|
+
mqtt_reader = class extends mqtt_reader {
|
|
195
|
+
static reasons(pkt_type, ...reason_entries) {
|
|
196
|
+
let proto = this.prototype;
|
|
197
|
+
proto._reasons_by = {... proto._reasons_by};
|
|
218
198
|
|
|
199
|
+
let lut = (proto._reasons_by[pkt_type] ||= new Map());
|
|
200
|
+
for (let [u8, reason] of reason_entries)
|
|
201
|
+
lut.set( u8, reason );
|
|
219
202
|
|
|
220
|
-
|
|
221
|
-
|
|
203
|
+
return this
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
for (let fn_info of info_fn_list)
|
|
208
|
+
fn_info(mqtt_reader);
|
|
209
|
+
|
|
210
|
+
return mqtt_reader
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
class mqtt_writer_v4 {
|
|
214
|
+
static of() { return this.prototype.of() }
|
|
215
|
+
of() { return {__proto__: this, $:[]} }
|
|
216
|
+
|
|
217
|
+
static init() { return this }
|
|
218
|
+
|
|
219
|
+
as_pkt(pkt_id) { return this.pack([pkt_id]) }
|
|
220
|
+
|
|
221
|
+
push(...z) { this.$.push(...z); }
|
|
222
|
+
pack(hdr) {
|
|
223
|
+
let z, i, n=0, parts = this.$;
|
|
224
|
+
this.$ = false;
|
|
225
|
+
for (z of parts) n += z.length;
|
|
226
|
+
|
|
227
|
+
hdr = encode_varint(n, hdr);
|
|
228
|
+
i = hdr.length;
|
|
229
|
+
|
|
230
|
+
let pkt = new Uint8Array(i + n);
|
|
231
|
+
pkt.set(hdr, 0);
|
|
232
|
+
for (z of parts) {
|
|
233
|
+
pkt.set(z, i);
|
|
234
|
+
i += z.length;
|
|
235
|
+
}
|
|
236
|
+
return pkt
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
u8(v) { this.push([ v & 0xff ]); }
|
|
240
|
+
u16(v) { this.push([ (v>>>8) & 0xff, v & 0xff ]); }
|
|
241
|
+
u32(v) { this.push([ (v>>>24) & 0xff, (v>>>16) & 0xff, (v>>>8) & 0xff, v & 0xff ]); }
|
|
242
|
+
vint(v) { this.push( encode_varint(v) );}
|
|
243
|
+
|
|
244
|
+
bin(u8_buf) {
|
|
245
|
+
if (! u8_buf) return this.u16(0)
|
|
246
|
+
if ('string' === typeof u8_buf)
|
|
247
|
+
return this.utf8(u8_buf)
|
|
248
|
+
|
|
249
|
+
if (u8_buf.length !== u8_buf.byteLength)
|
|
250
|
+
u8_buf = new Uint8Array(u8_buf);
|
|
251
|
+
|
|
252
|
+
this.u16(u8_buf.byteLength);
|
|
253
|
+
this.push(u8_buf);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
utf8(v) {
|
|
257
|
+
let u8_buf = new TextEncoder('utf-8').encode(v);
|
|
258
|
+
this.u16(u8_buf.byteLength);
|
|
259
|
+
this.push(u8_buf);
|
|
260
|
+
}
|
|
261
|
+
pair(k,v) { this.utf8(k); this.utf8(v); }
|
|
262
|
+
|
|
263
|
+
flags(v, enc_flags, b0=0) {
|
|
264
|
+
if (undefined !== v && isNaN(+v))
|
|
265
|
+
v = enc_flags(v, 0);
|
|
266
|
+
|
|
267
|
+
v |= b0;
|
|
268
|
+
this.push([v]);
|
|
269
|
+
return v
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
reason(v) { this.push([v | 0]); }
|
|
273
|
+
|
|
274
|
+
flush(buf) {
|
|
275
|
+
if (null != buf)
|
|
276
|
+
this.push(
|
|
277
|
+
'string' === typeof buf
|
|
278
|
+
? new TextEncoder('utf-8').encode(buf)
|
|
279
|
+
: buf );
|
|
280
|
+
|
|
281
|
+
this.push = false;
|
|
282
|
+
}
|
|
222
283
|
}
|
|
223
284
|
|
|
224
|
-
function bind_reason_lookup(reason_entries) {
|
|
225
|
-
const reason_map = new Map();
|
|
226
|
-
for (const [u8, reason] of reason_entries)
|
|
227
|
-
reason_map.set( u8, new U8_Reason(u8, reason) );
|
|
228
285
|
|
|
229
|
-
|
|
286
|
+
class mqtt_writer_v5 extends mqtt_writer_v4 {
|
|
287
|
+
props(props) {
|
|
288
|
+
if (! props)
|
|
289
|
+
return this.u8(0)
|
|
290
|
+
|
|
291
|
+
if (! Array.isArray(props))
|
|
292
|
+
props = props.entries
|
|
293
|
+
? Array.from(props.entries())
|
|
294
|
+
: Object.entries(props);
|
|
295
|
+
|
|
296
|
+
if (0 === props.length)
|
|
297
|
+
return this.u8(0)
|
|
298
|
+
|
|
299
|
+
let fork = this.of();
|
|
300
|
+
for (let [name, value] of props) {
|
|
301
|
+
let pt = mqtt_props.get(name);
|
|
302
|
+
fork[pt.op || 'one'](value, pt);
|
|
303
|
+
}
|
|
304
|
+
this.push(fork.pack());
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
one(value, pt) {
|
|
308
|
+
this.u8(pt.id);
|
|
309
|
+
this[pt.type](value);
|
|
310
|
+
}
|
|
311
|
+
kv_obj(obj, pt) {
|
|
312
|
+
for (let kv of Object.entries(obj)) {
|
|
313
|
+
this.u8(pt.id);
|
|
314
|
+
this.pair(kv);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
u8_vec(vec, pt) {
|
|
318
|
+
for (let v of vec) {
|
|
319
|
+
this.u8(pt.id);
|
|
320
|
+
this.u8(v);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
230
323
|
}
|
|
231
324
|
|
|
232
|
-
function mqtt_decode_connack(ns) {
|
|
325
|
+
function mqtt_decode_connack(ns, mqtt_reader) {
|
|
233
326
|
class _connack_flags_ extends Number {
|
|
234
327
|
get session_present() { return this & 0x01 !== 0 }
|
|
235
328
|
}
|
|
236
329
|
|
|
237
|
-
|
|
330
|
+
return ns[0x2] = (pkt, u8_body) => {
|
|
331
|
+
let rdr = mqtt_reader.of(u8_body);
|
|
332
|
+
|
|
333
|
+
pkt.flags =
|
|
334
|
+
rdr.flags(_connack_flags_);
|
|
335
|
+
|
|
336
|
+
pkt.reason = rdr.reason(pkt.type);
|
|
337
|
+
if (5 <= pkt.mqtt_level)
|
|
338
|
+
pkt.props = rdr.props();
|
|
339
|
+
return pkt }
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
function _connack_v4(mqtt_reader) {
|
|
344
|
+
mqtt_reader.reasons('connack',
|
|
238
345
|
// MQTT 3.1.1
|
|
239
346
|
[ 0x00, 'Success'],
|
|
240
347
|
[ 0x01, 'Connection refused, unacceptable protocol version'],
|
|
@@ -242,7 +349,13 @@ function mqtt_decode_connack(ns) {
|
|
|
242
349
|
[ 0x03, 'Connection refused, server unavailable'],
|
|
243
350
|
[ 0x04, 'Connection refused, bad user name or password'],
|
|
244
351
|
[ 0x05, 'Connection refused, not authorized'],
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function _connack_v5(mqtt_reader) {
|
|
356
|
+
_connack_v4(mqtt_reader);
|
|
245
357
|
|
|
358
|
+
mqtt_reader.reasons('connack',
|
|
246
359
|
// MQTT 5.0
|
|
247
360
|
[ 0x81, 'Malformed Packet'],
|
|
248
361
|
[ 0x82, 'Protocol Error'],
|
|
@@ -264,29 +377,17 @@ function mqtt_decode_connack(ns) {
|
|
|
264
377
|
[ 0x9C, 'Use another server'],
|
|
265
378
|
[ 0x9D, 'Server moved'],
|
|
266
379
|
[ 0x9F, 'Connection rate exceeded'],
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
return ns[0x2] = (pkt, u8_body) => {
|
|
271
|
-
const rdr = new mqtt_type_reader(u8_body, 0);
|
|
272
|
-
|
|
273
|
-
pkt.flags =
|
|
274
|
-
rdr.u8_flags(_connack_flags_);
|
|
275
|
-
|
|
276
|
-
pkt.reason = rdr.u8_reason(_connack_reason_);
|
|
277
|
-
if (5 <= pkt.mqtt_level)
|
|
278
|
-
pkt.props = rdr.props();
|
|
279
|
-
return pkt }
|
|
380
|
+
);
|
|
280
381
|
}
|
|
281
382
|
|
|
282
|
-
function mqtt_decode_publish(ns) {
|
|
383
|
+
function mqtt_decode_publish(ns, mqtt_reader) {
|
|
283
384
|
return ns[0x3] = (pkt, u8_body) => {
|
|
284
|
-
|
|
385
|
+
let {hdr} = pkt;
|
|
285
386
|
pkt.dup = Boolean(hdr & 0x8);
|
|
286
387
|
pkt.retain = Boolean(hdr & 0x1);
|
|
287
|
-
|
|
388
|
+
let qos = pkt.qos = (hdr>>1) & 0x3;
|
|
288
389
|
|
|
289
|
-
|
|
390
|
+
let rdr = mqtt_reader.of(u8_body);
|
|
290
391
|
pkt.topic = rdr.utf8();
|
|
291
392
|
if (0 !== qos)
|
|
292
393
|
pkt.pkt_id = rdr.u16();
|
|
@@ -298,73 +399,68 @@ function mqtt_decode_publish(ns) {
|
|
|
298
399
|
return pkt }
|
|
299
400
|
}
|
|
300
401
|
|
|
301
|
-
function mqtt_decode_puback(ns) {
|
|
302
|
-
const _puback_reason_ = bind_reason_lookup([
|
|
303
|
-
[ 0x00, 'Success'],
|
|
304
|
-
|
|
305
|
-
// MQTT 5.0
|
|
306
|
-
[ 0x10, 'No matching subscribers'],
|
|
307
|
-
[ 0x80, 'Unspecified error'],
|
|
308
|
-
[ 0x83, 'Implementation specific error'],
|
|
309
|
-
[ 0x87, 'Not authorized'],
|
|
310
|
-
[ 0x90, 'Topic Name invalid'],
|
|
311
|
-
[ 0x91, 'Packet identifier in use'],
|
|
312
|
-
[ 0x97, 'Quota exceeded'],
|
|
313
|
-
[ 0x99, 'Payload format invalid'],
|
|
314
|
-
]);
|
|
315
|
-
|
|
316
|
-
|
|
402
|
+
function mqtt_decode_puback(ns, mqtt_reader) {
|
|
317
403
|
return ns[0x4] = (pkt, u8_body) => {
|
|
318
|
-
|
|
404
|
+
let rdr = mqtt_reader.of(u8_body);
|
|
319
405
|
|
|
320
406
|
pkt.pkt_id = rdr.u16();
|
|
321
407
|
if (5 <= pkt.mqtt_level) {
|
|
322
|
-
pkt.reason = rdr.
|
|
408
|
+
pkt.reason = rdr.reason(pkt.type);
|
|
323
409
|
pkt.props = rdr.props();
|
|
324
410
|
}
|
|
325
411
|
|
|
326
412
|
return pkt }
|
|
327
413
|
}
|
|
328
414
|
|
|
329
|
-
function mqtt_decode_pubxxx(ns) {
|
|
330
|
-
const _pubxxx_reason_ = bind_reason_lookup([
|
|
331
|
-
[ 0x00, 'Success' ],
|
|
332
|
-
[ 0x92, 'Packet Identifier not found' ],
|
|
333
|
-
]);
|
|
334
|
-
|
|
335
|
-
return ns[0x5] = ns[0x6] = ns[0x7] = (pkt, u8_body) => {
|
|
336
|
-
const rdr = new mqtt_type_reader(u8_body, 0);
|
|
337
415
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
416
|
+
function _puback_v5(mqtt_reader) {
|
|
417
|
+
mqtt_reader.reasons('puback',
|
|
418
|
+
// MQTT 5.0
|
|
419
|
+
[ 0x00, 'Success'],
|
|
420
|
+
[ 0x10, 'No matching subscribers'],
|
|
421
|
+
[ 0x80, 'Unspecified error'],
|
|
422
|
+
[ 0x83, 'Implementation specific error'],
|
|
423
|
+
[ 0x87, 'Not authorized'],
|
|
424
|
+
[ 0x90, 'Topic Name invalid'],
|
|
425
|
+
[ 0x91, 'Packet identifier in use'],
|
|
426
|
+
[ 0x97, 'Quota exceeded'],
|
|
427
|
+
[ 0x99, 'Payload format invalid'],
|
|
428
|
+
);
|
|
343
429
|
}
|
|
344
430
|
|
|
345
|
-
function _mqtt_decode_suback(
|
|
431
|
+
function _mqtt_decode_suback(mqtt_reader) {
|
|
346
432
|
return (pkt, u8_body) => {
|
|
347
|
-
|
|
433
|
+
let rdr = mqtt_reader.of(u8_body);
|
|
348
434
|
|
|
349
435
|
pkt.pkt_id = rdr.u16();
|
|
350
436
|
if (5 <= pkt.mqtt_level)
|
|
351
437
|
pkt.props = rdr.props();
|
|
352
438
|
|
|
353
|
-
|
|
439
|
+
let answers = pkt.answers = [];
|
|
354
440
|
while (rdr.has_more())
|
|
355
441
|
answers.push(
|
|
356
|
-
rdr.
|
|
442
|
+
rdr.reason(pkt.type) );
|
|
357
443
|
|
|
358
444
|
return pkt }
|
|
359
445
|
}
|
|
360
446
|
|
|
361
|
-
function mqtt_decode_suback(ns) {
|
|
362
|
-
|
|
447
|
+
function mqtt_decode_suback(ns, mqtt_reader) {
|
|
448
|
+
return ns[0x9] = _mqtt_decode_suback(mqtt_reader)
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function _suback_v4(mqtt_reader) {
|
|
452
|
+
mqtt_reader.reasons('suback',
|
|
363
453
|
// MQTT 3.1.1
|
|
364
454
|
[ 0x00, 'Granted QoS 0'],
|
|
365
455
|
[ 0x01, 'Granted QoS 1'],
|
|
366
456
|
[ 0x02, 'Granted QoS 2'],
|
|
457
|
+
);
|
|
458
|
+
}
|
|
367
459
|
|
|
460
|
+
function _suback_v5(mqtt_reader) {
|
|
461
|
+
_suback_v4(mqtt_reader);
|
|
462
|
+
|
|
463
|
+
mqtt_reader.reasons('suback',
|
|
368
464
|
// MQTT 5.0
|
|
369
465
|
[ 0x80, 'Unspecified error'],
|
|
370
466
|
[ 0x83, 'Implementation specific error'],
|
|
@@ -375,13 +471,16 @@ function mqtt_decode_suback(ns) {
|
|
|
375
471
|
[ 0x9E, 'Shared Subscriptions not supported'],
|
|
376
472
|
[ 0xA1, 'Subscription Identifiers not supported'],
|
|
377
473
|
[ 0xA2, 'Wildcard Subscriptions not supported'],
|
|
378
|
-
|
|
474
|
+
);
|
|
475
|
+
}
|
|
379
476
|
|
|
380
|
-
|
|
477
|
+
function mqtt_decode_unsuback(ns, mqtt_reader) {
|
|
478
|
+
return ns[0xb] = _mqtt_decode_suback(mqtt_reader)
|
|
381
479
|
}
|
|
382
480
|
|
|
383
|
-
function
|
|
384
|
-
|
|
481
|
+
function _unsuback_v4(mqtt_reader) {
|
|
482
|
+
mqtt_reader.reasons('unsuback',
|
|
483
|
+
// MQTT 3.1.1
|
|
385
484
|
[ 0x00, 'Success'],
|
|
386
485
|
[ 0x11, 'No subscription existed'],
|
|
387
486
|
[ 0x80, 'Unspecified error'],
|
|
@@ -389,17 +488,26 @@ function mqtt_decode_unsuback(ns) {
|
|
|
389
488
|
[ 0x87, 'Not authorized'],
|
|
390
489
|
[ 0x8F, 'Topic Filter invalid'],
|
|
391
490
|
[ 0x91, 'Packet Identifier in use'],
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
return ns[0xb] = _mqtt_decode_suback(_unsuback_reason_)
|
|
491
|
+
);
|
|
395
492
|
}
|
|
396
493
|
|
|
397
494
|
function mqtt_decode_pingxxx(ns) {
|
|
398
495
|
return ns[0xc] = ns[0xd] = pkt => pkt
|
|
399
496
|
}
|
|
400
497
|
|
|
401
|
-
function mqtt_decode_disconnect(ns) {
|
|
402
|
-
|
|
498
|
+
function mqtt_decode_disconnect(ns, mqtt_reader) {
|
|
499
|
+
return ns[0xe] = (pkt, u8_body) => {
|
|
500
|
+
if (u8_body && 5 <= pkt.mqtt_level) {
|
|
501
|
+
let rdr = mqtt_reader.of(u8_body);
|
|
502
|
+
pkt.reason = rdr.reason(pkt.type);
|
|
503
|
+
pkt.props = rdr.props();
|
|
504
|
+
}
|
|
505
|
+
return pkt }
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
function _disconnect_v5(mqtt_reader) {
|
|
510
|
+
mqtt_reader.reasons('disconnect',
|
|
403
511
|
// MQTT 5.0
|
|
404
512
|
[ 0x00, 'Normal disconnection'],
|
|
405
513
|
[ 0x04, 'Disconnect with Will Message'],
|
|
@@ -430,181 +538,33 @@ function mqtt_decode_disconnect(ns) {
|
|
|
430
538
|
[ 0xA0, 'Maximum connect time'],
|
|
431
539
|
[ 0xA1, 'Subscription Identifiers not supported'],
|
|
432
540
|
[ 0xA2, 'Wildcard Subscriptions not supported'],
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
return ns[0xe] = (pkt, u8_body) => {
|
|
437
|
-
if (u8_body && 5 <= pkt.mqtt_level) {
|
|
438
|
-
const rdr = new mqtt_type_reader(u8_body, 0);
|
|
439
|
-
pkt.reason = rdr.u8_reason(_disconnect_reason_);
|
|
440
|
-
pkt.props = rdr.props();
|
|
441
|
-
}
|
|
442
|
-
return pkt }
|
|
541
|
+
);
|
|
443
542
|
}
|
|
444
543
|
|
|
445
|
-
function mqtt_decode_auth(ns) {
|
|
446
|
-
const _auth_reason_ = bind_reason_lookup([
|
|
447
|
-
// MQTT 5.0
|
|
448
|
-
[ 0x00, 'Success' ],
|
|
449
|
-
[ 0x18, 'Continue authentication' ],
|
|
450
|
-
[ 0x19, 'Re-authenticate' ],
|
|
451
|
-
]);
|
|
452
|
-
|
|
544
|
+
function mqtt_decode_auth(ns, mqtt_reader) {
|
|
453
545
|
return ns[0xf] = (pkt, u8_body) => {
|
|
454
546
|
if ( 5 <= pkt.mqtt_level ) {
|
|
455
|
-
|
|
456
|
-
pkt.reason = rdr.
|
|
547
|
+
let rdr = mqtt_reader.of(u8_body);
|
|
548
|
+
pkt.reason = rdr.reason(pkt.type);
|
|
457
549
|
pkt.props = rdr.props();
|
|
458
550
|
}
|
|
459
551
|
return pkt }
|
|
460
552
|
}
|
|
461
553
|
|
|
462
|
-
function mqtt_pkt_writer_pool() {
|
|
463
|
-
const _pool_ = [];
|
|
464
|
-
return host =>
|
|
465
|
-
0 === _pool_.length
|
|
466
|
-
? mqtt_pkt_writer(host, _pool_)
|
|
467
|
-
: _pool_.pop()(host)
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
function mqtt_pkt_writer(host, _pool_) {
|
|
471
|
-
// avoid GCing push/pull when they can be reused
|
|
472
|
-
let n=0, rope=[];
|
|
473
|
-
return install(host)
|
|
474
554
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
rope.push(u8);
|
|
483
|
-
n += u8.length;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
function pack(hdr) {
|
|
487
|
-
host = host.push = host.pack = null;
|
|
488
|
-
|
|
489
|
-
const res = _mqtt_pkt_rope(hdr, n, rope);
|
|
490
|
-
n=0; rope=[];
|
|
491
|
-
if (undefined !== _pool_)
|
|
492
|
-
_pool_.push(install);
|
|
493
|
-
|
|
494
|
-
return res
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
function _mqtt_pkt_rope(hdr, n, rope) {
|
|
500
|
-
const header = encode_varint(n, hdr);
|
|
501
|
-
let i = header.length;
|
|
502
|
-
|
|
503
|
-
const pkt = new Uint8Array(n + i);
|
|
504
|
-
pkt.set(header, 0);
|
|
505
|
-
for (const vec of rope) {
|
|
506
|
-
pkt.set(vec, i);
|
|
507
|
-
i += vec.length;
|
|
508
|
-
}
|
|
509
|
-
return pkt
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
const _is_array = Array.isArray;
|
|
513
|
-
const pack_utf8 = v => new TextEncoder('utf-8').encode(v);
|
|
514
|
-
const pack_u16 = v => [ (v>>>8) & 0xff, v & 0xff ];
|
|
515
|
-
const pack_u32 = v => [ (v>>>24) & 0xff, (v>>>16) & 0xff, (v>>>8) & 0xff, v & 0xff ];
|
|
516
|
-
|
|
517
|
-
class mqtt_type_writer {
|
|
518
|
-
constructor() {
|
|
519
|
-
this._pkt_writer(this);
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
as_pkt(hdr) { return this.pack([hdr]) }
|
|
523
|
-
|
|
524
|
-
u8(v) { this.push([ v & 0xff ]);}
|
|
525
|
-
u16(v) { this.push( pack_u16(v) );}
|
|
526
|
-
u32(v) { this.push( pack_u32(v) );}
|
|
527
|
-
vint(v) { this.push( encode_varint(v) );}
|
|
528
|
-
|
|
529
|
-
_u16_bin(u8_buf) {
|
|
530
|
-
const {push} = this;
|
|
531
|
-
push( pack_u16( u8_buf.byteLength ));
|
|
532
|
-
push( u8_buf );
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
flush(buf) {
|
|
536
|
-
if (null != buf)
|
|
537
|
-
this.push(
|
|
538
|
-
'string' === typeof buf
|
|
539
|
-
? pack_utf8(buf) : buf );
|
|
540
|
-
|
|
541
|
-
this.push = false;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
bin(u8_buf) {
|
|
545
|
-
if (! u8_buf) return this.u16(0)
|
|
546
|
-
if ('string' === typeof u8_buf)
|
|
547
|
-
return this.utf8(u8_buf)
|
|
548
|
-
|
|
549
|
-
if (u8_buf.length !== u8_buf.byteLength)
|
|
550
|
-
u8_buf = new Uint8Array(u8_buf);
|
|
551
|
-
this._u16_bin(u8_buf);
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
utf8(v) { this._u16_bin( new TextEncoder('utf-8').encode(v) ); }
|
|
555
|
-
|
|
556
|
-
pair(k,v) {
|
|
557
|
-
this.utf8(k);
|
|
558
|
-
this.utf8(v);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
u8_flags(v, enc_flags, b0=0) {
|
|
562
|
-
if (undefined !== v && isNaN(+v))
|
|
563
|
-
v = enc_flags(v, 0);
|
|
564
|
-
|
|
565
|
-
v |= b0;
|
|
566
|
-
this.push([v]);
|
|
567
|
-
return v
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
u8_reason(v) { this.push([v | 0]); }
|
|
571
|
-
|
|
572
|
-
props(props) {
|
|
573
|
-
if (! props)
|
|
574
|
-
return this.u8(0)
|
|
575
|
-
|
|
576
|
-
if (! _is_array(props))
|
|
577
|
-
props = props.entries
|
|
578
|
-
? Array.from(props.entries())
|
|
579
|
-
: Object.entries(props);
|
|
580
|
-
|
|
581
|
-
if (0 === props.length)
|
|
582
|
-
return this.u8(0)
|
|
583
|
-
|
|
584
|
-
const wrt = this._fork();
|
|
585
|
-
for (const [name, value] of props) {
|
|
586
|
-
const {id, type} = mqtt_props.get(name);
|
|
587
|
-
wrt.u8(id);
|
|
588
|
-
wrt[type](value);
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
this.push(wrt.pack([]));
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
_fork() {
|
|
595
|
-
let self = { __proto__: this };
|
|
596
|
-
this._pkt_writer(self);
|
|
597
|
-
return self
|
|
598
|
-
}
|
|
555
|
+
function _auth_v5(mqtt_reader) {
|
|
556
|
+
mqtt_reader.reasons('auth',
|
|
557
|
+
// MQTT 5.0
|
|
558
|
+
[ 0x00, 'Success' ],
|
|
559
|
+
[ 0x18, 'Continue authentication' ],
|
|
560
|
+
[ 0x19, 'Re-authenticate' ],
|
|
561
|
+
);
|
|
599
562
|
}
|
|
600
563
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
const _c_mqtt_proto = new Uint8Array([
|
|
605
|
-
0, 4, 0x4d, 0x51, 0x54, 0x54 ]);
|
|
564
|
+
function mqtt_encode_connect(ns, mqtt_writer) {
|
|
565
|
+
const _c_mqtt_proto = new Uint8Array([
|
|
566
|
+
0, 4, 0x4d, 0x51, 0x54, 0x54 ]);
|
|
606
567
|
|
|
607
|
-
function mqtt_encode_connect(ns) {
|
|
608
568
|
const _enc_flags_connect = flags => 0
|
|
609
569
|
| ( flags.reserved ? 0x01 : 0 )
|
|
610
570
|
| ( (flags.will_qos & 0x3) << 3 )
|
|
@@ -619,13 +579,13 @@ function mqtt_encode_connect(ns) {
|
|
|
619
579
|
| ( will.retain ? 0x20 : 0 );
|
|
620
580
|
|
|
621
581
|
return ns.connect = ( mqtt_level, pkt ) => {
|
|
622
|
-
|
|
582
|
+
let wrt = mqtt_writer.of(pkt);
|
|
623
583
|
|
|
624
584
|
wrt.push(_c_mqtt_proto);
|
|
625
585
|
wrt.u8( mqtt_level );
|
|
626
586
|
|
|
627
|
-
|
|
628
|
-
|
|
587
|
+
let {will, username, password} = pkt;
|
|
588
|
+
let flags = wrt.flags(
|
|
629
589
|
pkt.flags,
|
|
630
590
|
_enc_flags_connect,
|
|
631
591
|
0 | (username ? 0x80 : 0)
|
|
@@ -657,10 +617,10 @@ function mqtt_encode_connect(ns) {
|
|
|
657
617
|
}
|
|
658
618
|
}
|
|
659
619
|
|
|
660
|
-
function mqtt_encode_publish(ns) {
|
|
620
|
+
function mqtt_encode_publish(ns, mqtt_writer) {
|
|
661
621
|
return ns.publish = ( mqtt_level, pkt ) => {
|
|
662
|
-
|
|
663
|
-
|
|
622
|
+
let qos = (pkt.qos & 0x3) << 1;
|
|
623
|
+
let wrt = mqtt_writer.of(pkt);
|
|
664
624
|
|
|
665
625
|
wrt.utf8(pkt.topic);
|
|
666
626
|
if (0 !== qos)
|
|
@@ -678,13 +638,13 @@ function mqtt_encode_publish(ns) {
|
|
|
678
638
|
}
|
|
679
639
|
}
|
|
680
640
|
|
|
681
|
-
function mqtt_encode_puback(ns) {
|
|
641
|
+
function mqtt_encode_puback(ns, mqtt_writer) {
|
|
682
642
|
return ns.puback = ( mqtt_level, pkt ) => {
|
|
683
|
-
|
|
643
|
+
let wrt = mqtt_writer.of(pkt);
|
|
684
644
|
|
|
685
645
|
wrt.u16(pkt.pkt_id);
|
|
686
646
|
if (5 <= mqtt_level) {
|
|
687
|
-
wrt.
|
|
647
|
+
wrt.reason(pkt.reason);
|
|
688
648
|
wrt.props(pkt.props);
|
|
689
649
|
}
|
|
690
650
|
|
|
@@ -692,32 +652,32 @@ function mqtt_encode_puback(ns) {
|
|
|
692
652
|
}
|
|
693
653
|
}
|
|
694
654
|
|
|
695
|
-
function mqtt_encode_subscribe(ns) {
|
|
655
|
+
function mqtt_encode_subscribe(ns, mqtt_writer) {
|
|
696
656
|
const _enc_subscribe_flags = opts => 0
|
|
697
657
|
| ( opts.qos & 0x3 )
|
|
698
658
|
| ( opts.retain ? 0x4 : 0 )
|
|
699
659
|
| ( (opts.retain_handling & 0x3) << 2 );
|
|
700
660
|
|
|
701
661
|
return ns.subscribe = ( mqtt_level, pkt ) => {
|
|
702
|
-
|
|
662
|
+
let wrt = mqtt_writer.of(pkt);
|
|
703
663
|
|
|
704
664
|
wrt.u16(pkt.pkt_id);
|
|
705
665
|
if (5 <= mqtt_level)
|
|
706
666
|
wrt.props(pkt.props);
|
|
707
667
|
|
|
708
|
-
|
|
709
|
-
for (
|
|
668
|
+
let f0 = _enc_subscribe_flags(pkt);
|
|
669
|
+
for (let each of pkt.topics) {
|
|
710
670
|
if ('string' === typeof each) {
|
|
711
671
|
wrt.utf8(each);
|
|
712
672
|
wrt.u8(f0);
|
|
713
673
|
} else {
|
|
714
674
|
let [topic, opts] =
|
|
715
|
-
|
|
675
|
+
Array.isArray(each) ? each
|
|
716
676
|
: [each.topic, each.opts];
|
|
717
677
|
|
|
718
678
|
wrt.utf8(topic);
|
|
719
679
|
if (undefined === opts) wrt.u8(f0);
|
|
720
|
-
else wrt.
|
|
680
|
+
else wrt.flags(opts, _enc_subscribe_flags);
|
|
721
681
|
}
|
|
722
682
|
}
|
|
723
683
|
|
|
@@ -725,15 +685,15 @@ function mqtt_encode_subscribe(ns) {
|
|
|
725
685
|
}
|
|
726
686
|
}
|
|
727
687
|
|
|
728
|
-
function mqtt_encode_unsubscribe(ns) {
|
|
688
|
+
function mqtt_encode_unsubscribe(ns, mqtt_writer) {
|
|
729
689
|
return ns.unsubscribe = ( mqtt_level, pkt ) => {
|
|
730
|
-
|
|
690
|
+
let wrt = mqtt_writer.of(pkt);
|
|
731
691
|
|
|
732
692
|
wrt.u16(pkt.pkt_id);
|
|
733
693
|
if (5 <= mqtt_level)
|
|
734
694
|
wrt.props(pkt.props);
|
|
735
695
|
|
|
736
|
-
for (
|
|
696
|
+
for (let topic of pkt.topics)
|
|
737
697
|
wrt.utf8(topic);
|
|
738
698
|
|
|
739
699
|
return wrt.as_pkt(0xa2)
|
|
@@ -745,13 +705,13 @@ function mqtt_encode_pingxxx(ns) {
|
|
|
745
705
|
ns.pingresp = () => new Uint8Array([ 0xd0, 0 ]);
|
|
746
706
|
}
|
|
747
707
|
|
|
748
|
-
function mqtt_encode_disconnect(ns) {
|
|
708
|
+
function mqtt_encode_disconnect(ns, mqtt_writer) {
|
|
749
709
|
return ns.disconnect = ( mqtt_level, pkt ) => {
|
|
750
|
-
|
|
710
|
+
let wrt = mqtt_writer.of(pkt);
|
|
751
711
|
|
|
752
712
|
if (pkt && 5 <= mqtt_level) {
|
|
753
713
|
if (pkt.reason || pkt.props) {
|
|
754
|
-
wrt.
|
|
714
|
+
wrt.reason(pkt.reason);
|
|
755
715
|
wrt.props(pkt.props);
|
|
756
716
|
}
|
|
757
717
|
}
|
|
@@ -760,185 +720,250 @@ function mqtt_encode_disconnect(ns) {
|
|
|
760
720
|
}
|
|
761
721
|
}
|
|
762
722
|
|
|
763
|
-
function mqtt_encode_auth(ns) {
|
|
723
|
+
function mqtt_encode_auth(ns, mqtt_writer) {
|
|
764
724
|
return ns.auth = ( mqtt_level, pkt ) => {
|
|
765
725
|
if (5 > mqtt_level)
|
|
766
726
|
throw new Error('Auth packets are only available after MQTT 5.x')
|
|
767
727
|
|
|
768
|
-
|
|
728
|
+
let wrt = mqtt_writer.of(pkt);
|
|
769
729
|
|
|
770
|
-
wrt.
|
|
730
|
+
wrt.reason(pkt.reason);
|
|
771
731
|
wrt.props(pkt.props);
|
|
772
732
|
|
|
773
733
|
return wrt.as_pkt(0xf0)
|
|
774
734
|
}
|
|
775
735
|
}
|
|
776
736
|
|
|
737
|
+
const mqtt_decode_v5 = [
|
|
738
|
+
mqtt_decode_connack,
|
|
739
|
+
mqtt_decode_publish,
|
|
740
|
+
mqtt_decode_puback,
|
|
741
|
+
mqtt_decode_suback,
|
|
742
|
+
mqtt_decode_unsuback,
|
|
743
|
+
mqtt_decode_pingxxx,
|
|
744
|
+
mqtt_decode_disconnect,
|
|
745
|
+
mqtt_decode_auth,
|
|
746
|
+
];
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
const mqtt_encode_v5 = [
|
|
750
|
+
mqtt_encode_connect,
|
|
751
|
+
mqtt_encode_puback,
|
|
752
|
+
mqtt_encode_publish,
|
|
753
|
+
mqtt_encode_subscribe,
|
|
754
|
+
mqtt_encode_unsubscribe,
|
|
755
|
+
mqtt_encode_pingxxx,
|
|
756
|
+
mqtt_encode_disconnect,
|
|
757
|
+
mqtt_encode_auth,
|
|
758
|
+
];
|
|
759
|
+
|
|
760
|
+
const mqtt_reader_v5 = /* #__PURE__ */
|
|
761
|
+
mqtt_reader_info(
|
|
762
|
+
mqtt_reader_v5$1,
|
|
763
|
+
_connack_v5,
|
|
764
|
+
_puback_v5,
|
|
765
|
+
_suback_v5,
|
|
766
|
+
_unsuback_v4,
|
|
767
|
+
_disconnect_v5,
|
|
768
|
+
_auth_v5,
|
|
769
|
+
);
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
const mqtt_opts_v5 =
|
|
773
|
+
{ decode_fns: mqtt_decode_v5,
|
|
774
|
+
mqtt_reader: mqtt_reader_v5,
|
|
775
|
+
encode_fns: mqtt_encode_v5,
|
|
776
|
+
mqtt_writer: mqtt_writer_v5, };
|
|
777
777
|
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
778
|
+
/*
|
|
779
|
+
export function decode_varint_loop(u8, i=0) {
|
|
780
|
+
let i0 = i
|
|
781
|
+
let shift = 0, n = (u8[i] & 0x7f)
|
|
782
|
+
while ( 0x80 & u8[i++] )
|
|
783
|
+
n |= (u8[i] & 0x7f) << (shift += 7)
|
|
781
784
|
|
|
782
|
-
return
|
|
783
|
-
(b0, u8_body) => {
|
|
784
|
-
const decode_pkt = by_id[b0>>>4] || by_id[0];
|
|
785
|
-
if (undefined !== decode_pkt)
|
|
786
|
-
return decode_pkt({__proto__: _pkt_ctx_, b0}, u8_body)
|
|
787
|
-
})
|
|
785
|
+
return [n, i, i0]
|
|
788
786
|
}
|
|
787
|
+
*/
|
|
789
788
|
|
|
790
789
|
|
|
791
|
-
function
|
|
792
|
-
|
|
793
|
-
for
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
790
|
+
function decode_varint(u8, i=0) {
|
|
791
|
+
let i0 = i;
|
|
792
|
+
// unrolled for a max of 4 chains
|
|
793
|
+
let n = (u8[i] & 0x7f) << 0;
|
|
794
|
+
if ( 0x80 & u8[i++] ) {
|
|
795
|
+
n |= (u8[i] & 0x7f) << 7;
|
|
796
|
+
if ( 0x80 & u8[i++] ) {
|
|
797
|
+
n |= (u8[i] & 0x7f) << 14;
|
|
798
|
+
if ( 0x80 & u8[i++] ) {
|
|
799
|
+
n |= (u8[i] & 0x7f) << 21;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return [n, i, i0]
|
|
797
804
|
}
|
|
798
805
|
|
|
806
|
+
function mqtt_raw_dispatch(opt) {
|
|
807
|
+
let u8 = new Uint8Array(0);
|
|
808
|
+
return u8_buf => {
|
|
809
|
+
u8 = 0 === u8.byteLength
|
|
810
|
+
? u8_buf : _u8_join(u8, u8_buf);
|
|
799
811
|
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
id: {get() { return this.b0 >>> 4 }},
|
|
805
|
-
type: {get() { return _pkt_types[this.b0 >>> 4] }},
|
|
806
|
-
});
|
|
812
|
+
let res = [];
|
|
813
|
+
while (1) {
|
|
814
|
+
let [len_body, len_vh] = decode_varint(u8, 1);
|
|
815
|
+
let len_pkt = len_body + len_vh;
|
|
807
816
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
sess_encode = _bind_mqtt_encode(sess_encode);
|
|
811
|
-
_pkt_ctx_ = _bind_pkt_ctx(_pkt_ctx_);
|
|
817
|
+
if ( u8.byteLength < len_pkt )
|
|
818
|
+
return res
|
|
812
819
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
}
|
|
820
|
+
let b0 = u8[0];
|
|
821
|
+
let u8_body = 0 === len_body ? null
|
|
822
|
+
: u8.subarray(len_vh, len_pkt);
|
|
817
823
|
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
let std_pkt_api = {
|
|
825
|
-
utf8(u8) { return as_utf8( u8 || this.payload ) },
|
|
826
|
-
json(u8) { return JSON.parse( this.utf8(u8) || null ) },
|
|
827
|
-
text(u8) { return this.utf8(u8) },
|
|
828
|
-
};
|
|
829
|
-
|
|
830
|
-
mqtt_session_ctx.ctx = ctx =
|
|
831
|
-
_bind_mqtt_session_ctx(
|
|
832
|
-
[ // lst_decode_ops
|
|
833
|
-
mqtt_decode_connack,
|
|
834
|
-
mqtt_decode_disconnect,
|
|
835
|
-
mqtt_decode_publish,
|
|
836
|
-
mqtt_decode_puback,
|
|
837
|
-
mqtt_decode_pubxxx,
|
|
838
|
-
mqtt_decode_pingxxx,
|
|
839
|
-
mqtt_decode_suback,
|
|
840
|
-
mqtt_decode_unsuback,
|
|
841
|
-
mqtt_decode_auth, ],
|
|
842
|
-
|
|
843
|
-
[ // lst_encode_ops
|
|
844
|
-
mqtt_encode_connect,
|
|
845
|
-
mqtt_encode_disconnect,
|
|
846
|
-
mqtt_encode_publish,
|
|
847
|
-
mqtt_encode_puback,
|
|
848
|
-
mqtt_encode_pingxxx,
|
|
849
|
-
mqtt_encode_subscribe,
|
|
850
|
-
mqtt_encode_unsubscribe,
|
|
851
|
-
mqtt_encode_auth, ],
|
|
852
|
-
|
|
853
|
-
std_pkt_api );
|
|
824
|
+
u8 = u8.subarray(len_pkt);
|
|
825
|
+
|
|
826
|
+
let pkt = opt.decode_pkt(b0, u8_body, opt);
|
|
827
|
+
if (null != pkt)
|
|
828
|
+
res.push( pkt );
|
|
829
|
+
}
|
|
854
830
|
}
|
|
831
|
+
}
|
|
855
832
|
|
|
856
|
-
|
|
833
|
+
function _u8_join(a, b) {
|
|
834
|
+
let alen = a.byteLength, r = new Uint8Array(alen + b.byteLength);
|
|
835
|
+
r.set(a, 0);
|
|
836
|
+
r.set(b, alen);
|
|
837
|
+
return r
|
|
857
838
|
}
|
|
858
839
|
|
|
859
|
-
|
|
860
|
-
let q0 = _tiny_deferred_queue();
|
|
861
|
-
let q = _tiny_deferred_queue();
|
|
840
|
+
const _pkt_types = ['~', 'connect', 'connack', 'publish', 'puback', 'pubrec', 'pubrel', 'pubcomp', 'subscribe', 'suback', 'unsubscribe', 'unsuback', 'pingreq', 'pingresp', 'disconnect', 'auth'];
|
|
862
841
|
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
842
|
+
function mqtt_pkt_ctx(mqtt_level, opts, pkt_ctx) {
|
|
843
|
+
pkt_ctx = {
|
|
844
|
+
__proto__: pkt_ctx || opts.pkt_ctx,
|
|
845
|
+
mqtt_level,
|
|
846
|
+
get hdr() { return this.b0 & 0xf },
|
|
847
|
+
get id() { return this.b0 >>> 4 },
|
|
848
|
+
get type() { return _pkt_types[this.b0 >>> 4] },
|
|
849
|
+
};
|
|
866
850
|
|
|
867
|
-
let
|
|
868
|
-
|
|
851
|
+
let op, _decode_by_id=[], _encode_by_type={};
|
|
852
|
+
for (op of opts.encode_fns)
|
|
853
|
+
op(_encode_by_type, opts.mqtt_writer);
|
|
854
|
+
for (op of opts.decode_fns)
|
|
855
|
+
op(_decode_by_id, opts.mqtt_reader);
|
|
869
856
|
|
|
870
857
|
return {
|
|
871
|
-
|
|
872
|
-
, is_set: (() =>_is_set)
|
|
858
|
+
pkt_ctx,
|
|
873
859
|
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
client._send = _send = _asy_send;
|
|
877
|
-
_is_set = false;
|
|
860
|
+
encode_pkt(type, pkt) {
|
|
861
|
+
return _encode_by_type[type]( mqtt_level, pkt ) },
|
|
878
862
|
|
|
879
|
-
|
|
880
|
-
|
|
863
|
+
decode_pkt(b0, u8_body) {
|
|
864
|
+
let fn_decode = _decode_by_id[b0>>>4] || _decode_by_id[0];
|
|
865
|
+
return fn_decode?.({__proto__: this.pkt_ctx, b0}, u8_body) },
|
|
881
866
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
867
|
+
mqtt_stream() {
|
|
868
|
+
let self = { __proto__: this, pkt_ctx: { __proto__: pkt_ctx } };
|
|
869
|
+
self.pkt_ctx._base_ = self.pkt_ctx;
|
|
870
|
+
self.decode = mqtt_raw_dispatch(self);
|
|
871
|
+
return self
|
|
872
|
+
},
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
Object.freeze({ao_done: true});
|
|
877
|
+
|
|
878
|
+
function ao_defer_ctx(as_res = (...args) => args) {
|
|
879
|
+
let y,n,_pset = (a,b) => { y=a, n=b; };
|
|
880
|
+
return p =>(
|
|
881
|
+
p = new Promise(_pset)
|
|
882
|
+
, as_res(p, y, n)) }
|
|
883
|
+
|
|
884
|
+
const ao_defer_v = /* #__PURE__ */
|
|
885
|
+
ao_defer_ctx();
|
|
886
|
+
|
|
887
|
+
Promise.resolve({type:'init'});
|
|
888
|
+
|
|
889
|
+
function _mqtt_conn(client, [on_mqtt, pkt_future]) {
|
|
890
|
+
let _q_init = ao_defer_v(), _q_ready = ao_defer_v();
|
|
891
|
+
let _send_ready = async (...args) => (await _q_ready[0])(...args);
|
|
892
|
+
let _send_mqtt_pkt, _has_connected;
|
|
893
|
+
client._send = _send_ready;
|
|
894
|
+
|
|
895
|
+
return {
|
|
896
|
+
async when_ready() {await _q_ready[0];}
|
|
897
|
+
|
|
898
|
+
, ping: _ping_interval (() =>_send_mqtt_pkt?.('pingreq'))
|
|
899
|
+
|
|
900
|
+
, reset(err) {
|
|
901
|
+
if (! _send_mqtt_pkt) {return}
|
|
902
|
+
|
|
903
|
+
if (err) {
|
|
904
|
+
_q_init[2](err);}
|
|
905
|
+
|
|
906
|
+
_send_mqtt_pkt = null;
|
|
907
|
+
_q_init = ao_defer_v();
|
|
908
|
+
client._send = _send_ready;
|
|
909
|
+
|
|
910
|
+
// call client.on_conn_reset in next promise microtask
|
|
911
|
+
client.conn_emit('on_disconnect', false===err, err);}
|
|
888
912
|
|
|
889
913
|
, async send_connect(... args) {
|
|
890
|
-
if (
|
|
891
|
-
|
|
914
|
+
if (! _send_mqtt_pkt) {
|
|
915
|
+
await _q_init[0]; }// _send_mqtt_pkt is set before fulfilled
|
|
892
916
|
|
|
893
917
|
// await connack response
|
|
894
|
-
let res = await
|
|
918
|
+
let res = await _send_mqtt_pkt(...args);
|
|
919
|
+
if (0 == res[0].reason) {
|
|
920
|
+
_has_connected = true;
|
|
921
|
+
// resolve _q_ready[0] with _send_mqtt_pkt closure
|
|
922
|
+
_q_ready[1](client._send = _send_mqtt_pkt);
|
|
923
|
+
_q_ready = ao_defer_v();
|
|
924
|
+
client.conn_emit('on_ready');}
|
|
895
925
|
|
|
896
|
-
client._send = _send;
|
|
897
|
-
q.notify(_send);
|
|
898
926
|
return res}
|
|
899
927
|
|
|
900
|
-
,
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
928
|
+
, is_set: (() =>!! _send_mqtt_pkt)
|
|
929
|
+
, set(mqtt_ctx, send_u8_pkt) {
|
|
930
|
+
if (_send_mqtt_pkt) {
|
|
931
|
+
throw new Error('Already connected')}
|
|
904
932
|
|
|
933
|
+
mqtt_ctx = mqtt_ctx.mqtt_stream();
|
|
934
|
+
let sess_ctx = {mqtt: client};
|
|
905
935
|
let on_mqtt_chunk = u8_buf =>
|
|
906
|
-
on_mqtt(
|
|
907
|
-
mqtt_decode(u8_buf),
|
|
908
|
-
{mqtt: client});
|
|
936
|
+
on_mqtt(mqtt_ctx.decode(u8_buf), sess_ctx);
|
|
909
937
|
|
|
910
|
-
|
|
938
|
+
_send_mqtt_pkt = async (type, pkt, key) => {
|
|
911
939
|
let res = undefined !== key
|
|
912
940
|
? pkt_future(key) : true;
|
|
913
941
|
|
|
914
942
|
await send_u8_pkt(
|
|
915
|
-
|
|
943
|
+
mqtt_ctx.encode_pkt(type, pkt));
|
|
916
944
|
|
|
917
945
|
return res};
|
|
918
946
|
|
|
919
|
-
|
|
920
|
-
q0.notify(_send);
|
|
947
|
+
_q_init[1](_send_mqtt_pkt); // resolve _q_init with _send_mqtt_pkt closure
|
|
921
948
|
|
|
922
949
|
// call client.on_live in next promise microtask
|
|
923
|
-
|
|
924
|
-
|
|
950
|
+
client.conn_emit('on_live', _has_connected);
|
|
925
951
|
return on_mqtt_chunk} } }
|
|
926
952
|
|
|
927
953
|
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
}
|
|
954
|
+
function _ping_interval(send_ping) {
|
|
955
|
+
let tid;
|
|
956
|
+
return (( td ) => {
|
|
957
|
+
tid = clearInterval(tid);
|
|
958
|
+
if (td) {
|
|
959
|
+
tid = setInterval(send_ping, 1000 * td);
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
// ensure the interval allows the NodeJS event loop to exit
|
|
965
|
+
tid.unref?.();
|
|
966
|
+
return true} }) }
|
|
942
967
|
|
|
943
968
|
function parse(str, loose) {
|
|
944
969
|
if (str instanceof RegExp) return { keys:false, pattern:str };
|
|
@@ -972,7 +997,7 @@ function parse(str, loose) {
|
|
|
972
997
|
function _ignore(pkt, params, ctx) {ctx.done = true;}
|
|
973
998
|
|
|
974
999
|
function _mqtt_topic_router() {
|
|
975
|
-
let pri_lsts = [[],[]];
|
|
1000
|
+
let pri_lsts = [[],[]], rm = Symbol();
|
|
976
1001
|
let find = topic => _mqtt_routes_iter(pri_lsts, topic);
|
|
977
1002
|
|
|
978
1003
|
return {find,
|
|
@@ -996,8 +1021,7 @@ function _mqtt_topic_router() {
|
|
|
996
1021
|
|
|
997
1022
|
, remove(topic_route, priority) {
|
|
998
1023
|
let lst = pri_lsts[priority ? 0 : 1];
|
|
999
|
-
|
|
1000
|
-
pri_lsts[priority ? 0 : 1] = lst;}
|
|
1024
|
+
return _mqtt_route_remove([lst], topic_route)}
|
|
1001
1025
|
|
|
1002
1026
|
, clear(priority) {
|
|
1003
1027
|
pri_lsts[priority ? 0 : 1] = [];
|
|
@@ -1006,9 +1030,13 @@ function _mqtt_topic_router() {
|
|
|
1006
1030
|
|
|
1007
1031
|
, async invoke(pkt, ctx) {
|
|
1008
1032
|
ctx.idx = 0;
|
|
1033
|
+
ctx.rm = rm;
|
|
1009
1034
|
|
|
1010
1035
|
for (let [fn, params] of find(pkt.topic)) {
|
|
1011
|
-
await fn(pkt, params, ctx);
|
|
1036
|
+
let res = await fn(pkt, params, ctx);
|
|
1037
|
+
|
|
1038
|
+
if (rm === res) {
|
|
1039
|
+
_mqtt_route_remove(pri_lsts, fn);}
|
|
1012
1040
|
|
|
1013
1041
|
if (ctx.done) {
|
|
1014
1042
|
break}
|
|
@@ -1054,6 +1082,14 @@ function _mqtt_route_match_one(topic, {keys, pattern, tgt}) {
|
|
|
1054
1082
|
params[ keys[i] ] = match[1+i];}
|
|
1055
1083
|
return [tgt, params]}
|
|
1056
1084
|
|
|
1085
|
+
|
|
1086
|
+
function _mqtt_route_remove(all_route_lists, query) {
|
|
1087
|
+
let match = route => route===query || route.tgt===query || route.key===query;
|
|
1088
|
+
for (let lst of all_route_lists) {
|
|
1089
|
+
let i = lst.findIndex(match);
|
|
1090
|
+
if (0 <= i) {return !! lst.splice(i,1)} }
|
|
1091
|
+
return false}
|
|
1092
|
+
|
|
1057
1093
|
const _mqtt_cmdid_dispatch ={
|
|
1058
1094
|
create(target) {
|
|
1059
1095
|
return {__proto__: this, target, hashbelt: [new Map()]} }
|
|
@@ -1146,20 +1182,38 @@ function _mqtt_dispatch(opt, target) {
|
|
|
1146
1182
|
_disp_.rotate_belt(rotate_n);
|
|
1147
1183
|
rotate_ts = rotate_td + Date.now();} } }
|
|
1148
1184
|
|
|
1149
|
-
class
|
|
1185
|
+
class MQTTError extends Error {
|
|
1186
|
+
constructor(mqtt_pkt, reason=mqtt_pkt.reason) {
|
|
1187
|
+
super(`[0x${reason.toString(16)}] ${reason.reason}`);
|
|
1188
|
+
this.mqtt_pkt = mqtt_pkt;
|
|
1189
|
+
this.reason = reason;} }
|
|
1190
|
+
|
|
1191
|
+
class MQTTBase {
|
|
1150
1192
|
constructor(opt={}) {
|
|
1151
1193
|
this._conn_ = _mqtt_conn(this,
|
|
1152
1194
|
this._init_dispatch(opt, this)); }
|
|
1153
1195
|
|
|
1196
|
+
async conn_emit(evt, arg, err_arg) {
|
|
1197
|
+
this.log_conn?.(evt, arg, err_arg);
|
|
1198
|
+
try {
|
|
1199
|
+
let fn_evt = this[await evt]; // microtask break
|
|
1200
|
+
if (fn_evt) {
|
|
1201
|
+
await fn_evt.call(this, this, arg, err_arg);}
|
|
1202
|
+
else if (err_arg) {
|
|
1203
|
+
await this.on_error(err_arg, evt);} }
|
|
1204
|
+
catch (err) {
|
|
1205
|
+
this.on_error(err, evt);} }
|
|
1206
|
+
|
|
1207
|
+
on_error(err, err_path) {
|
|
1208
|
+
console.warn('[[u8-mqtt error: %s]]', err_path, err); }
|
|
1209
|
+
|
|
1154
1210
|
// Handshaking Packets
|
|
1155
1211
|
|
|
1156
1212
|
async connect(pkt={}) {
|
|
1157
|
-
let
|
|
1158
|
-
if (
|
|
1159
|
-
pkt.client_id = cid = this.init_client_id(['u8-mqtt--', '']);}
|
|
1160
|
-
else if (Array.isArray(cid)) {
|
|
1213
|
+
let cid = pkt.client_id || ['u8-mqtt--', ''];
|
|
1214
|
+
if (Array.isArray(cid)) {
|
|
1161
1215
|
pkt.client_id = cid = this.init_client_id(cid);}
|
|
1162
|
-
|
|
1216
|
+
this.client_id = cid;
|
|
1163
1217
|
|
|
1164
1218
|
if (null == pkt.keep_alive) {
|
|
1165
1219
|
pkt.keep_alive = 60;}
|
|
@@ -1167,13 +1221,16 @@ class MQTTBaseClient {
|
|
|
1167
1221
|
let res = await this._conn_
|
|
1168
1222
|
.send_connect('connect', pkt, 'connack');
|
|
1169
1223
|
|
|
1224
|
+
if (0 != res[0].reason) {
|
|
1225
|
+
throw new this.MQTTError(res[0])}
|
|
1226
|
+
|
|
1170
1227
|
// TODO: merge with server's keep_alive frequency
|
|
1171
1228
|
this._conn_.ping(pkt.keep_alive);
|
|
1172
1229
|
return res}
|
|
1173
1230
|
|
|
1174
1231
|
async disconnect(pkt={}) {
|
|
1175
1232
|
let res = await this._send('disconnect', pkt);
|
|
1176
|
-
this._conn_.reset();
|
|
1233
|
+
this._conn_.reset(false);
|
|
1177
1234
|
return res}
|
|
1178
1235
|
|
|
1179
1236
|
auth(pkt={}) {
|
|
@@ -1187,8 +1244,9 @@ class MQTTBaseClient {
|
|
|
1187
1244
|
pkt = _as_topics(pkt, ex);
|
|
1188
1245
|
return this._send('subscribe', pkt, pkt)}
|
|
1189
1246
|
_sub_chain(topic, ex) {
|
|
1247
|
+
let res = this.subscribe([[ topic ]], ex);
|
|
1190
1248
|
let subs = this.subs ||(this.subs = new Map());
|
|
1191
|
-
subs.set(topic,
|
|
1249
|
+
subs.set((res.topic = topic), (subs.last = res));
|
|
1192
1250
|
return this }// fluent api -- return this and track side effects
|
|
1193
1251
|
|
|
1194
1252
|
// alias: unsub
|
|
@@ -1282,22 +1340,19 @@ class MQTTBaseClient {
|
|
|
1282
1340
|
return this.router = _mqtt_topic_router()}
|
|
1283
1341
|
|
|
1284
1342
|
_init_dispatch(opt) {
|
|
1285
|
-
let router = this._init_router(opt, this);
|
|
1286
|
-
|
|
1287
1343
|
let tgt ={
|
|
1288
1344
|
__proto__: opt.on_mqtt_type || {}
|
|
1289
|
-
, router};
|
|
1290
|
-
|
|
1291
|
-
if (! tgt.mqtt_publish) {
|
|
1292
|
-
tgt.mqtt_publish = router.invoke;}
|
|
1345
|
+
, router: this._init_router(opt, this)};
|
|
1293
1346
|
|
|
1347
|
+
tgt.mqtt_publish ||= tgt.router.invoke;
|
|
1294
1348
|
return _mqtt_dispatch(this, tgt)} }
|
|
1295
1349
|
|
|
1296
1350
|
|
|
1297
1351
|
{
|
|
1298
|
-
let p =
|
|
1352
|
+
let p = MQTTBase.prototype;
|
|
1299
1353
|
Object.assign(p,{
|
|
1300
|
-
|
|
1354
|
+
MQTTError
|
|
1355
|
+
, pub: p.publish
|
|
1301
1356
|
, sub: p.subscribe
|
|
1302
1357
|
, unsub: p.unsubscribe
|
|
1303
1358
|
, sub_topic: p.subscribe_topic
|
|
@@ -1376,45 +1431,67 @@ async function _pub(self, pkt, pub_opt) {
|
|
|
1376
1431
|
, oqr: (self, topic, msg, pub_opt) =>
|
|
1377
1432
|
_pub(self, {topic, msg, arg: 'msg', qos:1, retain: 1}, pub_opt)} ); }
|
|
1378
1433
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1434
|
+
const pkt_api = {
|
|
1435
|
+
utf8(u8) { return new TextDecoder('utf-8').decode(u8 || this.payload ) },
|
|
1436
|
+
json(u8) { return JSON.parse( this.utf8(u8) || null ) },
|
|
1437
|
+
text(u8) { return this.utf8(u8) },
|
|
1438
|
+
};
|
|
1382
1439
|
|
|
1440
|
+
class MQTTCore extends MQTTBase {
|
|
1383
1441
|
constructor(opt={}) {
|
|
1384
1442
|
super(opt);
|
|
1385
|
-
this.
|
|
1386
|
-
this.with_reconnect(opt.on_reconnect);}
|
|
1443
|
+
this.with(opt);}
|
|
1387
1444
|
|
|
1445
|
+
static mqtt_ctx(mqtt_level, mqtt_opts, pkt_ctx=pkt_api) {
|
|
1446
|
+
let self = class extends this {};
|
|
1447
|
+
self.prototype.mqtt_ctx =
|
|
1448
|
+
mqtt_pkt_ctx(mqtt_level, mqtt_opts, pkt_ctx);
|
|
1449
|
+
return self}
|
|
1388
1450
|
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
this.on_live = on_live;}
|
|
1393
|
-
|
|
1451
|
+
with(fns_ns) {
|
|
1452
|
+
for (let [k,v] of Object.entries(fns_ns)) {
|
|
1453
|
+
if ('function' === typeof v) {this[k] = v;} }
|
|
1394
1454
|
return this}
|
|
1395
1455
|
|
|
1396
|
-
//
|
|
1397
|
-
|
|
1398
|
-
if (on_reconnect) {
|
|
1399
|
-
this.on_reconnect = on_reconnect;
|
|
1456
|
+
//log_conn(evt, arg, err_arg) ::
|
|
1457
|
+
//console.info @ '[[u8-mqtt log: %s]]', evt, arg, err_arg
|
|
1400
1458
|
|
|
1401
|
-
|
|
1402
|
-
|
|
1459
|
+
on_live(client, is_reconnect) {
|
|
1460
|
+
if (is_reconnect) {
|
|
1461
|
+
return client.connect()} }
|
|
1403
1462
|
|
|
1404
|
-
|
|
1463
|
+
//on_reconnect(client) ::
|
|
1405
1464
|
|
|
1465
|
+
_use_conn(fn_reconnect) {
|
|
1466
|
+
return (this.reconnect = fn_reconnect)?.()}
|
|
1467
|
+
with_autoreconnect(opt=2000) {
|
|
1468
|
+
if (opt.toFixed) {opt ={delay: opt};}
|
|
1469
|
+
return this.with({
|
|
1470
|
+
on_reconnect() {
|
|
1471
|
+
this.delay(opt.delay || 2000)
|
|
1472
|
+
.then(this.reconnect)
|
|
1473
|
+
.then(opt.reconnect, opt.error);} }) }
|
|
1474
|
+
|
|
1475
|
+
on_disconnect(client, intentional) {
|
|
1476
|
+
if (! intentional) {
|
|
1477
|
+
return client.on_reconnect?.()} }
|
|
1478
|
+
|
|
1479
|
+
delay(ms) {
|
|
1480
|
+
return new Promise(done => setTimeout(done, ms)) }
|
|
1406
1481
|
|
|
1407
1482
|
with_async_iter(async_iter, write_u8_pkt) {
|
|
1408
1483
|
let on_mqtt_chunk = this._conn_.set(
|
|
1409
|
-
this.
|
|
1484
|
+
this.mqtt_ctx,
|
|
1410
1485
|
write_u8_pkt);
|
|
1411
1486
|
|
|
1412
1487
|
this._msg_loop = ((async () => {
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1488
|
+
try {
|
|
1489
|
+
async_iter = await async_iter;
|
|
1490
|
+
for await (let chunk of async_iter)
|
|
1491
|
+
on_mqtt_chunk(chunk);
|
|
1492
|
+
this._conn_.reset();}
|
|
1493
|
+
catch (err) {
|
|
1494
|
+
this._conn_.reset(err);} })());
|
|
1418
1495
|
|
|
1419
1496
|
return this}
|
|
1420
1497
|
|
|
@@ -1434,16 +1511,17 @@ class MQTTCoreClient extends MQTTBaseClient {
|
|
|
1434
1511
|
|
|
1435
1512
|
|
|
1436
1513
|
|
|
1514
|
+
|
|
1437
1515
|
|
|
1438
1516
|
with_tcp(port, hostname) {
|
|
1439
1517
|
if (!Number.isFinite(port)) {
|
|
1440
1518
|
({port, hostname} = new URL(port));}
|
|
1441
1519
|
|
|
1442
|
-
|
|
1443
|
-
|
|
1520
|
+
return this._use_conn (() =>
|
|
1521
|
+
this.with_stream(
|
|
1522
|
+
node_net.connect(port, hostname)) ) }
|
|
1444
1523
|
|
|
1445
1524
|
|
|
1446
|
-
|
|
1447
1525
|
with_stream(read_stream, write_stream) {
|
|
1448
1526
|
if (undefined === write_stream) {
|
|
1449
1527
|
write_stream = read_stream;}
|
|
@@ -1452,14 +1530,12 @@ class MQTTCoreClient extends MQTTBaseClient {
|
|
|
1452
1530
|
u8_pkt => write_stream.write(u8_pkt)) }
|
|
1453
1531
|
|
|
1454
1532
|
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
1533
|
with_websock(websock) {
|
|
1458
|
-
if (
|
|
1459
|
-
websock = 'ws://127.0.0.1:9001';
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1534
|
+
if (! websock?.send) {
|
|
1535
|
+
websock = new URL(websock || 'ws://127.0.0.1:9001');
|
|
1536
|
+
return this._use_conn (() =>
|
|
1537
|
+
this.with_websock(
|
|
1538
|
+
new WebSocket(websock, ['mqtt'])) ) }
|
|
1463
1539
|
|
|
1464
1540
|
websock.binaryType = 'arraybuffer';
|
|
1465
1541
|
|
|
@@ -1468,54 +1544,53 @@ class MQTTCoreClient extends MQTTBaseClient {
|
|
|
1468
1544
|
if (0 !== readyState) {
|
|
1469
1545
|
throw new Error('Invalid WebSocket readyState') }
|
|
1470
1546
|
|
|
1471
|
-
ready = new Promise(
|
|
1472
|
-
websock.addEventListener('open', y, {once: true}));}
|
|
1547
|
+
ready = new Promise(fn => websock.onopen = fn); }
|
|
1473
1548
|
|
|
1474
1549
|
|
|
1475
1550
|
let {_conn_} = this;
|
|
1476
1551
|
let on_mqtt_chunk = _conn_.set(
|
|
1477
|
-
this.
|
|
1552
|
+
this.mqtt_ctx,
|
|
1478
1553
|
async u8_pkt =>(
|
|
1479
1554
|
await ready
|
|
1480
1555
|
, websock.send(u8_pkt)) );
|
|
1481
1556
|
|
|
1482
|
-
websock.
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1557
|
+
websock.onmessage = evt =>(on_mqtt_chunk(new Uint8Array(evt.data)));
|
|
1558
|
+
websock.onclose = evt => {
|
|
1559
|
+
if (! evt.wasClean) {
|
|
1560
|
+
var err = new Error('websocket connection close');
|
|
1561
|
+
err.code = evt.code;
|
|
1562
|
+
err.reason = evt.reason;}
|
|
1488
1563
|
|
|
1489
|
-
|
|
1490
|
-
on_mqtt_chunk(
|
|
1491
|
-
new Uint8Array(evt.data));
|
|
1564
|
+
_conn_.reset(err);};
|
|
1492
1565
|
|
|
1493
1566
|
return this} }
|
|
1494
1567
|
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
}
|
|
1568
|
+
const MQTTClient_v4 = /* #__PURE__ */
|
|
1569
|
+
MQTTCore.mqtt_ctx(4, mqtt_opts_v5);
|
|
1498
1570
|
|
|
1499
|
-
const
|
|
1571
|
+
const MQTTClient_v5 = /* #__PURE__ */
|
|
1572
|
+
MQTTCore.mqtt_ctx(5, mqtt_opts_v5);
|
|
1500
1573
|
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
}
|
|
1574
|
+
const mqtt_v4 = opt =>
|
|
1575
|
+
new MQTTClient_v4(opt);
|
|
1504
1576
|
|
|
1505
|
-
const mqtt_v5 = opt =>
|
|
1577
|
+
const mqtt_v5 = opt =>
|
|
1578
|
+
new MQTTClient_v5(opt);
|
|
1506
1579
|
|
|
1507
|
-
exports.
|
|
1580
|
+
exports.MQTTBase = MQTTBase;
|
|
1508
1581
|
exports.MQTTClient_v4 = MQTTClient_v4;
|
|
1509
1582
|
exports.MQTTClient_v5 = MQTTClient_v5;
|
|
1510
|
-
exports.
|
|
1583
|
+
exports.MQTTCore = MQTTCore;
|
|
1584
|
+
exports.MQTTError = MQTTError;
|
|
1511
1585
|
exports._mqtt_cmdid_dispatch = _mqtt_cmdid_dispatch;
|
|
1512
1586
|
exports._mqtt_conn = _mqtt_conn;
|
|
1513
1587
|
exports._mqtt_dispatch = _mqtt_dispatch;
|
|
1514
1588
|
exports._mqtt_route_match_one = _mqtt_route_match_one;
|
|
1589
|
+
exports._mqtt_route_remove = _mqtt_route_remove;
|
|
1515
1590
|
exports._mqtt_routes_iter = _mqtt_routes_iter;
|
|
1516
1591
|
exports._mqtt_topic_router = _mqtt_topic_router;
|
|
1592
|
+
exports.ao_defer_v = ao_defer_v;
|
|
1517
1593
|
exports["default"] = mqtt_v4;
|
|
1518
|
-
exports.mqtt_session_ctx = mqtt_session_ctx;
|
|
1519
1594
|
exports.mqtt_v4 = mqtt_v4;
|
|
1520
1595
|
exports.mqtt_v5 = mqtt_v5;
|
|
1521
1596
|
//# sourceMappingURL=index.cjs.map
|