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