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