iobroker.bee 0.0.0-stage → 0.2.2

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.
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TunnelClient = exports.ACCESS_LABEL = void 0;
7
+ exports.findTargets = findTargets;
8
+ exports.describeTargets = describeTargets;
9
+ exports.chooseTarget = chooseTarget;
10
+ exports.trustedTunnelUrl = trustedTunnelUrl;
11
+ const node_net_1 = __importDefault(require("node:net"));
12
+ const node_tls_1 = __importDefault(require("node:tls"));
13
+ const ws_1 = __importDefault(require("ws"));
14
+ const tunnel_1 = require("./tunnel");
15
+ exports.ACCESS_LABEL = { admin: 'admin', vis: 'vis-2', console: 'Konsole' };
16
+ /**
17
+ * Local web interfaces for a kind: the enabled admin instances, or web instances for vis-2 (only with vis-2
18
+ * installed), on this host, in the order of the instance number.
19
+ */
20
+ async function findTargets(adapter, kind) {
21
+ if (kind === 'console' || (kind === 'vis' && !(await adapter.getForeignObjectAsync('system.adapter.vis-2')))) {
22
+ return [];
23
+ }
24
+ const name = kind === 'admin' ? 'admin' : 'web';
25
+ const res = await adapter.getObjectViewAsync('system', 'instance', {
26
+ startkey: `system.adapter.${name}.`,
27
+ endkey: `system.adapter.${name}.香`,
28
+ });
29
+ return res.rows
30
+ .map(r => r.value)
31
+ .filter((o) => !!o?.common.enabled && o.common.host === adapter.host)
32
+ .sort((a, b) => a._id.localeCompare(b._id, undefined, { numeric: true }))
33
+ .map(obj => {
34
+ const native = obj.native;
35
+ // an interface listening on all addresses is reached over loopback
36
+ const bind = (native.bind || '').trim();
37
+ const defaultUser = (native.defaultUser || 'admin').replace(/^system\.user\./, '');
38
+ return {
39
+ instance: obj._id.replace(/^system\.adapter\./, ''),
40
+ host: !bind || bind === '0.0.0.0' || bind === '::' ? '127.0.0.1' : bind,
41
+ port: parseInt(String(native.port || (kind === 'admin' ? 8081 : 8082)), 10),
42
+ secure: !!native.secure,
43
+ auth: !!native.auth,
44
+ ...(native.auth ? {} : { defaultUser }),
45
+ };
46
+ });
47
+ }
48
+ /** What the server learns about the targets: without the local address */
49
+ function describeTargets(targets) {
50
+ return targets.map(({ host: _host, ...t }) => t);
51
+ }
52
+ /** The instance asked for, or the first one; null if it is not among the targets */
53
+ function chooseTarget(targets, instance) {
54
+ return (instance ? targets.find(t => t.instance === instance) : targets[0]) ?? null;
55
+ }
56
+ /** Is the tunnel URL one of our own server? The job came over the broker, this is a second check. */
57
+ function trustedTunnelUrl(url, serverUrls) {
58
+ let u;
59
+ try {
60
+ u = new URL(url);
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ const local = u.hostname === 'localhost' || u.hostname === '127.0.0.1';
66
+ if (u.protocol !== 'wss:' && !(u.protocol === 'ws:' && local)) {
67
+ return false;
68
+ }
69
+ return serverUrls.some(s => {
70
+ try {
71
+ return new URL(s).hostname === u.hostname;
72
+ }
73
+ catch {
74
+ return false;
75
+ }
76
+ });
77
+ }
78
+ const MAX_BACKOFF = 60_000;
79
+ /** The server pings every 25 s; without a ping for this long the connection is dead */
80
+ const DEAD_AFTER = 90_000;
81
+ /** Longest session the agent accepts, whatever the server says */
82
+ const MAX_SESSION = 4 * 3600_000;
83
+ /** Tunnel of one access session. Reconnects after a connection loss until the session expires. */
84
+ class TunnelClient {
85
+ req;
86
+ opts;
87
+ ws = null;
88
+ mux = null;
89
+ stopped = false;
90
+ backoff = 2000;
91
+ retryTimer = null;
92
+ endTimer;
93
+ watchdog = null;
94
+ lastPing = 0;
95
+ constructor(req, opts) {
96
+ this.req = req;
97
+ this.opts = opts;
98
+ const lifetime = Math.max(0, Math.min(req.expiresAt - Date.now(), MAX_SESSION));
99
+ this.endTimer = setTimeout(() => this.stop('expired'), lifetime);
100
+ }
101
+ /** Payload bytes so far */
102
+ get bytes() {
103
+ return (this.mux?.bytesIn ?? 0) + (this.mux?.bytesOut ?? 0);
104
+ }
105
+ start() {
106
+ this.connect();
107
+ }
108
+ stop(reason) {
109
+ if (this.stopped) {
110
+ return;
111
+ }
112
+ this.stopped = true;
113
+ clearTimeout(this.endTimer);
114
+ if (this.retryTimer) {
115
+ clearTimeout(this.retryTimer);
116
+ }
117
+ if (this.watchdog) {
118
+ clearInterval(this.watchdog);
119
+ }
120
+ this.mux?.close('Fernzugriff beendet');
121
+ if (this.ws && this.ws.readyState === ws_1.default.OPEN) {
122
+ this.ws.close(1000, 'agent stop');
123
+ }
124
+ else {
125
+ this.ws?.terminate();
126
+ }
127
+ this.opts.onEnd(this, reason);
128
+ }
129
+ connect() {
130
+ if (this.stopped) {
131
+ return;
132
+ }
133
+ const headers = { authorization: `Bearer ${this.req.ticket}` };
134
+ if (this.opts.refusal) {
135
+ headers[tunnel_1.REFUSE_HEADER] = encodeURIComponent(this.opts.refusal);
136
+ }
137
+ const ws = new ws_1.default(this.req.url, {
138
+ headers,
139
+ ca: this.opts.ca,
140
+ handshakeTimeout: 30_000,
141
+ // mobile data: compress, but cheaply (level 1) for the CPU of the device
142
+ perMessageDeflate: { threshold: 1024, zlibDeflateOptions: { level: 1 } },
143
+ });
144
+ this.ws = ws;
145
+ ws.on('open', () => {
146
+ this.backoff = 2000;
147
+ this.lastPing = Date.now();
148
+ this.mux = new tunnel_1.Mux(frame => ws.send(frame), stream => this.onStream(stream));
149
+ this.watchdog ??= setInterval(() => {
150
+ if (this.ws?.readyState === ws_1.default.OPEN && Date.now() - this.lastPing > DEAD_AFTER) {
151
+ this.opts.log.info('Remote access: no sign of the server, reconnecting');
152
+ this.ws.terminate();
153
+ }
154
+ }, 15_000);
155
+ this.opts.log.debug(`Remote access ${this.req.id}: tunnel open`);
156
+ });
157
+ ws.on('ping', () => (this.lastPing = Date.now()));
158
+ ws.on('message', (data, isBinary) => {
159
+ if (isBinary) {
160
+ this.mux?.receive(data);
161
+ }
162
+ });
163
+ ws.on('unexpected-response', (_request, res) => {
164
+ res.resume();
165
+ // 410: session unknown or ended, 403: refusal accepted; neither gets better by trying again
166
+ const reason = this.opts.refusal ? 'refused' : `server answered HTTP ${res.statusCode}`;
167
+ this.stop(reason);
168
+ });
169
+ ws.on('error', err => this.opts.log.debug(`Remote access ${this.req.id}: ${err.message}`));
170
+ ws.on('close', code => {
171
+ this.mux?.close('Verbindung zum Server unterbrochen');
172
+ this.mux = null;
173
+ if (this.ws !== ws || this.stopped) {
174
+ return;
175
+ }
176
+ if (code === tunnel_1.CLOSE.ENDED || code === tunnel_1.CLOSE.REPLACED) {
177
+ this.stop(code === tunnel_1.CLOSE.ENDED ? 'ended by the server' : 'replaced');
178
+ return;
179
+ }
180
+ const delay = this.backoff;
181
+ this.backoff = Math.min(this.backoff * 2, MAX_BACKOFF);
182
+ this.opts.log.info(`Remote access: connection lost, reconnecting in ${Math.round(delay / 1000)} s`);
183
+ this.retryTimer = setTimeout(() => {
184
+ this.retryTimer = null;
185
+ this.connect();
186
+ }, delay);
187
+ });
188
+ }
189
+ onStream(stream) {
190
+ if (this.opts.handler) {
191
+ this.opts.handler(stream);
192
+ return;
193
+ }
194
+ const t = this.opts.target;
195
+ if (!t) {
196
+ stream.destroy(new Error('no target'));
197
+ return;
198
+ }
199
+ // a local HTTPS interface has its own, usually self-signed certificate: loopback, nothing to verify
200
+ const sock = t.secure
201
+ ? node_tls_1.default.connect({ host: t.host, port: t.port, rejectUnauthorized: false })
202
+ : node_net_1.default.connect(t.port, t.host);
203
+ stream.pipe(sock);
204
+ sock.pipe(stream);
205
+ // a regular end runs through the pipes in both directions (half close); only errors cut off
206
+ sock.on('error', err => stream.destroy(err));
207
+ stream.on('error', () => sock.destroy());
208
+ }
209
+ }
210
+ exports.TunnelClient = TunnelClient;
211
+ //# sourceMappingURL=remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../src/lib/remote.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Transport = void 0;
7
+ exports.trustedCas = trustedCas;
8
+ const node_events_1 = require("node:events");
9
+ const node_tls_1 = __importDefault(require("node:tls"));
10
+ const mqtt_1 = __importDefault(require("mqtt"));
11
+ const protocol_1 = require("./protocol");
12
+ const util_1 = require("./util");
13
+ const MIN_BACKOFF = 10_000;
14
+ const MAX_BACKOFF = 24 * 3600_000;
15
+ /**
16
+ * CAs the broker certificate may come from: the platform CA handed out at enrollment, plus the
17
+ * public root certificates shipped with Node.js (Mozilla list). So the broker can run with a
18
+ * certificate of the platform CA or of a public CA (e.g. Let's Encrypt), and the public roots
19
+ * are kept up to date with Node.js instead of a copy in this adapter.
20
+ */
21
+ function trustedCas(platformCa) {
22
+ return [...node_tls_1.default.rootCertificates, platformCa];
23
+ }
24
+ class Transport extends node_events_1.EventEmitter {
25
+ creds;
26
+ opts;
27
+ client = null;
28
+ backoff = MIN_BACKOFF;
29
+ timer = null;
30
+ stopped = false;
31
+ constructor(creds, opts) {
32
+ super();
33
+ this.creds = creds;
34
+ this.opts = opts;
35
+ }
36
+ get connected() {
37
+ return !!this.client?.connected;
38
+ }
39
+ start() {
40
+ this.stopped = false;
41
+ this.connect();
42
+ }
43
+ async stop() {
44
+ this.stopped = true;
45
+ if (this.timer) {
46
+ clearTimeout(this.timer);
47
+ this.timer = null;
48
+ }
49
+ const client = this.client;
50
+ this.client = null;
51
+ if (client) {
52
+ // regular disconnect: publish offline ourselves, the Last Will only fires on connection loss
53
+ if (client.connected) {
54
+ await client
55
+ .publishAsync(this.topic('state'), (0, util_1.encodePayload)(this.offline()), { qos: 1 })
56
+ .catch(() => { });
57
+ }
58
+ await client.endAsync().catch(() => { });
59
+ }
60
+ }
61
+ topic(t) {
62
+ return (0, protocol_1.deviceTopic)(this.creds.tenantId, this.creds.deviceId, t);
63
+ }
64
+ offline() {
65
+ return { v: protocol_1.PROTOCOL_VERSION, ts: Date.now(), online: false };
66
+ }
67
+ scheduleReconnect() {
68
+ if (this.stopped || this.timer) {
69
+ return;
70
+ }
71
+ const delay = Math.round(this.backoff * (0.8 + Math.random() * 0.4));
72
+ this.opts.log.info(`Broker not reachable, next attempt in ${Math.round(delay / 1000)} s`);
73
+ this.backoff = Math.min(this.backoff * 2, MAX_BACKOFF);
74
+ this.timer = setTimeout(() => {
75
+ this.timer = null;
76
+ this.connect();
77
+ }, delay);
78
+ }
79
+ connect() {
80
+ if (this.stopped) {
81
+ return;
82
+ }
83
+ const client = mqtt_1.default.connect(this.creds.mqttUrl, {
84
+ clientId: this.creds.deviceId,
85
+ key: this.creds.key,
86
+ cert: this.creds.cert,
87
+ ca: trustedCas(this.creds.ca),
88
+ rejectUnauthorized: true,
89
+ protocolVersion: 4,
90
+ clean: false,
91
+ keepalive: this.opts.keepalive,
92
+ reconnectPeriod: 0,
93
+ connectTimeout: 30_000,
94
+ will: { topic: this.topic('state'), payload: (0, util_1.encodePayload)(this.offline()), qos: 1, retain: false },
95
+ });
96
+ this.client = client;
97
+ let rejected = false;
98
+ client.on('connect', () => {
99
+ this.backoff = MIN_BACKOFF;
100
+ client.subscribe([this.topic('desired'), this.topic('job'), (0, protocol_1.controlTopic)(this.creds.tenantId)], { qos: 1 }, err => err && this.opts.log.warn(`Subscribe failed: ${err.message}`));
101
+ this.emit('connected');
102
+ });
103
+ client.on('message', (topic, payload) => {
104
+ try {
105
+ if (topic === this.topic('desired')) {
106
+ this.emit('desired', payload.length ? (0, util_1.decodePayload)(payload) : null);
107
+ }
108
+ else if (topic === (0, protocol_1.controlTopic)(this.creds.tenantId)) {
109
+ if (payload.length) {
110
+ this.emit('control', (0, util_1.decodePayload)(payload));
111
+ }
112
+ }
113
+ else if (topic === this.topic('job')) {
114
+ this.emit('job', (0, util_1.decodePayload)(payload));
115
+ }
116
+ }
117
+ catch (e) {
118
+ this.opts.log.warn(`Invalid message on ${topic}: ${e.message}`);
119
+ }
120
+ });
121
+ client.on('error', err => {
122
+ const code = err.code;
123
+ // CONNACK 4/5: the broker knows who we are and says no (certificate revoked)
124
+ if (code === 4 || code === 5 || /Not authorized|Bad username/i.test(err.message)) {
125
+ rejected = true;
126
+ this.stopped = true;
127
+ this.emit('rejected', err.message);
128
+ client.end(true);
129
+ return;
130
+ }
131
+ this.opts.log.debug(`MQTT: ${err.message}`);
132
+ });
133
+ client.on('close', () => {
134
+ if (this.client !== client) {
135
+ return;
136
+ }
137
+ this.emit('disconnected');
138
+ if (!rejected) {
139
+ this.scheduleReconnect();
140
+ }
141
+ });
142
+ }
143
+ async publish(topic, msg) {
144
+ if (!this.client?.connected) {
145
+ return false;
146
+ }
147
+ try {
148
+ await this.client.publishAsync(this.topic(topic), (0, util_1.encodePayload)(msg), { qos: 1 });
149
+ return true;
150
+ }
151
+ catch (e) {
152
+ this.opts.log.debug(`Publish ${topic} failed: ${e.message}`);
153
+ return false;
154
+ }
155
+ }
156
+ }
157
+ exports.Transport = Transport;
158
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/lib/transport.ts"],"names":[],"mappings":"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"}