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