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