@dxos/teleport 0.1.52 → 0.1.53-main.01cbc6b
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/dist/lib/browser/{chunk-NJQ5JWQJ.mjs → chunk-YGY6ZROZ.mjs} +113 -83
- package/dist/lib/browser/chunk-YGY6ZROZ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +4 -4
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +24 -23
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/index.cjs +110 -80
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +130 -99
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/types/src/muxing/framer.d.ts.map +1 -1
- package/dist/types/src/muxing/muxer.d.ts +4 -0
- package/dist/types/src/muxing/muxer.d.ts.map +1 -1
- package/dist/types/src/teleport.d.ts +3 -0
- package/dist/types/src/teleport.d.ts.map +1 -1
- package/package.json +12 -12
- package/src/muxing/framer.ts +3 -3
- package/src/muxing/muxer.test.ts +5 -1
- package/src/muxing/muxer.ts +43 -5
- package/src/rpc-extension.ts +2 -2
- package/src/teleport.ts +16 -11
- package/src/testing/test-builder.ts +11 -11
- package/src/testing/test-extension.ts +2 -2
- package/dist/lib/browser/chunk-NJQ5JWQJ.mjs.map +0 -7
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import "@dxos/node-std/globals"
|
|
1
|
+
import "@dxos/node-std/globals";
|
|
2
2
|
|
|
3
3
|
// packages/core/mesh/teleport/src/muxing/framer.ts
|
|
4
|
-
import assert from "@dxos/node-std/assert";
|
|
5
4
|
import { Duplex } from "@dxos/node-std/stream";
|
|
5
|
+
import invariant from "tiny-invariant";
|
|
6
6
|
import * as varint from "varint";
|
|
7
7
|
var Framer = class {
|
|
8
8
|
constructor() {
|
|
@@ -11,7 +11,7 @@ var Framer = class {
|
|
|
11
11
|
read: () => {
|
|
12
12
|
},
|
|
13
13
|
write: (chunk, encoding, callback) => {
|
|
14
|
-
|
|
14
|
+
invariant(!this._subscribeCb, "Internal Framer bug. Concurrent writes detected.");
|
|
15
15
|
if (this._buffer && this._buffer.length > 0) {
|
|
16
16
|
this._buffer = Buffer.concat([
|
|
17
17
|
this._buffer,
|
|
@@ -38,7 +38,7 @@ var Framer = class {
|
|
|
38
38
|
},
|
|
39
39
|
subscribe: (callback) => {
|
|
40
40
|
var _a;
|
|
41
|
-
|
|
41
|
+
invariant(!this._messageCb, "Rpc port already has a message listener.");
|
|
42
42
|
this._messageCb = callback;
|
|
43
43
|
(_a = this._subscribeCb) == null ? void 0 : _a.call(this);
|
|
44
44
|
return () => {
|
|
@@ -102,13 +102,16 @@ var encodeFrame = (payload) => {
|
|
|
102
102
|
};
|
|
103
103
|
|
|
104
104
|
// packages/core/mesh/teleport/src/muxing/muxer.ts
|
|
105
|
-
import assert2 from "@dxos/node-std/assert";
|
|
106
105
|
import { Duplex as Duplex2 } from "@dxos/node-std/stream";
|
|
107
|
-
import
|
|
106
|
+
import invariant2 from "tiny-invariant";
|
|
107
|
+
import { Event, scheduleTaskInterval } from "@dxos/async";
|
|
108
|
+
import { Context } from "@dxos/context";
|
|
108
109
|
import { failUndefined } from "@dxos/debug";
|
|
109
110
|
import { log } from "@dxos/log";
|
|
110
111
|
import { schema } from "@dxos/protocols";
|
|
112
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/muxer.ts";
|
|
111
113
|
var codec = schema.getCodecForType("dxos.mesh.muxer.Command");
|
|
114
|
+
var STATS_INTERVAL = 1e3;
|
|
112
115
|
var Muxer = class {
|
|
113
116
|
constructor() {
|
|
114
117
|
this._framer = new Framer();
|
|
@@ -119,9 +122,12 @@ var Muxer = class {
|
|
|
119
122
|
this._destroyed = false;
|
|
120
123
|
this._destroying = false;
|
|
121
124
|
this.close = new Event();
|
|
125
|
+
this.statsUpdated = new Event();
|
|
126
|
+
this._ctx = new Context();
|
|
122
127
|
this._framer.port.subscribe((msg) => {
|
|
123
128
|
this._handleCommand(codec.decode(msg));
|
|
124
129
|
});
|
|
130
|
+
scheduleTaskInterval(this._ctx, async () => this._emitStats(), STATS_INTERVAL);
|
|
125
131
|
}
|
|
126
132
|
/**
|
|
127
133
|
* Creates a duplex Node.js-style stream.
|
|
@@ -134,7 +140,7 @@ var Muxer = class {
|
|
|
134
140
|
tag,
|
|
135
141
|
contentType: opts.contentType
|
|
136
142
|
});
|
|
137
|
-
|
|
143
|
+
invariant2(!channel.push, `Channel already open: ${tag}`);
|
|
138
144
|
const stream = new Duplex2({
|
|
139
145
|
write: (data, encoding, callback) => {
|
|
140
146
|
this._sendData(channel, data);
|
|
@@ -144,6 +150,7 @@ var Muxer = class {
|
|
|
144
150
|
}
|
|
145
151
|
});
|
|
146
152
|
channel.push = (data) => {
|
|
153
|
+
channel.stats.bytesReceived += data.length;
|
|
147
154
|
stream.push(data);
|
|
148
155
|
};
|
|
149
156
|
channel.destroy = (err) => {
|
|
@@ -169,10 +176,11 @@ var Muxer = class {
|
|
|
169
176
|
tag,
|
|
170
177
|
contentType: opts.contentType
|
|
171
178
|
});
|
|
172
|
-
|
|
179
|
+
invariant2(!channel.push, `Channel already open: ${tag}`);
|
|
173
180
|
let inboundBuffer = [];
|
|
174
181
|
let callback;
|
|
175
182
|
channel.push = (data) => {
|
|
183
|
+
channel.stats.bytesReceived += data.length;
|
|
176
184
|
if (callback) {
|
|
177
185
|
callback(data);
|
|
178
186
|
} else {
|
|
@@ -184,7 +192,7 @@ var Muxer = class {
|
|
|
184
192
|
this._sendData(channel, data);
|
|
185
193
|
},
|
|
186
194
|
subscribe: (cb) => {
|
|
187
|
-
|
|
195
|
+
invariant2(!callback, "Only one subscriber is allowed");
|
|
188
196
|
callback = cb;
|
|
189
197
|
for (const data of inboundBuffer) {
|
|
190
198
|
cb(data);
|
|
@@ -215,6 +223,7 @@ var Muxer = class {
|
|
|
215
223
|
}
|
|
216
224
|
});
|
|
217
225
|
this._dispose();
|
|
226
|
+
void this._ctx.dispose();
|
|
218
227
|
}
|
|
219
228
|
_dispose(err) {
|
|
220
229
|
var _a;
|
|
@@ -235,17 +244,17 @@ var Muxer = class {
|
|
|
235
244
|
log("Received command", {
|
|
236
245
|
cmd
|
|
237
246
|
}, {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
247
|
+
F: __dxlog_file,
|
|
248
|
+
L: 207,
|
|
249
|
+
S: this,
|
|
250
|
+
C: (f, a) => f(...a)
|
|
242
251
|
});
|
|
243
252
|
if (this._destroyed || this._destroying) {
|
|
244
|
-
log.warn("Received command after destroy",
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
253
|
+
log.warn("Received command after destroy", void 0, {
|
|
254
|
+
F: __dxlog_file,
|
|
255
|
+
L: 210,
|
|
256
|
+
S: this,
|
|
257
|
+
C: (f, a) => f(...a)
|
|
249
258
|
});
|
|
250
259
|
return;
|
|
251
260
|
}
|
|
@@ -270,10 +279,10 @@ var Muxer = class {
|
|
|
270
279
|
log.warn("Received data for channel before it was opened", {
|
|
271
280
|
tag: stream.tag
|
|
272
281
|
}, {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
282
|
+
F: __dxlog_file,
|
|
283
|
+
L: 234,
|
|
284
|
+
S: this,
|
|
285
|
+
C: (f, a) => f(...a)
|
|
277
286
|
});
|
|
278
287
|
return;
|
|
279
288
|
}
|
|
@@ -297,7 +306,11 @@ var Muxer = class {
|
|
|
297
306
|
contentType: params.contentType,
|
|
298
307
|
buffer: [],
|
|
299
308
|
push: null,
|
|
300
|
-
destroy: null
|
|
309
|
+
destroy: null,
|
|
310
|
+
stats: {
|
|
311
|
+
bytesSent: 0,
|
|
312
|
+
bytesReceived: 0
|
|
313
|
+
}
|
|
301
314
|
};
|
|
302
315
|
this._channelsByTag.set(channel.tag, channel);
|
|
303
316
|
this._channelsByLocalId.set(channel.id, channel);
|
|
@@ -305,6 +318,7 @@ var Muxer = class {
|
|
|
305
318
|
return channel;
|
|
306
319
|
}
|
|
307
320
|
_sendData(channel, data) {
|
|
321
|
+
channel.stats.bytesSent += data.length;
|
|
308
322
|
if (channel.remoteId === null) {
|
|
309
323
|
channel.buffer.push(data);
|
|
310
324
|
} else {
|
|
@@ -316,19 +330,30 @@ var Muxer = class {
|
|
|
316
330
|
});
|
|
317
331
|
}
|
|
318
332
|
}
|
|
333
|
+
async _emitStats() {
|
|
334
|
+
if (this._destroyed || this._destroying) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
this.statsUpdated.emit(Array.from(this._channelsByTag.values()).map((channel) => ({
|
|
338
|
+
id: channel.id,
|
|
339
|
+
tag: channel.tag,
|
|
340
|
+
bytesSent: channel.stats.bytesSent,
|
|
341
|
+
bytesReceived: channel.stats.bytesReceived
|
|
342
|
+
})));
|
|
343
|
+
}
|
|
319
344
|
};
|
|
320
345
|
|
|
321
346
|
// packages/core/mesh/teleport/src/teleport.ts
|
|
322
|
-
import
|
|
323
|
-
import { asyncTimeout, scheduleTaskInterval, runInContextAsync, synchronized, scheduleTask } from "@dxos/async";
|
|
324
|
-
import { Context } from "@dxos/context";
|
|
347
|
+
import invariant3 from "tiny-invariant";
|
|
348
|
+
import { asyncTimeout, scheduleTaskInterval as scheduleTaskInterval2, runInContextAsync, synchronized, scheduleTask } from "@dxos/async";
|
|
349
|
+
import { Context as Context2 } from "@dxos/context";
|
|
325
350
|
import { failUndefined as failUndefined2 } from "@dxos/debug";
|
|
326
351
|
import { PublicKey } from "@dxos/keys";
|
|
327
352
|
import { log as log2 } from "@dxos/log";
|
|
328
353
|
import { schema as schema2, RpcClosedError } from "@dxos/protocols";
|
|
329
354
|
import { createProtoRpcPeer } from "@dxos/rpc";
|
|
330
355
|
import { Callback } from "@dxos/util";
|
|
331
|
-
|
|
356
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
332
357
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
333
358
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
334
359
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -337,17 +362,18 @@ var __decorate = function(decorators, target, key, desc) {
|
|
|
337
362
|
if (d = decorators[i])
|
|
338
363
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
339
364
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
340
|
-
}
|
|
365
|
+
}
|
|
366
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts";
|
|
341
367
|
var Teleport = class {
|
|
342
368
|
constructor({ initiator, localPeerId, remotePeerId }) {
|
|
343
|
-
this._ctx = new
|
|
369
|
+
this._ctx = new Context2({
|
|
344
370
|
onError: (err) => {
|
|
345
371
|
void this.destroy(err).catch(() => {
|
|
346
372
|
log2.error("Error during destroy", err, {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
373
|
+
F: __dxlog_file2,
|
|
374
|
+
L: 35,
|
|
375
|
+
S: this,
|
|
376
|
+
C: (f, a) => f(...a)
|
|
351
377
|
});
|
|
352
378
|
});
|
|
353
379
|
}
|
|
@@ -357,21 +383,21 @@ var Teleport = class {
|
|
|
357
383
|
heartbeatInterval: 1e4,
|
|
358
384
|
heartbeatTimeout: 1e4,
|
|
359
385
|
onTimeout: () => {
|
|
360
|
-
this.destroy(new Error("Connection timed out")).catch((err) => log2.catch(err,
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
386
|
+
this.destroy(new Error("Connection timed out")).catch((err) => log2.catch(err, void 0, {
|
|
387
|
+
F: __dxlog_file2,
|
|
388
|
+
L: 46,
|
|
389
|
+
S: this,
|
|
390
|
+
C: (f, a) => f(...a)
|
|
365
391
|
}));
|
|
366
392
|
}
|
|
367
393
|
});
|
|
368
394
|
this._extensions = /* @__PURE__ */ new Map();
|
|
369
395
|
this._remoteExtensions = /* @__PURE__ */ new Set();
|
|
370
396
|
this._open = false;
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
397
|
+
invariant3(typeof initiator === "boolean");
|
|
398
|
+
invariant3(PublicKey.isPublicKey(localPeerId));
|
|
399
|
+
invariant3(PublicKey.isPublicKey(remotePeerId));
|
|
400
|
+
invariant3(typeof initiator === "boolean");
|
|
375
401
|
this.initiator = initiator;
|
|
376
402
|
this.localPeerId = localPeerId;
|
|
377
403
|
this.remotePeerId = remotePeerId;
|
|
@@ -379,12 +405,12 @@ var Teleport = class {
|
|
|
379
405
|
log2("remote extension", {
|
|
380
406
|
name
|
|
381
407
|
}, {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
408
|
+
F: __dxlog_file2,
|
|
409
|
+
L: 65,
|
|
410
|
+
S: this,
|
|
411
|
+
C: (f, a) => f(...a)
|
|
386
412
|
});
|
|
387
|
-
|
|
413
|
+
invariant3(!this._remoteExtensions.has(name), "Remote extension already exists");
|
|
388
414
|
this._remoteExtensions.add(name);
|
|
389
415
|
if (this._extensions.has(name)) {
|
|
390
416
|
try {
|
|
@@ -406,6 +432,9 @@ var Teleport = class {
|
|
|
406
432
|
get stream() {
|
|
407
433
|
return this._muxer.stream;
|
|
408
434
|
}
|
|
435
|
+
get stats() {
|
|
436
|
+
return this._muxer.statsUpdated;
|
|
437
|
+
}
|
|
409
438
|
/**
|
|
410
439
|
* Blocks until the handshake is complete.
|
|
411
440
|
*/
|
|
@@ -425,12 +454,12 @@ var Teleport = class {
|
|
|
425
454
|
for (const extension of this._extensions.values()) {
|
|
426
455
|
try {
|
|
427
456
|
await extension.onClose(err);
|
|
428
|
-
} catch (
|
|
429
|
-
log2.catch(
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
457
|
+
} catch (err2) {
|
|
458
|
+
log2.catch(err2, void 0, {
|
|
459
|
+
F: __dxlog_file2,
|
|
460
|
+
L: 125,
|
|
461
|
+
S: this,
|
|
462
|
+
C: (f, a) => f(...a)
|
|
434
463
|
});
|
|
435
464
|
}
|
|
436
465
|
}
|
|
@@ -443,10 +472,10 @@ var Teleport = class {
|
|
|
443
472
|
log2("addExtension", {
|
|
444
473
|
name
|
|
445
474
|
}, {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
475
|
+
F: __dxlog_file2,
|
|
476
|
+
L: 137,
|
|
477
|
+
S: this,
|
|
478
|
+
C: (f, a) => f(...a)
|
|
450
479
|
});
|
|
451
480
|
this._setExtension(name, extension);
|
|
452
481
|
scheduleTask(this._ctx, async () => {
|
|
@@ -466,8 +495,8 @@ var Teleport = class {
|
|
|
466
495
|
}
|
|
467
496
|
}
|
|
468
497
|
_setExtension(extensionName, extension) {
|
|
469
|
-
|
|
470
|
-
|
|
498
|
+
invariant3(!extensionName.includes("/"), "Invalid extension name");
|
|
499
|
+
invariant3(!this._extensions.has(extensionName), "Extension already exists");
|
|
471
500
|
this._extensions.set(extensionName, extension);
|
|
472
501
|
}
|
|
473
502
|
async _openExtension(extensionName) {
|
|
@@ -475,10 +504,10 @@ var Teleport = class {
|
|
|
475
504
|
log2("open extension", {
|
|
476
505
|
extensionName
|
|
477
506
|
}, {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
507
|
+
F: __dxlog_file2,
|
|
508
|
+
L: 167,
|
|
509
|
+
S: this,
|
|
510
|
+
C: (f, a) => f(...a)
|
|
482
511
|
});
|
|
483
512
|
const extension = (_a = this._extensions.get(extensionName)) != null ? _a : failUndefined2();
|
|
484
513
|
const context = {
|
|
@@ -486,11 +515,11 @@ var Teleport = class {
|
|
|
486
515
|
localPeerId: this.localPeerId,
|
|
487
516
|
remotePeerId: this.remotePeerId,
|
|
488
517
|
createPort: (channelName, opts) => {
|
|
489
|
-
|
|
518
|
+
invariant3(!channelName.includes("/"), "Invalid channel name");
|
|
490
519
|
return this._muxer.createPort(`${extensionName}/${channelName}`, opts);
|
|
491
520
|
},
|
|
492
521
|
createStream: (channelName, opts) => {
|
|
493
|
-
|
|
522
|
+
invariant3(!channelName.includes("/"), "Invalid channel name");
|
|
494
523
|
return this._muxer.createStream(`${extensionName}/${channelName}`, opts);
|
|
495
524
|
},
|
|
496
525
|
close: (err) => {
|
|
@@ -503,20 +532,20 @@ var Teleport = class {
|
|
|
503
532
|
log2("extension opened", {
|
|
504
533
|
extensionName
|
|
505
534
|
}, {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
535
|
+
F: __dxlog_file2,
|
|
536
|
+
L: 190,
|
|
537
|
+
S: this,
|
|
538
|
+
C: (f, a) => f(...a)
|
|
510
539
|
});
|
|
511
540
|
}
|
|
512
541
|
};
|
|
513
|
-
|
|
542
|
+
_ts_decorate([
|
|
514
543
|
synchronized
|
|
515
544
|
], Teleport.prototype, "destroy", null);
|
|
516
545
|
var ControlExtension = class {
|
|
517
546
|
constructor(opts) {
|
|
518
547
|
this.opts = opts;
|
|
519
|
-
this._ctx = new
|
|
548
|
+
this._ctx = new Context2({
|
|
520
549
|
onError: (err) => {
|
|
521
550
|
this._extensionContext.close(err);
|
|
522
551
|
}
|
|
@@ -546,7 +575,7 @@ var ControlExtension = class {
|
|
|
546
575
|
})
|
|
547
576
|
});
|
|
548
577
|
await this._rpc.open();
|
|
549
|
-
|
|
578
|
+
scheduleTaskInterval2(this._ctx, async () => {
|
|
550
579
|
try {
|
|
551
580
|
await asyncTimeout(this._rpc.rpc.Control.heartbeat(), this.opts.heartbeatTimeout);
|
|
552
581
|
} catch (err) {
|
|
@@ -566,11 +595,12 @@ var ControlExtension = class {
|
|
|
566
595
|
};
|
|
567
596
|
|
|
568
597
|
// packages/core/mesh/teleport/src/testing/test-extension.ts
|
|
569
|
-
import
|
|
598
|
+
import invariant4 from "tiny-invariant";
|
|
570
599
|
import { asyncTimeout as asyncTimeout2, Trigger } from "@dxos/async";
|
|
571
600
|
import { log as log3 } from "@dxos/log";
|
|
572
601
|
import { schema as schema3 } from "@dxos/protocols";
|
|
573
602
|
import { createProtoRpcPeer as createProtoRpcPeer2 } from "@dxos/rpc";
|
|
603
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/testing/test-extension.ts";
|
|
574
604
|
var TestExtension = class {
|
|
575
605
|
constructor(callbacks = {}) {
|
|
576
606
|
this.callbacks = callbacks;
|
|
@@ -587,10 +617,10 @@ var TestExtension = class {
|
|
|
587
617
|
localPeerId: context.localPeerId,
|
|
588
618
|
remotePeerId: context.remotePeerId
|
|
589
619
|
}, {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
620
|
+
F: __dxlog_file3,
|
|
621
|
+
L: 33,
|
|
622
|
+
S: this,
|
|
623
|
+
C: (f, a) => f(...a)
|
|
594
624
|
});
|
|
595
625
|
this.extensionContext = context;
|
|
596
626
|
this._rpc = createProtoRpcPeer2({
|
|
@@ -625,10 +655,10 @@ var TestExtension = class {
|
|
|
625
655
|
log3("onClose", {
|
|
626
656
|
err
|
|
627
657
|
}, {
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
658
|
+
F: __dxlog_file3,
|
|
659
|
+
L: 67,
|
|
660
|
+
S: this,
|
|
661
|
+
C: (f, a) => f(...a)
|
|
632
662
|
});
|
|
633
663
|
await ((_b = (_a = this.callbacks).onClose) == null ? void 0 : _b.call(_a));
|
|
634
664
|
this.closed.wake();
|
|
@@ -641,7 +671,7 @@ var TestExtension = class {
|
|
|
641
671
|
const res = await asyncTimeout2(this._rpc.rpc.TestService.testCall({
|
|
642
672
|
data: message
|
|
643
673
|
}), 500);
|
|
644
|
-
|
|
674
|
+
invariant4(res.data === message);
|
|
645
675
|
}
|
|
646
676
|
/**
|
|
647
677
|
* Force-close the connection.
|
|
@@ -660,4 +690,4 @@ export {
|
|
|
660
690
|
Teleport,
|
|
661
691
|
TestExtension
|
|
662
692
|
};
|
|
663
|
-
//# sourceMappingURL=chunk-
|
|
693
|
+
//# sourceMappingURL=chunk-YGY6ZROZ.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/muxing/framer.ts", "../../../src/muxing/muxer.ts", "../../../src/teleport.ts", "../../../src/testing/test-extension.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport { Duplex } from 'node:stream';\nimport invariant from 'tiny-invariant';\nimport * as varint from 'varint';\n\nimport { RpcPort } from './rpc-port';\n\n/**\n * Framer that turns a stream of binary messages into a framed RpcPort.\n *\n * Buffers are written prefixed by their length encoded as a varint.\n */\nexport class Framer {\n // private readonly _tagBuffer = Buffer.alloc(4)\n private _messageCb?: (msg: Uint8Array) => void;\n private _subscribeCb?: () => void;\n private _buffer?: Buffer; // The rest of the bytes from the previous write call.\n\n private readonly _stream = new Duplex({\n objectMode: false,\n read: () => {},\n write: (chunk, encoding, callback) => {\n invariant(!this._subscribeCb, 'Internal Framer bug. Concurrent writes detected.');\n\n if (this._buffer && this._buffer.length > 0) {\n this._buffer = Buffer.concat([this._buffer, chunk]);\n } else {\n this._buffer = chunk;\n }\n\n if (this._messageCb) {\n this._popFrames();\n callback();\n } else {\n this._subscribeCb = () => {\n // Schedule the processing of the chunk after the peer subscribes to the messages.\n this._popFrames();\n this._subscribeCb = undefined;\n callback();\n };\n }\n },\n });\n\n public readonly port: RpcPort = {\n send: (message) => {\n // log('write', { len: message.length, frame: Buffer.from(message).toString('hex') })\n this._stream.push(encodeFrame(message));\n },\n subscribe: (callback) => {\n invariant(!this._messageCb, 'Rpc port already has a message listener.');\n this._messageCb = callback;\n this._subscribeCb?.();\n return () => {\n this._messageCb = undefined;\n };\n },\n };\n\n get stream(): Duplex {\n return this._stream;\n }\n\n /**\n * Attempts to pop frames from the buffer and call the message callback.\n */\n private _popFrames() {\n let offset = 0;\n while (offset < this._buffer!.length) {\n const frame = decodeFrame(this._buffer!, offset);\n\n if (!frame) {\n break; // Couldn't read frame but there are still bytes left in the buffer.\n }\n offset += frame.bytesConsumed;\n // TODO(dmaretskyi): Possible bug if the peer unsubscribes while we're reading frames.\n // log('read', { len: frame.payload.length, frame: Buffer.from(frame.payload).toString('hex') })\n this._messageCb!(frame.payload);\n }\n\n if (offset < this._buffer!.length) {\n // Save the rest of the bytes for the next write call.\n this._buffer = this._buffer!.subarray(offset);\n } else {\n this._buffer = undefined;\n }\n }\n\n destroy() {\n // TODO(dmaretskyi): Call stream.end() instead?\n this._stream.destroy();\n }\n}\n\n/**\n * Attempts to read a frame from the input buffer.\n */\nexport const decodeFrame = (buffer: Buffer, offset: number): { payload: Buffer; bytesConsumed: number } | undefined => {\n try {\n const frameLength = varint.decode(buffer, offset);\n const tagLength = varint.decode.bytes;\n\n if (buffer.length < offset + tagLength + frameLength) {\n // Not enough bytes to read the frame.\n return undefined;\n }\n\n const payload = buffer.subarray(offset + tagLength, offset + tagLength + frameLength);\n\n return {\n payload,\n bytesConsumed: tagLength + frameLength,\n };\n } catch (err) {\n if (err instanceof RangeError) {\n // Not enough bytes to read the tag.\n return undefined;\n } else {\n throw err;\n }\n }\n};\n\nexport const encodeFrame = (payload: Uint8Array): Buffer => {\n const tagLength = varint.encodingLength(payload.length);\n const frame = Buffer.allocUnsafe(tagLength + payload.length);\n varint.encode(payload.length, frame);\n frame.set(payload, tagLength);\n return frame;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { Duplex } from 'node:stream';\nimport invariant from 'tiny-invariant';\n\nimport { Event, scheduleTaskInterval } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\nimport { ConnectionInfo } from '@dxos/protocols/proto/dxos/devtools/swarm';\nimport { Command } from '@dxos/protocols/proto/dxos/mesh/muxer';\n\nimport { Framer } from './framer';\nimport { RpcPort } from './rpc-port';\n\nconst codec = schema.getCodecForType('dxos.mesh.muxer.Command');\n\nexport type CleanupCb = void | (() => void);\n\nexport type CreateChannelOpts = {\n /**\n * MIME type of the wire content.\n *\n * Examples:\n * - application/octet-stream\n * - application/x-protobuf; messageType=\"dxos.rpc.Message\"\n */\n contentType?: string;\n};\n\nconst STATS_INTERVAL = 1000;\n\n/**\n * Channel based multiplexer.\n *\n * Can be used to open a number of channels represented by streams or RPC ports.\n * Performs framing for RPC ports.\n * Will buffer data until the remote peer opens the channel.\n *\n * The API will not advertise channels that as they are opened by the remote peer.\n * A higher level API (could be build on top of this muxer) for channel discovery is required.\n */\nexport class Muxer {\n private readonly _framer = new Framer();\n public readonly stream = this._framer.stream;\n\n private readonly _channelsByLocalId = new Map<number, Channel>();\n private readonly _channelsByTag = new Map<string, Channel>();\n\n private _nextId = 0;\n private _destroyed = false;\n private _destroying = false;\n\n public close = new Event<Error | undefined>();\n\n public statsUpdated = new Event<ConnectionInfo.StreamStats[]>();\n\n private readonly _ctx = new Context();\n\n constructor() {\n this._framer.port.subscribe((msg) => {\n this._handleCommand(codec.decode(msg));\n });\n\n scheduleTaskInterval(this._ctx, async () => this._emitStats(), STATS_INTERVAL);\n }\n\n /**\n * Creates a duplex Node.js-style stream.\n * The remote peer is expected to call `createStream` with the same tag.\n * The stream is immediately readable and writable.\n * NOTE: The data will be buffered until the stream is opened remotely with the same tag (may cause a memory leak).\n */\n createStream(tag: string, opts: CreateChannelOpts = {}): Duplex {\n const channel = this._getOrCreateStream({\n tag,\n contentType: opts.contentType,\n });\n invariant(!channel.push, `Channel already open: ${tag}`);\n\n const stream = new Duplex({\n write: (data, encoding, callback) => {\n this._sendData(channel, data);\n // TODO(dmaretskyi): Should we error if sending data has errored?\n callback();\n },\n read: () => {}, // No-op. We will push data when we receive it.\n });\n\n channel.push = (data) => {\n channel.stats.bytesReceived += data.length;\n stream.push(data);\n };\n channel.destroy = (err) => {\n // TODO(dmaretskyi): Call stream.end() instead?\n stream.destroy(err);\n };\n\n // NOTE: Make sure channel.push is set before sending the command.\n this._sendCommand({\n openChannel: {\n id: channel.id,\n tag: channel.tag,\n contentType: channel.contentType,\n },\n });\n\n return stream;\n }\n\n /**\n * Creates an RPC port.\n * The remote peer is expected to call `createPort` with the same tag.\n * The port is immediately usable.\n * NOTE: The data will be buffered until the stream is opened remotely with the same tag (may cause a memory leak).\n */\n createPort(tag: string, opts: CreateChannelOpts = {}): RpcPort {\n const channel = this._getOrCreateStream({\n tag,\n contentType: opts.contentType,\n });\n invariant(!channel.push, `Channel already open: ${tag}`);\n\n // We need to buffer incoming data until the port is subscribed to.\n let inboundBuffer: Uint8Array[] = [];\n let callback: ((data: Uint8Array) => void) | undefined;\n\n channel.push = (data) => {\n channel.stats.bytesReceived += data.length;\n if (callback) {\n callback(data);\n } else {\n inboundBuffer.push(data);\n }\n };\n\n const port: RpcPort = {\n send: (data: Uint8Array) => {\n this._sendData(channel, data); // TODO(dmaretskyi): Error propagation?\n\n // TODO(dmaretskyi): Debugging.\n // appendFileSync('log.json', JSON.stringify(schema.getCodecForType('dxos.rpc.RpcMessage').decode(data), null, 2) + '\\n')\n },\n subscribe: (cb: (data: Uint8Array) => void) => {\n invariant(!callback, 'Only one subscriber is allowed');\n callback = cb;\n for (const data of inboundBuffer) {\n cb(data);\n }\n inboundBuffer = [];\n },\n };\n\n // NOTE: Make sure channel.push is set before sending the command.\n this._sendCommand({\n openChannel: {\n id: channel.id,\n tag: channel.tag,\n contentType: channel.contentType,\n },\n });\n\n return port;\n }\n\n /**\n * Force-close with optional error.\n */\n destroy(err?: Error) {\n if (this._destroying) {\n return;\n }\n this._destroying = true;\n\n this._sendCommand({\n destroy: {\n error: err?.message,\n },\n });\n this._dispose();\n void this._ctx.dispose();\n }\n\n private _dispose(err?: Error) {\n if (this._destroyed) {\n return;\n }\n\n this._destroyed = true;\n this._framer.destroy();\n\n for (const channel of this._channelsByTag.values()) {\n channel.destroy?.(err);\n }\n\n this.close.emit(err);\n\n // Make it easy for GC.\n this._channelsByLocalId.clear();\n this._channelsByTag.clear();\n }\n\n private _handleCommand(cmd: Command) {\n log('Received command', { cmd });\n\n if (this._destroyed || this._destroying) {\n log.warn('Received command after destroy');\n return;\n }\n\n if (cmd.openChannel) {\n const channel = this._getOrCreateStream({\n tag: cmd.openChannel.tag,\n contentType: cmd.openChannel.contentType,\n });\n channel.remoteId = cmd.openChannel.id;\n\n // Flush any buffered data.\n for (const data of channel.buffer) {\n this._sendCommand({\n data: {\n channelId: channel.remoteId,\n data,\n },\n });\n }\n channel.buffer = [];\n } else if (cmd.data) {\n const stream = this._channelsByLocalId.get(cmd.data.channelId) ?? failUndefined();\n if (!stream.push) {\n log.warn('Received data for channel before it was opened', { tag: stream.tag });\n return;\n }\n stream.push(cmd.data.data);\n } else if (cmd.destroy) {\n this._dispose();\n }\n }\n\n private _sendCommand(cmd: Command) {\n Promise.resolve(this._framer.port.send(codec.encode(cmd))).catch((err) => {\n this.destroy(err);\n });\n }\n\n private _getOrCreateStream(params: CreateChannelInternalParams): Channel {\n let channel = this._channelsByTag.get(params.tag);\n if (!channel) {\n channel = {\n id: this._nextId++,\n remoteId: null,\n tag: params.tag,\n contentType: params.contentType,\n buffer: [],\n push: null,\n destroy: null,\n stats: {\n bytesSent: 0,\n bytesReceived: 0,\n },\n };\n this._channelsByTag.set(channel.tag, channel);\n this._channelsByLocalId.set(channel.id, channel);\n }\n return channel;\n }\n\n private _sendData(channel: Channel, data: Uint8Array) {\n channel.stats.bytesSent += data.length;\n if (channel.remoteId === null) {\n // Remote side has not opened the channel yet.\n channel.buffer.push(data);\n } else {\n this._sendCommand({\n data: {\n channelId: channel.remoteId,\n data,\n },\n });\n }\n }\n\n private async _emitStats() {\n if (this._destroyed || this._destroying) {\n return;\n }\n\n this.statsUpdated.emit(\n Array.from(this._channelsByTag.values()).map((channel) => ({\n id: channel.id,\n tag: channel.tag,\n bytesSent: channel.stats.bytesSent,\n bytesReceived: channel.stats.bytesReceived,\n })),\n );\n }\n}\n\ntype Channel = {\n /**\n * Our local channel ID.\n * Incoming Data commands will have this ID.\n */\n id: number;\n tag: string;\n\n /**\n * Remote id is set when we receive an OpenChannel command.\n * The originating Data commands should carry this id.\n */\n remoteId: null | number;\n\n contentType?: string;\n\n /**\n * Send buffer.\n */\n buffer: Uint8Array[];\n\n /**\n * Set when we initialize a NodeJS stream or an RPC port consuming the channel.\n */\n push: null | ((data: Uint8Array) => void);\n\n destroy: null | ((err?: Error) => void);\n\n stats: {\n bytesSent: number;\n bytesReceived: number;\n };\n};\n\ntype CreateChannelInternalParams = {\n tag: string;\n contentType?: string;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { Duplex } from 'node:stream';\nimport invariant from 'tiny-invariant';\n\nimport { asyncTimeout, scheduleTaskInterval, runInContextAsync, synchronized, scheduleTask, Event } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { schema, RpcClosedError } from '@dxos/protocols';\nimport { ConnectionInfo } from '@dxos/protocols/proto/dxos/devtools/swarm';\nimport { ControlService } from '@dxos/protocols/proto/dxos/mesh/teleport/control';\nimport { createProtoRpcPeer, ProtoRpcPeer } from '@dxos/rpc';\nimport { Callback } from '@dxos/util';\n\nimport { CreateChannelOpts, Muxer, RpcPort } from './muxing';\n\nexport type TeleportParams = {\n initiator: boolean;\n localPeerId: PublicKey;\n remotePeerId: PublicKey;\n};\n\nexport class Teleport {\n public readonly initiator: boolean;\n public readonly localPeerId: PublicKey;\n public readonly remotePeerId: PublicKey;\n\n private readonly _ctx = new Context({\n onError: (err) => {\n void this.destroy(err).catch(() => {\n log.error('Error during destroy', err);\n });\n },\n });\n\n private readonly _muxer = new Muxer();\n\n private readonly _control = new ControlExtension({\n heartbeatInterval: 10_000,\n heartbeatTimeout: 10_000,\n onTimeout: () => {\n this.destroy(new Error('Connection timed out')).catch((err) => log.catch(err));\n },\n });\n\n private readonly _extensions = new Map<string, TeleportExtension>();\n private readonly _remoteExtensions = new Set<string>();\n\n private _open = false;\n\n constructor({ initiator, localPeerId, remotePeerId }: TeleportParams) {\n invariant(typeof initiator === 'boolean');\n invariant(PublicKey.isPublicKey(localPeerId));\n invariant(PublicKey.isPublicKey(remotePeerId));\n invariant(typeof initiator === 'boolean');\n this.initiator = initiator;\n this.localPeerId = localPeerId;\n this.remotePeerId = remotePeerId;\n\n this._control.onExtensionRegistered.set(async (name) => {\n log('remote extension', { name });\n invariant(!this._remoteExtensions.has(name), 'Remote extension already exists');\n this._remoteExtensions.add(name);\n\n if (this._extensions.has(name)) {\n try {\n await this._openExtension(name);\n } catch (err: any) {\n await this.destroy(err);\n }\n }\n });\n\n {\n // Destroy Teleport when the stream is closed.\n this._muxer.stream.on('close', async () => {\n await this.destroy();\n });\n\n this._muxer.stream.on('error', async (err) => {\n await this.destroy(err);\n });\n }\n }\n\n get stream(): Duplex {\n return this._muxer.stream;\n }\n\n get stats(): Event<ConnectionInfo.StreamStats[]> {\n return this._muxer.statsUpdated;\n }\n\n /**\n * Blocks until the handshake is complete.\n */\n async open() {\n this._setExtension('dxos.mesh.teleport.control', this._control);\n await this._openExtension('dxos.mesh.teleport.control');\n this._open = true;\n }\n\n async close(err?: Error) {\n // TODO(dmaretskyi): Try soft close.\n\n await this.destroy(err);\n }\n\n @synchronized\n async destroy(err?: Error) {\n if (this._ctx.disposed) {\n return;\n }\n\n await this._ctx.dispose();\n\n for (const extension of this._extensions.values()) {\n try {\n await extension.onClose(err);\n } catch (err: any) {\n log.catch(err);\n }\n }\n\n this._muxer.destroy(err);\n }\n\n addExtension(name: string, extension: TeleportExtension) {\n if (!this._open) {\n throw new Error('Not open');\n }\n\n log('addExtension', { name });\n this._setExtension(name, extension);\n\n // Perform the registration in a separate tick as this might block while the remote side is opening the extension.\n scheduleTask(this._ctx, async () => {\n try {\n await this._control.registerExtension(name);\n } catch (err) {\n if (err instanceof RpcClosedError) {\n return;\n }\n throw err;\n }\n });\n\n if (this._remoteExtensions.has(name)) {\n // Open the extension in a separate tick.\n scheduleTask(this._ctx, async () => {\n await this._openExtension(name);\n });\n }\n }\n\n private _setExtension(extensionName: string, extension: TeleportExtension) {\n invariant(!extensionName.includes('/'), 'Invalid extension name');\n invariant(!this._extensions.has(extensionName), 'Extension already exists');\n this._extensions.set(extensionName, extension);\n }\n\n private async _openExtension(extensionName: string) {\n log('open extension', { extensionName });\n const extension = this._extensions.get(extensionName) ?? failUndefined();\n\n const context: ExtensionContext = {\n initiator: this.initiator,\n localPeerId: this.localPeerId,\n remotePeerId: this.remotePeerId,\n createPort: (channelName: string, opts?: CreateChannelOpts) => {\n invariant(!channelName.includes('/'), 'Invalid channel name');\n return this._muxer.createPort(`${extensionName}/${channelName}`, opts);\n },\n createStream: (channelName: string, opts?: CreateChannelOpts) => {\n invariant(!channelName.includes('/'), 'Invalid channel name');\n return this._muxer.createStream(`${extensionName}/${channelName}`, opts);\n },\n close: (err) => {\n void runInContextAsync(this._ctx, async () => {\n await this.close(err);\n });\n },\n };\n\n await extension.onOpen(context);\n log('extension opened', { extensionName });\n }\n}\n\nexport type ExtensionContext = {\n /**\n * One of the peers will be designated an initiator.\n */\n initiator: boolean;\n localPeerId: PublicKey;\n remotePeerId: PublicKey;\n createStream(tag: string, opts?: CreateChannelOpts): Duplex;\n createPort(tag: string, opts?: CreateChannelOpts): RpcPort;\n close(err?: Error): void;\n};\n\nexport interface TeleportExtension {\n onOpen(context: ExtensionContext): Promise<void>;\n onClose(err?: Error): Promise<void>;\n}\n\ntype ControlExtensionOpts = {\n heartbeatInterval: number;\n heartbeatTimeout: number;\n onTimeout: () => void;\n};\n\nclass ControlExtension implements TeleportExtension {\n private readonly _ctx = new Context({\n onError: (err) => {\n this._extensionContext.close(err);\n },\n });\n\n private _extensionContext!: ExtensionContext;\n private _rpc!: ProtoRpcPeer<{ Control: ControlService }>;\n\n public readonly onExtensionRegistered = new Callback<(extensionName: string) => void>();\n\n constructor(private readonly opts: ControlExtensionOpts) {}\n\n async onOpen(extensionContext: ExtensionContext): Promise<void> {\n this._extensionContext = extensionContext;\n\n // NOTE: Make sure that RPC timeout is greater than the heartbeat timeout.\n // TODO(dmaretskyi): Allow overwriting the timeout on individual RPC calls?\n this._rpc = createProtoRpcPeer<ControlRpcBundle, ControlRpcBundle>({\n requested: {\n Control: schema.getService('dxos.mesh.teleport.control.ControlService'),\n },\n exposed: {\n Control: schema.getService('dxos.mesh.teleport.control.ControlService'),\n },\n handlers: {\n Control: {\n registerExtension: async (request) => {\n this.onExtensionRegistered.call(request.name);\n },\n heartbeat: async (request) => {\n // Ok.\n },\n },\n },\n port: extensionContext.createPort('rpc', {\n contentType: 'application/x-protobuf; messagType=\"dxos.rpc.Message\"',\n }),\n });\n\n await this._rpc.open();\n\n scheduleTaskInterval(\n this._ctx,\n async () => {\n try {\n await asyncTimeout(this._rpc.rpc.Control.heartbeat(), this.opts.heartbeatTimeout);\n } catch (err: any) {\n this.opts.onTimeout();\n }\n },\n this.opts.heartbeatInterval,\n );\n }\n\n async onClose(err?: Error): Promise<void> {\n await this._ctx.dispose();\n await this._rpc.close();\n }\n\n async registerExtension(name: string) {\n await this._rpc.rpc.Control.registerExtension({ name });\n }\n}\n\ntype ControlRpcBundle = {\n Control: ControlService;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport invariant from 'tiny-invariant';\n\nimport { asyncTimeout, Trigger } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\nimport { TestService } from '@dxos/protocols/proto/example/testing/rpc';\nimport { createProtoRpcPeer, ProtoRpcPeer } from '@dxos/rpc';\n\nimport { ExtensionContext, TeleportExtension } from '../teleport';\n\ninterface TestExtensionCallbacks {\n onOpen?: () => Promise<void>;\n onClose?: () => Promise<void>;\n}\n\nexport class TestExtension implements TeleportExtension {\n public readonly open = new Trigger();\n public readonly closed = new Trigger();\n public extensionContext: ExtensionContext | undefined;\n private _rpc!: ProtoRpcPeer<{ TestService: TestService }>;\n\n constructor(public readonly callbacks: TestExtensionCallbacks = {}) {}\n\n get remotePeerId() {\n return this.extensionContext?.remotePeerId;\n }\n\n async onOpen(context: ExtensionContext) {\n log('onOpen', { localPeerId: context.localPeerId, remotePeerId: context.remotePeerId });\n this.extensionContext = context;\n this._rpc = createProtoRpcPeer<{ TestService: TestService }, { TestService: TestService }>({\n port: context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"',\n }),\n requested: {\n TestService: schema.getService('example.testing.rpc.TestService'),\n },\n exposed: {\n TestService: schema.getService('example.testing.rpc.TestService'),\n },\n handlers: {\n TestService: {\n voidCall: async (request) => {\n // Ok.\n },\n testCall: async (request) => {\n return {\n data: request.data,\n };\n },\n },\n },\n timeout: 1000,\n });\n\n await this._rpc.open();\n await this.callbacks.onOpen?.();\n\n this.open.wake();\n }\n\n async onClose(err?: Error) {\n log('onClose', { err });\n await this.callbacks.onClose?.();\n this.closed.wake();\n await this._rpc?.close();\n }\n\n async test(message = 'test') {\n await this.open.wait({ timeout: 500 });\n const res = await asyncTimeout(this._rpc.rpc.TestService.testCall({ data: message }), 500);\n invariant(res.data === message);\n }\n\n /**\n * Force-close the connection.\n */\n async closeConnection(err?: Error) {\n this.extensionContext?.close(err);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Duplex", "invariant", "varint", "Framer", "_stream", "Duplex", "objectMode", "read", "write", "chunk", "encoding", "callback", "invariant", "_subscribeCb", "_buffer", "length", "Buffer", "concat", "_messageCb", "_popFrames", "undefined", "port", "send", "message", "push", "encodeFrame", "subscribe", "stream", "offset", "frame", "decodeFrame", "bytesConsumed", "payload", "subarray", "destroy", "buffer", "frameLength", "decode", "tagLength", "bytes", "err", "RangeError", "encodingLength", "allocUnsafe", "varint", "encode", "set", "Duplex", "invariant", "Event", "scheduleTaskInterval", "Context", "failUndefined", "log", "schema", "codec", "schema", "getCodecForType", "STATS_INTERVAL", "Muxer", "constructor", "_framer", "Framer", "stream", "_channelsByLocalId", "Map", "_channelsByTag", "_nextId", "_destroyed", "_destroying", "close", "Event", "statsUpdated", "_ctx", "Context", "port", "subscribe", "msg", "_handleCommand", "decode", "scheduleTaskInterval", "_emitStats", "createStream", "tag", "opts", "channel", "_getOrCreateStream", "contentType", "invariant", "push", "Duplex", "write", "data", "encoding", "callback", "_sendData", "read", "stats", "bytesReceived", "length", "destroy", "err", "_sendCommand", "openChannel", "id", "createPort", "inboundBuffer", "send", "cb", "error", "message", "_dispose", "dispose", "values", "emit", "clear", "cmd", "log", "warn", "remoteId", "buffer", "channelId", "get", "failUndefined", "Promise", "resolve", "encode", "catch", "params", "bytesSent", "set", "Array", "from", "map", "invariant", "asyncTimeout", "scheduleTaskInterval", "runInContextAsync", "synchronized", "scheduleTask", "Context", "failUndefined", "PublicKey", "log", "schema", "RpcClosedError", "createProtoRpcPeer", "Callback", "Teleport", "constructor", "initiator", "localPeerId", "remotePeerId", "_ctx", "Context", "onError", "err", "destroy", "catch", "log", "error", "_muxer", "Muxer", "_control", "ControlExtension", "heartbeatInterval", "heartbeatTimeout", "onTimeout", "Error", "_extensions", "Map", "_remoteExtensions", "Set", "_open", "invariant", "PublicKey", "isPublicKey", "onExtensionRegistered", "set", "name", "has", "add", "_openExtension", "stream", "on", "stats", "statsUpdated", "open", "_setExtension", "close", "disposed", "dispose", "extension", "values", "onClose", "addExtension", "scheduleTask", "registerExtension", "RpcClosedError", "extensionName", "includes", "get", "failUndefined", "context", "createPort", "channelName", "opts", "createStream", "runInContextAsync", "onOpen", "synchronized", "_extensionContext", "Callback", "extensionContext", "_rpc", "createProtoRpcPeer", "requested", "Control", "schema", "getService", "exposed", "handlers", "request", "call", "heartbeat", "port", "contentType", "scheduleTaskInterval", "asyncTimeout", "rpc", "invariant", "asyncTimeout", "Trigger", "log", "schema", "createProtoRpcPeer", "TestExtension", "constructor", "callbacks", "open", "closed", "remotePeerId", "extensionContext", "onOpen", "context", "localPeerId", "_rpc", "port", "createPort", "contentType", "requested", "TestService", "getService", "exposed", "handlers", "voidCall", "request", "testCall", "data", "timeout", "wake", "onClose", "err", "close", "test", "message", "wait", "res", "rpc", "closeConnection"]
|
|
7
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "@dxos/node-std/globals"
|
|
1
|
+
import "@dxos/node-std/globals";
|
|
2
2
|
import {
|
|
3
3
|
Framer,
|
|
4
4
|
Muxer,
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
TestExtension,
|
|
7
7
|
decodeFrame,
|
|
8
8
|
encodeFrame
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-YGY6ZROZ.mjs";
|
|
10
10
|
|
|
11
11
|
// packages/core/mesh/teleport/src/rpc-extension.ts
|
|
12
|
-
import
|
|
12
|
+
import invariant from "tiny-invariant";
|
|
13
13
|
import { createProtoRpcPeer } from "@dxos/rpc";
|
|
14
14
|
var RpcExtension = class {
|
|
15
15
|
constructor(_rpcParams) {
|
|
@@ -26,7 +26,7 @@ var RpcExtension = class {
|
|
|
26
26
|
return this._extensionContext.remotePeerId;
|
|
27
27
|
}
|
|
28
28
|
get rpc() {
|
|
29
|
-
|
|
29
|
+
invariant(this._rpc);
|
|
30
30
|
return this._rpc.rpc;
|
|
31
31
|
}
|
|
32
32
|
async onOpen(context) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/rpc-extension.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport
|
|
5
|
-
"mappings": ";;;;;;;;;;;AAIA,OAAOA,
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport invariant from 'tiny-invariant';\n\nimport { createProtoRpcPeer, ProtoRpcPeer, ProtoRpcPeerOptions } from '@dxos/rpc';\n\nimport { ExtensionContext, TeleportExtension } from './teleport';\n\nexport abstract class RpcExtension<Client, Server> implements TeleportExtension {\n // TODO(dmaretskyi): Type optionally.\n private _extensionContext!: ExtensionContext;\n private _rpc?: ProtoRpcPeer<Client>;\n\n private _isClosed = false;\n\n constructor(private readonly _rpcParams: Omit<ProtoRpcPeerOptions<Client, Server>, 'port' | 'handlers'>) {}\n\n get initiator() {\n return this._extensionContext.initiator;\n }\n\n get localPeerId() {\n return this._extensionContext.localPeerId;\n }\n\n get remotePeerId() {\n return this._extensionContext.remotePeerId;\n }\n\n get rpc(): Client {\n invariant(this._rpc);\n return this._rpc.rpc;\n }\n\n protected abstract getHandlers(): Promise<Server>;\n\n async onOpen(context: ExtensionContext): Promise<void> {\n this._extensionContext = context;\n\n const handlers = await this.getHandlers();\n\n if (this._isClosed) {\n return;\n }\n\n const port = context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"',\n });\n this._rpc = createProtoRpcPeer({\n ...this._rpcParams,\n handlers,\n port,\n });\n\n await this._rpc.open();\n }\n\n async onClose(err?: Error | undefined): Promise<void> {\n this._isClosed = true;\n await this._rpc?.close();\n }\n\n close() {\n this._extensionContext.close();\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;AAIA,OAAOA,eAAe;AAEtB,SAASC,0BAA6D;AAI/D,IAAeC,eAAf,MAAeA;EAOpBC,YAA6BC,YAA4E;sBAA5EA;SAFrBC,YAAY;EAEsF;EAE1G,IAAIC,YAAY;AACd,WAAO,KAAKC,kBAAkBD;EAChC;EAEA,IAAIE,cAAc;AAChB,WAAO,KAAKD,kBAAkBC;EAChC;EAEA,IAAIC,eAAe;AACjB,WAAO,KAAKF,kBAAkBE;EAChC;EAEA,IAAIC,MAAc;AAChBC,cAAU,KAAKC,IAAI;AACnB,WAAO,KAAKA,KAAKF;EACnB;EAIA,MAAMG,OAAOC,SAA0C;AACrD,SAAKP,oBAAoBO;AAEzB,UAAMC,WAAW,MAAM,KAAKC,YAAW;AAEvC,QAAI,KAAKX,WAAW;AAClB;IACF;AAEA,UAAMY,OAAOH,QAAQI,WAAW,OAAO;MACrCC,aAAa;IACf,CAAA;AACA,SAAKP,OAAOQ,mBAAmB;MAC7B,GAAG,KAAKhB;MACRW;MACAE;IACF,CAAA;AAEA,UAAM,KAAKL,KAAKS,KAAI;EACtB;EAEA,MAAMC,QAAQC,KAAwC;AA3DxD;AA4DI,SAAKlB,YAAY;AACjB,YAAM,UAAKO,SAAL,mBAAWY;EACnB;EAEAA,QAAQ;AACN,SAAKjB,kBAAkBiB,MAAK;EAC9B;AACF;",
|
|
6
|
+
"names": ["invariant", "createProtoRpcPeer", "RpcExtension", "constructor", "_rpcParams", "_isClosed", "initiator", "_extensionContext", "localPeerId", "remotePeerId", "rpc", "invariant", "_rpc", "onOpen", "context", "handlers", "getHandlers", "port", "createPort", "contentType", "createProtoRpcPeer", "open", "onClose", "err", "close"]
|
|
7
7
|
}
|