@dxos/teleport 0.1.18 → 0.1.19
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/index.mjs +72 -11
- package/dist/lib/browser/index.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +13 -12
- package/dist/lib/browser/testing/index.mjs.map +7 -0
- package/dist/lib/node/index.cjs +73 -11
- package/dist/lib/node/index.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +13 -12
- package/dist/lib/node/testing/index.cjs.map +7 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/rpc-extension.d.ts +17 -0
- package/dist/types/src/rpc-extension.d.ts.map +1 -0
- package/package.json +10 -10
- package/src/index.ts +1 -0
- package/src/rpc-extension.ts +63 -0
|
@@ -217,14 +217,14 @@ var Muxer = class {
|
|
|
217
217
|
log("Received command", {
|
|
218
218
|
cmd
|
|
219
219
|
}, {
|
|
220
|
-
file: "
|
|
220
|
+
file: "muxer.ts",
|
|
221
221
|
line: 194,
|
|
222
222
|
scope: this,
|
|
223
223
|
callSite: (f, a) => f(...a)
|
|
224
224
|
});
|
|
225
225
|
if (this._destroyed || this._destroying) {
|
|
226
226
|
log.warn("Received command after destroy", {}, {
|
|
227
|
-
file: "
|
|
227
|
+
file: "muxer.ts",
|
|
228
228
|
line: 197,
|
|
229
229
|
scope: this,
|
|
230
230
|
callSite: (f, a) => f(...a)
|
|
@@ -252,7 +252,7 @@ var Muxer = class {
|
|
|
252
252
|
log.warn("Received data for channel before it was opened", {
|
|
253
253
|
tag: stream.tag
|
|
254
254
|
}, {
|
|
255
|
-
file: "
|
|
255
|
+
file: "muxer.ts",
|
|
256
256
|
line: 221,
|
|
257
257
|
scope: this,
|
|
258
258
|
callSite: (f, a) => f(...a)
|
|
@@ -326,7 +326,7 @@ var Teleport = class {
|
|
|
326
326
|
onError: (err) => {
|
|
327
327
|
void this.destroy(err).catch(() => {
|
|
328
328
|
log2.error("Error during destroy", err, {
|
|
329
|
-
file: "
|
|
329
|
+
file: "teleport.ts",
|
|
330
330
|
line: 34,
|
|
331
331
|
scope: this,
|
|
332
332
|
callSite: (f, a) => f(...a)
|
|
@@ -353,7 +353,7 @@ var Teleport = class {
|
|
|
353
353
|
log2("remote extension", {
|
|
354
354
|
name
|
|
355
355
|
}, {
|
|
356
|
-
file: "
|
|
356
|
+
file: "teleport.ts",
|
|
357
357
|
line: 61,
|
|
358
358
|
scope: this,
|
|
359
359
|
callSite: (f, a) => f(...a)
|
|
@@ -398,7 +398,7 @@ var Teleport = class {
|
|
|
398
398
|
await extension.onClose(err);
|
|
399
399
|
} catch (err1) {
|
|
400
400
|
log2.catch(err1, {}, {
|
|
401
|
-
file: "
|
|
401
|
+
file: "teleport.ts",
|
|
402
402
|
line: 117,
|
|
403
403
|
scope: this,
|
|
404
404
|
callSite: (f, a) => f(...a)
|
|
@@ -414,7 +414,7 @@ var Teleport = class {
|
|
|
414
414
|
log2("addExtension", {
|
|
415
415
|
name
|
|
416
416
|
}, {
|
|
417
|
-
file: "
|
|
417
|
+
file: "teleport.ts",
|
|
418
418
|
line: 129,
|
|
419
419
|
scope: this,
|
|
420
420
|
callSite: (f, a) => f(...a)
|
|
@@ -446,7 +446,7 @@ var Teleport = class {
|
|
|
446
446
|
log2("open extension", {
|
|
447
447
|
extensionName
|
|
448
448
|
}, {
|
|
449
|
-
file: "
|
|
449
|
+
file: "teleport.ts",
|
|
450
450
|
line: 159,
|
|
451
451
|
scope: this,
|
|
452
452
|
callSite: (f, a) => f(...a)
|
|
@@ -474,7 +474,7 @@ var Teleport = class {
|
|
|
474
474
|
log2("extension opened", {
|
|
475
475
|
extensionName
|
|
476
476
|
}, {
|
|
477
|
-
file: "
|
|
477
|
+
file: "teleport.ts",
|
|
478
478
|
line: 182,
|
|
479
479
|
scope: this,
|
|
480
480
|
callSite: (f, a) => f(...a)
|
|
@@ -559,7 +559,7 @@ var TestExtension = class {
|
|
|
559
559
|
localPeerId: context.localPeerId,
|
|
560
560
|
remotePeerId: context.remotePeerId
|
|
561
561
|
}, {
|
|
562
|
-
file: "
|
|
562
|
+
file: "test-extension.ts",
|
|
563
563
|
line: 33,
|
|
564
564
|
scope: this,
|
|
565
565
|
callSite: (f, a) => f(...a)
|
|
@@ -597,7 +597,7 @@ var TestExtension = class {
|
|
|
597
597
|
log3("onClose", {
|
|
598
598
|
err
|
|
599
599
|
}, {
|
|
600
|
-
file: "
|
|
600
|
+
file: "test-extension.ts",
|
|
601
601
|
line: 67,
|
|
602
602
|
scope: this,
|
|
603
603
|
callSite: (f, a) => f(...a)
|
|
@@ -616,11 +616,72 @@ var TestExtension = class {
|
|
|
616
616
|
assert4(res.data === "test");
|
|
617
617
|
}
|
|
618
618
|
};
|
|
619
|
+
|
|
620
|
+
// packages/core/mesh/teleport/src/rpc-extension.ts
|
|
621
|
+
import assert5 from "@dxos/node-std/assert";
|
|
622
|
+
import { synchronized as synchronized2 } from "@dxos/async";
|
|
623
|
+
import { createProtoRpcPeer as createProtoRpcPeer3 } from "@dxos/rpc";
|
|
624
|
+
var __decorate2 = function(decorators, target, key, desc) {
|
|
625
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
626
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
627
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
628
|
+
else
|
|
629
|
+
for (var i = decorators.length - 1; i >= 0; i--)
|
|
630
|
+
if (d = decorators[i])
|
|
631
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
632
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
633
|
+
};
|
|
634
|
+
var RpcExtension = class {
|
|
635
|
+
constructor(_params) {
|
|
636
|
+
this._params = _params;
|
|
637
|
+
}
|
|
638
|
+
get initiator() {
|
|
639
|
+
return this._extensionContext.initiator;
|
|
640
|
+
}
|
|
641
|
+
get localPeerId() {
|
|
642
|
+
return this._extensionContext.localPeerId;
|
|
643
|
+
}
|
|
644
|
+
get remotePeerId() {
|
|
645
|
+
return this._extensionContext.remotePeerId;
|
|
646
|
+
}
|
|
647
|
+
get rpc() {
|
|
648
|
+
assert5(this._rpc);
|
|
649
|
+
return this._rpc.rpc;
|
|
650
|
+
}
|
|
651
|
+
async onOpen(context) {
|
|
652
|
+
this._extensionContext = context;
|
|
653
|
+
const handlers = await this.getHandlers();
|
|
654
|
+
const port = context.createPort("rpc", {
|
|
655
|
+
contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
|
|
656
|
+
});
|
|
657
|
+
this._rpc = createProtoRpcPeer3({
|
|
658
|
+
...this._params,
|
|
659
|
+
handlers,
|
|
660
|
+
port
|
|
661
|
+
});
|
|
662
|
+
await this._rpc.open();
|
|
663
|
+
}
|
|
664
|
+
async onClose(err) {
|
|
665
|
+
var _a;
|
|
666
|
+
await ((_a = this._rpc) == null ? void 0 : _a.close());
|
|
667
|
+
}
|
|
668
|
+
close() {
|
|
669
|
+
this._extensionContext.close();
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
__decorate2([
|
|
673
|
+
synchronized2
|
|
674
|
+
], RpcExtension.prototype, "onOpen", null);
|
|
675
|
+
__decorate2([
|
|
676
|
+
synchronized2
|
|
677
|
+
], RpcExtension.prototype, "onClose", null);
|
|
619
678
|
export {
|
|
620
679
|
Framer,
|
|
621
680
|
Muxer,
|
|
681
|
+
RpcExtension,
|
|
622
682
|
Teleport,
|
|
623
683
|
TestExtension,
|
|
624
684
|
decodeFrame,
|
|
625
685
|
encodeFrame
|
|
626
686
|
};
|
|
687
|
+
//# sourceMappingURL=index.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", "../../../src/rpc-extension.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\nimport { Duplex } from 'node:stream';\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 assert(!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 assert(!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 assert from 'node:assert';\nimport { Duplex } from 'node:stream';\n\nimport { Event } from '@dxos/async';\nimport { failUndefined } from '@dxos/debug';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\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\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 constructor() {\n this._framer.port.subscribe((msg) => {\n this._handleCommand(codec.decode(msg));\n });\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 assert(!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 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 assert(!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 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 assert(!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 }\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 };\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 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\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\ntype CreateChannelInternalParams = {\n tag: string;\n contentType?: string;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\nimport { Duplex } from 'node:stream';\n\nimport { asyncTimeout, scheduleTaskInterval, runInContextAsync, synchronized, scheduleTask } 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 } from '@dxos/protocols';\nimport { ControlService } from '@dxos/protocols/proto/dxos/mesh/teleport/control';\nimport { createProtoRpcPeer, ProtoRpcPeer, RpcClosedError } 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: 3000,\n heartbeatTimeout: 3000\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 assert(typeof initiator === 'boolean');\n assert(PublicKey.isPublicKey(localPeerId));\n assert(PublicKey.isPublicKey(remotePeerId));\n assert(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 assert(!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 /**\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 assert(!extensionName.includes('/'), 'Invalid extension name');\n assert(!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 assert(!channelName.includes('/'), 'Invalid channel name');\n return this._muxer.createPort(`${extensionName}/${channelName}`, opts);\n },\n createStream: (channelName: string, opts?: CreateChannelOpts) => {\n assert(!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};\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 public readonly onTimeout = new Callback<() => 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; messageType=\"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.onTimeout.call();\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 assert from 'node:assert';\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() {\n await this.open.wait({ timeout: 500 });\n const res = await asyncTimeout(this._rpc.rpc.TestService.testCall({ data: 'test' }), 500);\n assert(res.data === 'test');\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\n\nimport { synchronized } from '@dxos/async';\nimport { createProtoRpcPeer, ProtoRpcPeer, ProtoRpcPeerOptions } from '@dxos/rpc';\n\nimport { ExtensionContext, TeleportExtension } from './teleport';\n\nexport abstract class RpcExtension<Client, Server> implements TeleportExtension {\n private _extensionContext!: ExtensionContext;\n private _rpc?: ProtoRpcPeer<Client>;\n\n constructor(private readonly _params: 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 assert(this._rpc);\n return this._rpc.rpc;\n }\n\n protected abstract getHandlers(): Promise<Server>;\n\n @synchronized\n async onOpen(context: ExtensionContext): Promise<void> {\n this._extensionContext = context;\n\n const handlers = await this.getHandlers();\n\n const port = context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"'\n });\n this._rpc = createProtoRpcPeer({\n ...this._params,\n handlers,\n port\n });\n\n await this._rpc.open();\n }\n\n @synchronized\n async onClose(err?: Error | undefined): Promise<void> {\n await this._rpc?.close();\n }\n\n close() {\n this._extensionContext.close();\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["assert", "Duplex", "varint", "Framer", "_stream", "objectMode", "read", "write", "chunk", "encoding", "callback", "_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", "encode", "set", "assert", "Duplex", "Event", "failUndefined", "log", "schema", "codec", "schema", "getCodecForType", "Muxer", "constructor", "_framer", "Framer", "stream", "_channelsByLocalId", "Map", "_channelsByTag", "_nextId", "_destroyed", "_destroying", "close", "Event", "port", "subscribe", "msg", "_handleCommand", "decode", "createStream", "tag", "opts", "channel", "_getOrCreateStream", "contentType", "assert", "push", "Duplex", "write", "data", "encoding", "callback", "_sendData", "read", "destroy", "err", "_sendCommand", "openChannel", "id", "createPort", "inboundBuffer", "send", "cb", "error", "message", "_dispose", "values", "emit", "clear", "cmd", "log", "warn", "remoteId", "buffer", "channelId", "get", "failUndefined", "Promise", "resolve", "encode", "catch", "params", "set", "assert", "asyncTimeout", "scheduleTaskInterval", "runInContextAsync", "synchronized", "scheduleTask", "Context", "failUndefined", "PublicKey", "log", "schema", "createProtoRpcPeer", "RpcClosedError", "Callback", "Teleport", "constructor", "initiator", "localPeerId", "remotePeerId", "_ctx", "Context", "onError", "err", "destroy", "catch", "log", "error", "_muxer", "Muxer", "_control", "ControlExtension", "heartbeatInterval", "heartbeatTimeout", "_extensions", "Map", "_remoteExtensions", "Set", "_open", "assert", "PublicKey", "isPublicKey", "onExtensionRegistered", "set", "name", "has", "add", "_openExtension", "stream", "on", "open", "_setExtension", "close", "disposed", "dispose", "extension", "values", "onClose", "addExtension", "Error", "scheduleTask", "registerExtension", "RpcClosedError", "extensionName", "includes", "get", "failUndefined", "context", "createPort", "channelName", "opts", "createStream", "runInContextAsync", "onOpen", "synchronized", "_extensionContext", "Callback", "onTimeout", "extensionContext", "_rpc", "createProtoRpcPeer", "requested", "Control", "schema", "getService", "exposed", "handlers", "request", "call", "heartbeat", "port", "contentType", "scheduleTaskInterval", "asyncTimeout", "rpc", "assert", "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", "wait", "res", "rpc", "assert", "synchronized", "createProtoRpcPeer", "__decorate", "RpcExtension", "constructor", "_params", "initiator", "_extensionContext", "localPeerId", "remotePeerId", "rpc", "_rpc", "onOpen", "context", "handlers", "getHandlers", "port", "createPort", "contentType", "open", "onClose", "err", "close"]
|
|
7
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"packages/core/mesh/teleport/src/muxing/framer.ts":{"bytes":
|
|
1
|
+
{"inputs":{"packages/core/mesh/teleport/src/muxing/framer.ts":{"bytes":12785,"imports":[]},"packages/core/mesh/teleport/src/muxing/muxer.ts":{"bytes":25338,"imports":[{"path":"packages/core/mesh/teleport/src/muxing/framer.ts","kind":"import-statement"}]},"packages/core/mesh/teleport/src/muxing/rpc-port.ts":{"bytes":824,"imports":[]},"packages/core/mesh/teleport/src/muxing/index.ts":{"bytes":539,"imports":[{"path":"packages/core/mesh/teleport/src/muxing/framer.ts","kind":"import-statement"},{"path":"packages/core/mesh/teleport/src/muxing/muxer.ts","kind":"import-statement"},{"path":"packages/core/mesh/teleport/src/muxing/rpc-port.ts","kind":"import-statement"}]},"packages/core/mesh/teleport/src/teleport.ts":{"bytes":27441,"imports":[{"path":"packages/core/mesh/teleport/src/muxing/index.ts","kind":"import-statement"}]},"packages/core/mesh/teleport/src/testing/test-extension.ts":{"bytes":7935,"imports":[]},"packages/core/mesh/teleport/src/rpc-extension.ts":{"bytes":5596,"imports":[]},"packages/core/mesh/teleport/src/index.ts":{"bytes":685,"imports":[{"path":"packages/core/mesh/teleport/src/muxing/index.ts","kind":"import-statement"},{"path":"packages/core/mesh/teleport/src/teleport.ts","kind":"import-statement"},{"path":"packages/core/mesh/teleport/src/testing/test-extension.ts","kind":"import-statement"},{"path":"packages/core/mesh/teleport/src/rpc-extension.ts","kind":"import-statement"}]},"packages/core/mesh/teleport/src/testing/test-builder.ts":{"bytes":7379,"imports":[{"path":"packages/core/mesh/teleport/src/teleport.ts","kind":"import-statement"}]},"packages/core/mesh/teleport/src/testing/index.ts":{"bytes":494,"imports":[{"path":"packages/core/mesh/teleport/src/testing/test-builder.ts","kind":"import-statement"},{"path":"packages/core/mesh/teleport/src/testing/test-extension.ts","kind":"import-statement"}]}},"outputs":{"packages/core/mesh/teleport/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":38915},"packages/core/mesh/teleport/dist/lib/browser/index.mjs":{"imports":[],"exports":["Framer","Muxer","RpcExtension","Teleport","TestExtension","decodeFrame","encodeFrame"],"entryPoint":"packages/core/mesh/teleport/src/index.ts","inputs":{"packages/core/mesh/teleport/src/muxing/framer.ts":{"bytesInOutput":2560},"packages/core/mesh/teleport/src/muxing/index.ts":{"bytesInOutput":0},"packages/core/mesh/teleport/src/muxing/muxer.ts":{"bytesInOutput":5087},"packages/core/mesh/teleport/src/index.ts":{"bytesInOutput":0},"packages/core/mesh/teleport/src/teleport.ts":{"bytesInOutput":7144},"packages/core/mesh/teleport/src/testing/test-extension.ts":{"bytesInOutput":2203},"packages/core/mesh/teleport/src/rpc-extension.ts":{"bytesInOutput":1774}},"bytes":19208},"packages/core/mesh/teleport/dist/lib/browser/testing/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":39914},"packages/core/mesh/teleport/dist/lib/browser/testing/index.mjs":{"imports":[],"exports":["TestBuilder","TestExtension","TestPeer"],"entryPoint":"packages/core/mesh/teleport/src/testing/index.ts","inputs":{"packages/core/mesh/teleport/src/testing/test-builder.ts":{"bytesInOutput":1821},"packages/core/mesh/teleport/src/teleport.ts":{"bytesInOutput":7144},"packages/core/mesh/teleport/src/muxing/framer.ts":{"bytesInOutput":2560},"packages/core/mesh/teleport/src/muxing/index.ts":{"bytesInOutput":0},"packages/core/mesh/teleport/src/muxing/muxer.ts":{"bytesInOutput":5087},"packages/core/mesh/teleport/src/testing/index.ts":{"bytesInOutput":0},"packages/core/mesh/teleport/src/testing/test-extension.ts":{"bytesInOutput":2203}},"bytes":19320}}}
|
|
@@ -233,14 +233,14 @@ var Muxer = class {
|
|
|
233
233
|
log("Received command", {
|
|
234
234
|
cmd
|
|
235
235
|
}, {
|
|
236
|
-
file: "
|
|
236
|
+
file: "muxer.ts",
|
|
237
237
|
line: 194,
|
|
238
238
|
scope: this,
|
|
239
239
|
callSite: (f, a) => f(...a)
|
|
240
240
|
});
|
|
241
241
|
if (this._destroyed || this._destroying) {
|
|
242
242
|
log.warn("Received command after destroy", {}, {
|
|
243
|
-
file: "
|
|
243
|
+
file: "muxer.ts",
|
|
244
244
|
line: 197,
|
|
245
245
|
scope: this,
|
|
246
246
|
callSite: (f, a) => f(...a)
|
|
@@ -268,7 +268,7 @@ var Muxer = class {
|
|
|
268
268
|
log.warn("Received data for channel before it was opened", {
|
|
269
269
|
tag: stream.tag
|
|
270
270
|
}, {
|
|
271
|
-
file: "
|
|
271
|
+
file: "muxer.ts",
|
|
272
272
|
line: 221,
|
|
273
273
|
scope: this,
|
|
274
274
|
callSite: (f, a) => f(...a)
|
|
@@ -333,7 +333,7 @@ var Teleport = class {
|
|
|
333
333
|
onError: (err) => {
|
|
334
334
|
void this.destroy(err).catch(() => {
|
|
335
335
|
log2.error("Error during destroy", err, {
|
|
336
|
-
file: "
|
|
336
|
+
file: "teleport.ts",
|
|
337
337
|
line: 34,
|
|
338
338
|
scope: this,
|
|
339
339
|
callSite: (f, a) => f(...a)
|
|
@@ -360,7 +360,7 @@ var Teleport = class {
|
|
|
360
360
|
log2("remote extension", {
|
|
361
361
|
name
|
|
362
362
|
}, {
|
|
363
|
-
file: "
|
|
363
|
+
file: "teleport.ts",
|
|
364
364
|
line: 61,
|
|
365
365
|
scope: this,
|
|
366
366
|
callSite: (f, a) => f(...a)
|
|
@@ -405,7 +405,7 @@ var Teleport = class {
|
|
|
405
405
|
await extension.onClose(err);
|
|
406
406
|
} catch (err1) {
|
|
407
407
|
log2.catch(err1, {}, {
|
|
408
|
-
file: "
|
|
408
|
+
file: "teleport.ts",
|
|
409
409
|
line: 117,
|
|
410
410
|
scope: this,
|
|
411
411
|
callSite: (f, a) => f(...a)
|
|
@@ -421,7 +421,7 @@ var Teleport = class {
|
|
|
421
421
|
log2("addExtension", {
|
|
422
422
|
name
|
|
423
423
|
}, {
|
|
424
|
-
file: "
|
|
424
|
+
file: "teleport.ts",
|
|
425
425
|
line: 129,
|
|
426
426
|
scope: this,
|
|
427
427
|
callSite: (f, a) => f(...a)
|
|
@@ -453,7 +453,7 @@ var Teleport = class {
|
|
|
453
453
|
log2("open extension", {
|
|
454
454
|
extensionName
|
|
455
455
|
}, {
|
|
456
|
-
file: "
|
|
456
|
+
file: "teleport.ts",
|
|
457
457
|
line: 159,
|
|
458
458
|
scope: this,
|
|
459
459
|
callSite: (f, a) => f(...a)
|
|
@@ -481,7 +481,7 @@ var Teleport = class {
|
|
|
481
481
|
log2("extension opened", {
|
|
482
482
|
extensionName
|
|
483
483
|
}, {
|
|
484
|
-
file: "
|
|
484
|
+
file: "teleport.ts",
|
|
485
485
|
line: 182,
|
|
486
486
|
scope: this,
|
|
487
487
|
callSite: (f, a) => f(...a)
|
|
@@ -602,7 +602,7 @@ var TestPeer = class {
|
|
|
602
602
|
pipeline(this.teleport.stream, peer.teleport.stream, (err) => {
|
|
603
603
|
if (err && err.code !== "ERR_STREAM_PREMATURE_CLOSE") {
|
|
604
604
|
log3.catch(err, {}, {
|
|
605
|
-
file: "
|
|
605
|
+
file: "test-builder.ts",
|
|
606
606
|
line: 67,
|
|
607
607
|
scope: this,
|
|
608
608
|
callSite: (f, a) => f(...a)
|
|
@@ -638,7 +638,7 @@ var TestExtension = class {
|
|
|
638
638
|
localPeerId: context.localPeerId,
|
|
639
639
|
remotePeerId: context.remotePeerId
|
|
640
640
|
}, {
|
|
641
|
-
file: "
|
|
641
|
+
file: "test-extension.ts",
|
|
642
642
|
line: 33,
|
|
643
643
|
scope: this,
|
|
644
644
|
callSite: (f, a) => f(...a)
|
|
@@ -676,7 +676,7 @@ var TestExtension = class {
|
|
|
676
676
|
log4("onClose", {
|
|
677
677
|
err
|
|
678
678
|
}, {
|
|
679
|
-
file: "
|
|
679
|
+
file: "test-extension.ts",
|
|
680
680
|
line: 67,
|
|
681
681
|
scope: this,
|
|
682
682
|
callSite: (f, a) => f(...a)
|
|
@@ -700,3 +700,4 @@ export {
|
|
|
700
700
|
TestExtension,
|
|
701
701
|
TestPeer
|
|
702
702
|
};
|
|
703
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/testing/test-builder.ts", "../../../../src/teleport.ts", "../../../../src/muxing/framer.ts", "../../../../src/muxing/muxer.ts", "../../../../src/testing/test-extension.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport { pipeline } from 'node:stream';\n\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\n\nimport { Teleport } from '../teleport';\n\nexport class TestBuilder {\n private readonly _peers = new Array<TestPeer>();\n\n createPeer(peerId?: PublicKey): TestPeer {\n const peer = new TestPeer(peerId);\n this._peers.push(peer);\n return peer;\n }\n\n async destroy() {\n await Promise.all(this._peers.map((agent) => agent.destroy()));\n }\n\n /**\n * Simulates two peers connected via P2P network.\n */\n async createPipedPeers({ peerId1, peerId2 }: { peerId1?: PublicKey; peerId2?: PublicKey } = {}) {\n const peer1 = this.createPeer(peerId1);\n const peer2 = this.createPeer(peerId2);\n\n peer1.initializeTeleport({ initiator: true, remotePeerId: peer2.peerId });\n peer2.initializeTeleport({ initiator: false, remotePeerId: peer1.peerId });\n\n peer1.pipeline(peer2);\n peer2.pipeline(peer1);\n\n await Promise.all([peer1.teleport!.open(), peer2.teleport!.open()]);\n\n return { peer1, peer2 };\n }\n}\n\nexport class TestPeer {\n public teleport?: Teleport;\n\n constructor(public readonly peerId: PublicKey = PublicKey.random()) {}\n\n initializeTeleport({ initiator, remotePeerId }: { initiator: boolean; remotePeerId: PublicKey }) {\n if (this.teleport) {\n return this;\n }\n this.teleport = new Teleport({\n initiator,\n localPeerId: this.peerId,\n remotePeerId\n });\n return this;\n }\n\n pipeline(peer: TestPeer) {\n if (!this.teleport || !peer.teleport) {\n throw new Error('Teleport not initialized');\n }\n pipeline(this.teleport.stream, peer.teleport.stream, (err) => {\n if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') {\n log.catch(err);\n }\n });\n }\n\n async destroy() {\n await this.teleport?.destroy();\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\nimport { Duplex } from 'node:stream';\n\nimport { asyncTimeout, scheduleTaskInterval, runInContextAsync, synchronized, scheduleTask } 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 } from '@dxos/protocols';\nimport { ControlService } from '@dxos/protocols/proto/dxos/mesh/teleport/control';\nimport { createProtoRpcPeer, ProtoRpcPeer, RpcClosedError } 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: 3000,\n heartbeatTimeout: 3000\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 assert(typeof initiator === 'boolean');\n assert(PublicKey.isPublicKey(localPeerId));\n assert(PublicKey.isPublicKey(remotePeerId));\n assert(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 assert(!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 /**\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 assert(!extensionName.includes('/'), 'Invalid extension name');\n assert(!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 assert(!channelName.includes('/'), 'Invalid channel name');\n return this._muxer.createPort(`${extensionName}/${channelName}`, opts);\n },\n createStream: (channelName: string, opts?: CreateChannelOpts) => {\n assert(!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};\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 public readonly onTimeout = new Callback<() => 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; messageType=\"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.onTimeout.call();\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 assert from 'node:assert';\nimport { Duplex } from 'node:stream';\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 assert(!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 assert(!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 assert from 'node:assert';\nimport { Duplex } from 'node:stream';\n\nimport { Event } from '@dxos/async';\nimport { failUndefined } from '@dxos/debug';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\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\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 constructor() {\n this._framer.port.subscribe((msg) => {\n this._handleCommand(codec.decode(msg));\n });\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 assert(!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 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 assert(!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 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 assert(!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 }\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 };\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 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\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\ntype CreateChannelInternalParams = {\n tag: string;\n contentType?: string;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\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() {\n await this.open.wait({ timeout: 500 });\n const res = await asyncTimeout(this._rpc.rpc.TestService.testCall({ data: 'test' }), 500);\n assert(res.data === 'test');\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["pipeline", "PublicKey", "log", "assert", "asyncTimeout", "scheduleTaskInterval", "runInContextAsync", "synchronized", "scheduleTask", "Context", "failUndefined", "PublicKey", "log", "schema", "createProtoRpcPeer", "RpcClosedError", "Callback", "assert", "Duplex", "varint", "Framer", "_stream", "objectMode", "read", "write", "chunk", "encoding", "callback", "_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", "encode", "set", "assert", "Duplex", "Event", "failUndefined", "log", "schema", "codec", "schema", "getCodecForType", "Muxer", "constructor", "_framer", "Framer", "stream", "_channelsByLocalId", "Map", "_channelsByTag", "_nextId", "_destroyed", "_destroying", "close", "Event", "port", "subscribe", "msg", "_handleCommand", "decode", "createStream", "tag", "opts", "channel", "_getOrCreateStream", "contentType", "assert", "push", "Duplex", "write", "data", "encoding", "callback", "_sendData", "read", "destroy", "err", "_sendCommand", "openChannel", "id", "createPort", "inboundBuffer", "send", "cb", "error", "message", "_dispose", "values", "emit", "clear", "cmd", "log", "warn", "remoteId", "buffer", "channelId", "get", "failUndefined", "Promise", "resolve", "encode", "catch", "params", "set", "Teleport", "constructor", "initiator", "localPeerId", "remotePeerId", "_ctx", "Context", "onError", "err", "destroy", "catch", "log", "error", "_muxer", "Muxer", "_control", "ControlExtension", "heartbeatInterval", "heartbeatTimeout", "_extensions", "Map", "_remoteExtensions", "Set", "_open", "assert", "PublicKey", "isPublicKey", "onExtensionRegistered", "set", "name", "has", "add", "_openExtension", "stream", "on", "open", "_setExtension", "close", "disposed", "dispose", "extension", "values", "onClose", "addExtension", "Error", "scheduleTask", "registerExtension", "RpcClosedError", "extensionName", "includes", "get", "failUndefined", "context", "createPort", "channelName", "opts", "createStream", "runInContextAsync", "onOpen", "synchronized", "_extensionContext", "Callback", "onTimeout", "extensionContext", "_rpc", "createProtoRpcPeer", "requested", "Control", "schema", "getService", "exposed", "handlers", "request", "call", "heartbeat", "port", "contentType", "scheduleTaskInterval", "asyncTimeout", "rpc", "TestBuilder", "_peers", "Array", "createPeer", "peerId", "peer", "TestPeer", "push", "destroy", "Promise", "all", "map", "agent", "createPipedPeers", "peerId1", "peerId2", "peer1", "peer2", "initializeTeleport", "initiator", "remotePeerId", "pipeline", "teleport", "open", "constructor", "PublicKey", "random", "Teleport", "localPeerId", "Error", "stream", "err", "code", "log", "catch", "assert", "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", "wait", "res", "rpc"]
|
|
7
|
+
}
|
package/dist/lib/node/index.cjs
CHANGED
|
@@ -28,6 +28,7 @@ var src_exports = {};
|
|
|
28
28
|
__export(src_exports, {
|
|
29
29
|
Framer: () => Framer,
|
|
30
30
|
Muxer: () => Muxer,
|
|
31
|
+
RpcExtension: () => RpcExtension,
|
|
31
32
|
Teleport: () => Teleport,
|
|
32
33
|
TestExtension: () => TestExtension,
|
|
33
34
|
decodeFrame: () => decodeFrame,
|
|
@@ -252,14 +253,14 @@ var Muxer = class {
|
|
|
252
253
|
(0, import_log.log)("Received command", {
|
|
253
254
|
cmd
|
|
254
255
|
}, {
|
|
255
|
-
file: "
|
|
256
|
+
file: "muxer.ts",
|
|
256
257
|
line: 194,
|
|
257
258
|
scope: this,
|
|
258
259
|
callSite: (f, a) => f(...a)
|
|
259
260
|
});
|
|
260
261
|
if (this._destroyed || this._destroying) {
|
|
261
262
|
import_log.log.warn("Received command after destroy", {}, {
|
|
262
|
-
file: "
|
|
263
|
+
file: "muxer.ts",
|
|
263
264
|
line: 197,
|
|
264
265
|
scope: this,
|
|
265
266
|
callSite: (f, a) => f(...a)
|
|
@@ -287,7 +288,7 @@ var Muxer = class {
|
|
|
287
288
|
import_log.log.warn("Received data for channel before it was opened", {
|
|
288
289
|
tag: stream.tag
|
|
289
290
|
}, {
|
|
290
|
-
file: "
|
|
291
|
+
file: "muxer.ts",
|
|
291
292
|
line: 221,
|
|
292
293
|
scope: this,
|
|
293
294
|
callSite: (f, a) => f(...a)
|
|
@@ -361,7 +362,7 @@ var Teleport = class {
|
|
|
361
362
|
onError: (err) => {
|
|
362
363
|
void this.destroy(err).catch(() => {
|
|
363
364
|
import_log2.log.error("Error during destroy", err, {
|
|
364
|
-
file: "
|
|
365
|
+
file: "teleport.ts",
|
|
365
366
|
line: 34,
|
|
366
367
|
scope: this,
|
|
367
368
|
callSite: (f, a) => f(...a)
|
|
@@ -388,7 +389,7 @@ var Teleport = class {
|
|
|
388
389
|
(0, import_log2.log)("remote extension", {
|
|
389
390
|
name
|
|
390
391
|
}, {
|
|
391
|
-
file: "
|
|
392
|
+
file: "teleport.ts",
|
|
392
393
|
line: 61,
|
|
393
394
|
scope: this,
|
|
394
395
|
callSite: (f, a) => f(...a)
|
|
@@ -433,7 +434,7 @@ var Teleport = class {
|
|
|
433
434
|
await extension.onClose(err);
|
|
434
435
|
} catch (err1) {
|
|
435
436
|
import_log2.log.catch(err1, {}, {
|
|
436
|
-
file: "
|
|
437
|
+
file: "teleport.ts",
|
|
437
438
|
line: 117,
|
|
438
439
|
scope: this,
|
|
439
440
|
callSite: (f, a) => f(...a)
|
|
@@ -449,7 +450,7 @@ var Teleport = class {
|
|
|
449
450
|
(0, import_log2.log)("addExtension", {
|
|
450
451
|
name
|
|
451
452
|
}, {
|
|
452
|
-
file: "
|
|
453
|
+
file: "teleport.ts",
|
|
453
454
|
line: 129,
|
|
454
455
|
scope: this,
|
|
455
456
|
callSite: (f, a) => f(...a)
|
|
@@ -481,7 +482,7 @@ var Teleport = class {
|
|
|
481
482
|
(0, import_log2.log)("open extension", {
|
|
482
483
|
extensionName
|
|
483
484
|
}, {
|
|
484
|
-
file: "
|
|
485
|
+
file: "teleport.ts",
|
|
485
486
|
line: 159,
|
|
486
487
|
scope: this,
|
|
487
488
|
callSite: (f, a) => f(...a)
|
|
@@ -509,7 +510,7 @@ var Teleport = class {
|
|
|
509
510
|
(0, import_log2.log)("extension opened", {
|
|
510
511
|
extensionName
|
|
511
512
|
}, {
|
|
512
|
-
file: "
|
|
513
|
+
file: "teleport.ts",
|
|
513
514
|
line: 182,
|
|
514
515
|
scope: this,
|
|
515
516
|
callSite: (f, a) => f(...a)
|
|
@@ -594,7 +595,7 @@ var TestExtension = class {
|
|
|
594
595
|
localPeerId: context.localPeerId,
|
|
595
596
|
remotePeerId: context.remotePeerId
|
|
596
597
|
}, {
|
|
597
|
-
file: "
|
|
598
|
+
file: "test-extension.ts",
|
|
598
599
|
line: 33,
|
|
599
600
|
scope: this,
|
|
600
601
|
callSite: (f, a) => f(...a)
|
|
@@ -632,7 +633,7 @@ var TestExtension = class {
|
|
|
632
633
|
(0, import_log3.log)("onClose", {
|
|
633
634
|
err
|
|
634
635
|
}, {
|
|
635
|
-
file: "
|
|
636
|
+
file: "test-extension.ts",
|
|
636
637
|
line: 67,
|
|
637
638
|
scope: this,
|
|
638
639
|
callSite: (f, a) => f(...a)
|
|
@@ -651,12 +652,73 @@ var TestExtension = class {
|
|
|
651
652
|
(0, import_node_assert4.default)(res.data === "test");
|
|
652
653
|
}
|
|
653
654
|
};
|
|
655
|
+
|
|
656
|
+
// packages/core/mesh/teleport/src/rpc-extension.ts
|
|
657
|
+
var import_node_assert5 = __toESM(require("node:assert"));
|
|
658
|
+
var import_async4 = require("@dxos/async");
|
|
659
|
+
var import_rpc3 = require("@dxos/rpc");
|
|
660
|
+
var __decorate2 = function(decorators, target, key, desc) {
|
|
661
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
662
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
663
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
664
|
+
else
|
|
665
|
+
for (var i = decorators.length - 1; i >= 0; i--)
|
|
666
|
+
if (d = decorators[i])
|
|
667
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
668
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
669
|
+
};
|
|
670
|
+
var RpcExtension = class {
|
|
671
|
+
constructor(_params) {
|
|
672
|
+
this._params = _params;
|
|
673
|
+
}
|
|
674
|
+
get initiator() {
|
|
675
|
+
return this._extensionContext.initiator;
|
|
676
|
+
}
|
|
677
|
+
get localPeerId() {
|
|
678
|
+
return this._extensionContext.localPeerId;
|
|
679
|
+
}
|
|
680
|
+
get remotePeerId() {
|
|
681
|
+
return this._extensionContext.remotePeerId;
|
|
682
|
+
}
|
|
683
|
+
get rpc() {
|
|
684
|
+
(0, import_node_assert5.default)(this._rpc);
|
|
685
|
+
return this._rpc.rpc;
|
|
686
|
+
}
|
|
687
|
+
async onOpen(context) {
|
|
688
|
+
this._extensionContext = context;
|
|
689
|
+
const handlers = await this.getHandlers();
|
|
690
|
+
const port = context.createPort("rpc", {
|
|
691
|
+
contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
|
|
692
|
+
});
|
|
693
|
+
this._rpc = (0, import_rpc3.createProtoRpcPeer)({
|
|
694
|
+
...this._params,
|
|
695
|
+
handlers,
|
|
696
|
+
port
|
|
697
|
+
});
|
|
698
|
+
await this._rpc.open();
|
|
699
|
+
}
|
|
700
|
+
async onClose(err) {
|
|
701
|
+
var _a;
|
|
702
|
+
await ((_a = this._rpc) == null ? void 0 : _a.close());
|
|
703
|
+
}
|
|
704
|
+
close() {
|
|
705
|
+
this._extensionContext.close();
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
__decorate2([
|
|
709
|
+
import_async4.synchronized
|
|
710
|
+
], RpcExtension.prototype, "onOpen", null);
|
|
711
|
+
__decorate2([
|
|
712
|
+
import_async4.synchronized
|
|
713
|
+
], RpcExtension.prototype, "onClose", null);
|
|
654
714
|
// Annotate the CommonJS export names for ESM import in node:
|
|
655
715
|
0 && (module.exports = {
|
|
656
716
|
Framer,
|
|
657
717
|
Muxer,
|
|
718
|
+
RpcExtension,
|
|
658
719
|
Teleport,
|
|
659
720
|
TestExtension,
|
|
660
721
|
decodeFrame,
|
|
661
722
|
encodeFrame
|
|
662
723
|
});
|
|
724
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/index.ts", "../../../src/muxing/framer.ts", "../../../src/muxing/muxer.ts", "../../../src/teleport.ts", "../../../src/testing/test-extension.ts", "../../../src/rpc-extension.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nexport * from './muxing';\nexport * from './teleport';\nexport * from './testing/test-extension';\nexport * from './rpc-extension';\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\nimport { Duplex } from 'node:stream';\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 assert(!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 assert(!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 assert from 'node:assert';\nimport { Duplex } from 'node:stream';\n\nimport { Event } from '@dxos/async';\nimport { failUndefined } from '@dxos/debug';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\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\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 constructor() {\n this._framer.port.subscribe((msg) => {\n this._handleCommand(codec.decode(msg));\n });\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 assert(!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 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 assert(!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 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 assert(!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 }\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 };\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 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\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\ntype CreateChannelInternalParams = {\n tag: string;\n contentType?: string;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\nimport { Duplex } from 'node:stream';\n\nimport { asyncTimeout, scheduleTaskInterval, runInContextAsync, synchronized, scheduleTask } 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 } from '@dxos/protocols';\nimport { ControlService } from '@dxos/protocols/proto/dxos/mesh/teleport/control';\nimport { createProtoRpcPeer, ProtoRpcPeer, RpcClosedError } 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: 3000,\n heartbeatTimeout: 3000\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 assert(typeof initiator === 'boolean');\n assert(PublicKey.isPublicKey(localPeerId));\n assert(PublicKey.isPublicKey(remotePeerId));\n assert(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 assert(!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 /**\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 assert(!extensionName.includes('/'), 'Invalid extension name');\n assert(!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 assert(!channelName.includes('/'), 'Invalid channel name');\n return this._muxer.createPort(`${extensionName}/${channelName}`, opts);\n },\n createStream: (channelName: string, opts?: CreateChannelOpts) => {\n assert(!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};\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 public readonly onTimeout = new Callback<() => 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; messageType=\"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.onTimeout.call();\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 assert from 'node:assert';\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() {\n await this.open.wait({ timeout: 500 });\n const res = await asyncTimeout(this._rpc.rpc.TestService.testCall({ data: 'test' }), 500);\n assert(res.data === 'test');\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\n\nimport { synchronized } from '@dxos/async';\nimport { createProtoRpcPeer, ProtoRpcPeer, ProtoRpcPeerOptions } from '@dxos/rpc';\n\nimport { ExtensionContext, TeleportExtension } from './teleport';\n\nexport abstract class RpcExtension<Client, Server> implements TeleportExtension {\n private _extensionContext!: ExtensionContext;\n private _rpc?: ProtoRpcPeer<Client>;\n\n constructor(private readonly _params: 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 assert(this._rpc);\n return this._rpc.rpc;\n }\n\n protected abstract getHandlers(): Promise<Server>;\n\n @synchronized\n async onOpen(context: ExtensionContext): Promise<void> {\n this._extensionContext = context;\n\n const handlers = await this.getHandlers();\n\n const port = context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"'\n });\n this._rpc = createProtoRpcPeer({\n ...this._params,\n handlers,\n port\n });\n\n await this._rpc.open();\n }\n\n @synchronized\n async onClose(err?: Error | undefined): Promise<void> {\n await this._rpc?.close();\n }\n\n close() {\n this._extensionContext.close();\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Framer", "_stream", "Duplex", "objectMode", "read", "write", "chunk", "encoding", "callback", "assert", "_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", "import_node_assert", "import_node_stream", "codec", "schema", "getCodecForType", "Muxer", "constructor", "_framer", "Framer", "stream", "_channelsByLocalId", "Map", "_channelsByTag", "_nextId", "_destroyed", "_destroying", "close", "Event", "port", "subscribe", "msg", "_handleCommand", "decode", "createStream", "tag", "opts", "channel", "_getOrCreateStream", "contentType", "assert", "push", "Duplex", "write", "data", "encoding", "callback", "_sendData", "read", "destroy", "err", "_sendCommand", "openChannel", "id", "createPort", "inboundBuffer", "send", "cb", "error", "message", "_dispose", "values", "emit", "clear", "cmd", "log", "warn", "remoteId", "buffer", "channelId", "get", "failUndefined", "Promise", "resolve", "encode", "catch", "params", "set", "import_node_assert", "import_async", "import_debug", "import_log", "import_protocols", "Teleport", "constructor", "initiator", "localPeerId", "remotePeerId", "_ctx", "Context", "onError", "err", "destroy", "catch", "log", "error", "_muxer", "Muxer", "_control", "ControlExtension", "heartbeatInterval", "heartbeatTimeout", "_extensions", "Map", "_remoteExtensions", "Set", "_open", "assert", "PublicKey", "isPublicKey", "onExtensionRegistered", "set", "name", "has", "add", "_openExtension", "stream", "on", "open", "_setExtension", "close", "disposed", "dispose", "extension", "values", "onClose", "addExtension", "Error", "scheduleTask", "registerExtension", "RpcClosedError", "extensionName", "includes", "get", "failUndefined", "context", "createPort", "channelName", "opts", "createStream", "runInContextAsync", "onOpen", "synchronized", "_extensionContext", "Callback", "onTimeout", "extensionContext", "_rpc", "createProtoRpcPeer", "requested", "Control", "schema", "getService", "exposed", "handlers", "request", "call", "heartbeat", "port", "contentType", "scheduleTaskInterval", "asyncTimeout", "rpc", "import_node_assert", "import_async", "import_log", "import_protocols", "import_rpc", "TestExtension", "constructor", "callbacks", "open", "Trigger", "closed", "remotePeerId", "extensionContext", "onOpen", "context", "log", "localPeerId", "_rpc", "createProtoRpcPeer", "port", "createPort", "contentType", "requested", "TestService", "schema", "getService", "exposed", "handlers", "voidCall", "request", "testCall", "data", "timeout", "wake", "onClose", "err", "close", "test", "wait", "res", "asyncTimeout", "rpc", "assert", "import_node_assert", "import_async", "import_rpc", "__decorate", "RpcExtension", "constructor", "_params", "initiator", "_extensionContext", "localPeerId", "remotePeerId", "rpc", "assert", "_rpc", "onOpen", "context", "handlers", "getHandlers", "port", "createPort", "contentType", "createProtoRpcPeer", "open", "onClose", "err", "close", "synchronized"]
|
|
7
|
+
}
|
package/dist/lib/node/meta.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"packages/core/mesh/teleport/src/muxing/framer.ts":{"bytes":
|
|
1
|
+
{"inputs":{"packages/core/mesh/teleport/src/muxing/framer.ts":{"bytes":12785,"imports":[]},"packages/core/mesh/teleport/src/muxing/muxer.ts":{"bytes":25338,"imports":[{"path":"packages/core/mesh/teleport/src/muxing/framer.ts","kind":"import-statement"}]},"packages/core/mesh/teleport/src/muxing/rpc-port.ts":{"bytes":824,"imports":[]},"packages/core/mesh/teleport/src/muxing/index.ts":{"bytes":539,"imports":[{"path":"packages/core/mesh/teleport/src/muxing/framer.ts","kind":"import-statement"},{"path":"packages/core/mesh/teleport/src/muxing/muxer.ts","kind":"import-statement"},{"path":"packages/core/mesh/teleport/src/muxing/rpc-port.ts","kind":"import-statement"}]},"packages/core/mesh/teleport/src/teleport.ts":{"bytes":27441,"imports":[{"path":"packages/core/mesh/teleport/src/muxing/index.ts","kind":"import-statement"}]},"packages/core/mesh/teleport/src/testing/test-extension.ts":{"bytes":7935,"imports":[]},"packages/core/mesh/teleport/src/rpc-extension.ts":{"bytes":5596,"imports":[]},"packages/core/mesh/teleport/src/index.ts":{"bytes":685,"imports":[{"path":"packages/core/mesh/teleport/src/muxing/index.ts","kind":"import-statement"},{"path":"packages/core/mesh/teleport/src/teleport.ts","kind":"import-statement"},{"path":"packages/core/mesh/teleport/src/testing/test-extension.ts","kind":"import-statement"},{"path":"packages/core/mesh/teleport/src/rpc-extension.ts","kind":"import-statement"}]},"packages/core/mesh/teleport/src/testing/test-builder.ts":{"bytes":7379,"imports":[{"path":"packages/core/mesh/teleport/src/teleport.ts","kind":"import-statement"}]},"packages/core/mesh/teleport/src/testing/index.ts":{"bytes":494,"imports":[{"path":"packages/core/mesh/teleport/src/testing/test-builder.ts","kind":"import-statement"},{"path":"packages/core/mesh/teleport/src/testing/test-extension.ts","kind":"import-statement"}]}},"outputs":{"packages/core/mesh/teleport/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":39018},"packages/core/mesh/teleport/dist/lib/node/index.cjs":{"imports":[],"exports":[],"entryPoint":"packages/core/mesh/teleport/src/index.ts","inputs":{"packages/core/mesh/teleport/src/index.ts":{"bytesInOutput":309},"packages/core/mesh/teleport/src/muxing/framer.ts":{"bytesInOutput":2651},"packages/core/mesh/teleport/src/muxing/index.ts":{"bytesInOutput":0},"packages/core/mesh/teleport/src/muxing/muxer.ts":{"bytesInOutput":5291},"packages/core/mesh/teleport/src/teleport.ts":{"bytesInOutput":7629},"packages/core/mesh/teleport/src/testing/test-extension.ts":{"bytesInOutput":2311},"packages/core/mesh/teleport/src/rpc-extension.ts":{"bytesInOutput":1807}},"bytes":21640},"packages/core/mesh/teleport/dist/lib/node/testing/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":39919},"packages/core/mesh/teleport/dist/lib/node/testing/index.cjs":{"imports":[],"exports":[],"entryPoint":"packages/core/mesh/teleport/src/testing/index.ts","inputs":{"packages/core/mesh/teleport/src/testing/index.ts":{"bytesInOutput":205},"packages/core/mesh/teleport/src/testing/test-builder.ts":{"bytesInOutput":1856},"packages/core/mesh/teleport/src/teleport.ts":{"bytesInOutput":7629},"packages/core/mesh/teleport/src/muxing/framer.ts":{"bytesInOutput":2651},"packages/core/mesh/teleport/src/muxing/index.ts":{"bytesInOutput":0},"packages/core/mesh/teleport/src/muxing/muxer.ts":{"bytesInOutput":5291},"packages/core/mesh/teleport/src/testing/test-extension.ts":{"bytesInOutput":2311}},"bytes":21658}}}
|
|
@@ -265,14 +265,14 @@ var Muxer = class {
|
|
|
265
265
|
(0, import_log.log)("Received command", {
|
|
266
266
|
cmd
|
|
267
267
|
}, {
|
|
268
|
-
file: "
|
|
268
|
+
file: "muxer.ts",
|
|
269
269
|
line: 194,
|
|
270
270
|
scope: this,
|
|
271
271
|
callSite: (f, a) => f(...a)
|
|
272
272
|
});
|
|
273
273
|
if (this._destroyed || this._destroying) {
|
|
274
274
|
import_log.log.warn("Received command after destroy", {}, {
|
|
275
|
-
file: "
|
|
275
|
+
file: "muxer.ts",
|
|
276
276
|
line: 197,
|
|
277
277
|
scope: this,
|
|
278
278
|
callSite: (f, a) => f(...a)
|
|
@@ -300,7 +300,7 @@ var Muxer = class {
|
|
|
300
300
|
import_log.log.warn("Received data for channel before it was opened", {
|
|
301
301
|
tag: stream.tag
|
|
302
302
|
}, {
|
|
303
|
-
file: "
|
|
303
|
+
file: "muxer.ts",
|
|
304
304
|
line: 221,
|
|
305
305
|
scope: this,
|
|
306
306
|
callSite: (f, a) => f(...a)
|
|
@@ -365,7 +365,7 @@ var Teleport = class {
|
|
|
365
365
|
onError: (err) => {
|
|
366
366
|
void this.destroy(err).catch(() => {
|
|
367
367
|
import_log2.log.error("Error during destroy", err, {
|
|
368
|
-
file: "
|
|
368
|
+
file: "teleport.ts",
|
|
369
369
|
line: 34,
|
|
370
370
|
scope: this,
|
|
371
371
|
callSite: (f, a) => f(...a)
|
|
@@ -392,7 +392,7 @@ var Teleport = class {
|
|
|
392
392
|
(0, import_log2.log)("remote extension", {
|
|
393
393
|
name
|
|
394
394
|
}, {
|
|
395
|
-
file: "
|
|
395
|
+
file: "teleport.ts",
|
|
396
396
|
line: 61,
|
|
397
397
|
scope: this,
|
|
398
398
|
callSite: (f, a) => f(...a)
|
|
@@ -437,7 +437,7 @@ var Teleport = class {
|
|
|
437
437
|
await extension.onClose(err);
|
|
438
438
|
} catch (err1) {
|
|
439
439
|
import_log2.log.catch(err1, {}, {
|
|
440
|
-
file: "
|
|
440
|
+
file: "teleport.ts",
|
|
441
441
|
line: 117,
|
|
442
442
|
scope: this,
|
|
443
443
|
callSite: (f, a) => f(...a)
|
|
@@ -453,7 +453,7 @@ var Teleport = class {
|
|
|
453
453
|
(0, import_log2.log)("addExtension", {
|
|
454
454
|
name
|
|
455
455
|
}, {
|
|
456
|
-
file: "
|
|
456
|
+
file: "teleport.ts",
|
|
457
457
|
line: 129,
|
|
458
458
|
scope: this,
|
|
459
459
|
callSite: (f, a) => f(...a)
|
|
@@ -485,7 +485,7 @@ var Teleport = class {
|
|
|
485
485
|
(0, import_log2.log)("open extension", {
|
|
486
486
|
extensionName
|
|
487
487
|
}, {
|
|
488
|
-
file: "
|
|
488
|
+
file: "teleport.ts",
|
|
489
489
|
line: 159,
|
|
490
490
|
scope: this,
|
|
491
491
|
callSite: (f, a) => f(...a)
|
|
@@ -513,7 +513,7 @@ var Teleport = class {
|
|
|
513
513
|
(0, import_log2.log)("extension opened", {
|
|
514
514
|
extensionName
|
|
515
515
|
}, {
|
|
516
|
-
file: "
|
|
516
|
+
file: "teleport.ts",
|
|
517
517
|
line: 182,
|
|
518
518
|
scope: this,
|
|
519
519
|
callSite: (f, a) => f(...a)
|
|
@@ -634,7 +634,7 @@ var TestPeer = class {
|
|
|
634
634
|
(0, import_node_stream3.pipeline)(this.teleport.stream, peer.teleport.stream, (err) => {
|
|
635
635
|
if (err && err.code !== "ERR_STREAM_PREMATURE_CLOSE") {
|
|
636
636
|
import_log3.log.catch(err, {}, {
|
|
637
|
-
file: "
|
|
637
|
+
file: "test-builder.ts",
|
|
638
638
|
line: 67,
|
|
639
639
|
scope: this,
|
|
640
640
|
callSite: (f, a) => f(...a)
|
|
@@ -670,7 +670,7 @@ var TestExtension = class {
|
|
|
670
670
|
localPeerId: context.localPeerId,
|
|
671
671
|
remotePeerId: context.remotePeerId
|
|
672
672
|
}, {
|
|
673
|
-
file: "
|
|
673
|
+
file: "test-extension.ts",
|
|
674
674
|
line: 33,
|
|
675
675
|
scope: this,
|
|
676
676
|
callSite: (f, a) => f(...a)
|
|
@@ -708,7 +708,7 @@ var TestExtension = class {
|
|
|
708
708
|
(0, import_log4.log)("onClose", {
|
|
709
709
|
err
|
|
710
710
|
}, {
|
|
711
|
-
file: "
|
|
711
|
+
file: "test-extension.ts",
|
|
712
712
|
line: 67,
|
|
713
713
|
scope: this,
|
|
714
714
|
callSite: (f, a) => f(...a)
|
|
@@ -733,3 +733,4 @@ var TestExtension = class {
|
|
|
733
733
|
TestExtension,
|
|
734
734
|
TestPeer
|
|
735
735
|
});
|
|
736
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/testing/index.ts", "../../../../src/testing/test-builder.ts", "../../../../src/teleport.ts", "../../../../src/muxing/framer.ts", "../../../../src/muxing/muxer.ts", "../../../../src/testing/test-extension.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nexport * from './test-builder';\nexport * from './test-extension';\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { pipeline } from 'node:stream';\n\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\n\nimport { Teleport } from '../teleport';\n\nexport class TestBuilder {\n private readonly _peers = new Array<TestPeer>();\n\n createPeer(peerId?: PublicKey): TestPeer {\n const peer = new TestPeer(peerId);\n this._peers.push(peer);\n return peer;\n }\n\n async destroy() {\n await Promise.all(this._peers.map((agent) => agent.destroy()));\n }\n\n /**\n * Simulates two peers connected via P2P network.\n */\n async createPipedPeers({ peerId1, peerId2 }: { peerId1?: PublicKey; peerId2?: PublicKey } = {}) {\n const peer1 = this.createPeer(peerId1);\n const peer2 = this.createPeer(peerId2);\n\n peer1.initializeTeleport({ initiator: true, remotePeerId: peer2.peerId });\n peer2.initializeTeleport({ initiator: false, remotePeerId: peer1.peerId });\n\n peer1.pipeline(peer2);\n peer2.pipeline(peer1);\n\n await Promise.all([peer1.teleport!.open(), peer2.teleport!.open()]);\n\n return { peer1, peer2 };\n }\n}\n\nexport class TestPeer {\n public teleport?: Teleport;\n\n constructor(public readonly peerId: PublicKey = PublicKey.random()) {}\n\n initializeTeleport({ initiator, remotePeerId }: { initiator: boolean; remotePeerId: PublicKey }) {\n if (this.teleport) {\n return this;\n }\n this.teleport = new Teleport({\n initiator,\n localPeerId: this.peerId,\n remotePeerId\n });\n return this;\n }\n\n pipeline(peer: TestPeer) {\n if (!this.teleport || !peer.teleport) {\n throw new Error('Teleport not initialized');\n }\n pipeline(this.teleport.stream, peer.teleport.stream, (err) => {\n if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') {\n log.catch(err);\n }\n });\n }\n\n async destroy() {\n await this.teleport?.destroy();\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\nimport { Duplex } from 'node:stream';\n\nimport { asyncTimeout, scheduleTaskInterval, runInContextAsync, synchronized, scheduleTask } 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 } from '@dxos/protocols';\nimport { ControlService } from '@dxos/protocols/proto/dxos/mesh/teleport/control';\nimport { createProtoRpcPeer, ProtoRpcPeer, RpcClosedError } 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: 3000,\n heartbeatTimeout: 3000\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 assert(typeof initiator === 'boolean');\n assert(PublicKey.isPublicKey(localPeerId));\n assert(PublicKey.isPublicKey(remotePeerId));\n assert(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 assert(!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 /**\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 assert(!extensionName.includes('/'), 'Invalid extension name');\n assert(!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 assert(!channelName.includes('/'), 'Invalid channel name');\n return this._muxer.createPort(`${extensionName}/${channelName}`, opts);\n },\n createStream: (channelName: string, opts?: CreateChannelOpts) => {\n assert(!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};\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 public readonly onTimeout = new Callback<() => 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; messageType=\"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.onTimeout.call();\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 assert from 'node:assert';\nimport { Duplex } from 'node:stream';\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 assert(!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 assert(!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 assert from 'node:assert';\nimport { Duplex } from 'node:stream';\n\nimport { Event } from '@dxos/async';\nimport { failUndefined } from '@dxos/debug';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\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\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 constructor() {\n this._framer.port.subscribe((msg) => {\n this._handleCommand(codec.decode(msg));\n });\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 assert(!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 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 assert(!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 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 assert(!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 }\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 };\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 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\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\ntype CreateChannelInternalParams = {\n tag: string;\n contentType?: string;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport assert from 'node:assert';\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() {\n await this.open.wait({ timeout: 500 });\n const res = await asyncTimeout(this._rpc.rpc.TestService.testCall({ data: 'test' }), 500);\n assert(res.data === 'test');\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_node_stream", "import_keys", "import_log", "import_node_assert", "import_async", "import_debug", "import_log", "import_protocols", "Framer", "_stream", "Duplex", "objectMode", "read", "write", "chunk", "encoding", "callback", "assert", "_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", "import_node_assert", "import_node_stream", "codec", "schema", "getCodecForType", "Muxer", "constructor", "_framer", "Framer", "stream", "_channelsByLocalId", "Map", "_channelsByTag", "_nextId", "_destroyed", "_destroying", "close", "Event", "port", "subscribe", "msg", "_handleCommand", "decode", "createStream", "tag", "opts", "channel", "_getOrCreateStream", "contentType", "assert", "push", "Duplex", "write", "data", "encoding", "callback", "_sendData", "read", "destroy", "err", "_sendCommand", "openChannel", "id", "createPort", "inboundBuffer", "send", "cb", "error", "message", "_dispose", "values", "emit", "clear", "cmd", "log", "warn", "remoteId", "buffer", "channelId", "get", "failUndefined", "Promise", "resolve", "encode", "catch", "params", "set", "Teleport", "constructor", "initiator", "localPeerId", "remotePeerId", "_ctx", "Context", "onError", "err", "destroy", "catch", "log", "error", "_muxer", "Muxer", "_control", "ControlExtension", "heartbeatInterval", "heartbeatTimeout", "_extensions", "Map", "_remoteExtensions", "Set", "_open", "assert", "PublicKey", "isPublicKey", "onExtensionRegistered", "set", "name", "has", "add", "_openExtension", "stream", "on", "open", "_setExtension", "close", "disposed", "dispose", "extension", "values", "onClose", "addExtension", "Error", "scheduleTask", "registerExtension", "RpcClosedError", "extensionName", "includes", "get", "failUndefined", "context", "createPort", "channelName", "opts", "createStream", "runInContextAsync", "onOpen", "synchronized", "_extensionContext", "Callback", "onTimeout", "extensionContext", "_rpc", "createProtoRpcPeer", "requested", "Control", "schema", "getService", "exposed", "handlers", "request", "call", "heartbeat", "port", "contentType", "scheduleTaskInterval", "asyncTimeout", "rpc", "TestBuilder", "_peers", "Array", "createPeer", "peerId", "peer", "TestPeer", "push", "destroy", "Promise", "all", "map", "agent", "createPipedPeers", "peerId1", "peerId2", "peer1", "peer2", "initializeTeleport", "initiator", "remotePeerId", "pipeline", "teleport", "open", "constructor", "PublicKey", "random", "Teleport", "localPeerId", "Error", "stream", "err", "code", "log", "catch", "import_node_assert", "import_async", "import_log", "import_protocols", "import_rpc", "TestExtension", "constructor", "callbacks", "open", "Trigger", "closed", "remotePeerId", "extensionContext", "onOpen", "context", "log", "localPeerId", "_rpc", "createProtoRpcPeer", "port", "createPort", "contentType", "requested", "TestService", "schema", "getService", "exposed", "handlers", "voidCall", "request", "testCall", "data", "timeout", "wake", "onClose", "err", "close", "test", "wait", "res", "asyncTimeout", "rpc", "assert"]
|
|
7
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ProtoRpcPeerOptions } from '@dxos/rpc';
|
|
2
|
+
import { ExtensionContext, TeleportExtension } from './teleport';
|
|
3
|
+
export declare abstract class RpcExtension<Client, Server> implements TeleportExtension {
|
|
4
|
+
private readonly _params;
|
|
5
|
+
private _extensionContext;
|
|
6
|
+
private _rpc?;
|
|
7
|
+
constructor(_params: Omit<ProtoRpcPeerOptions<Client, Server>, 'port' | 'handlers'>);
|
|
8
|
+
get initiator(): boolean;
|
|
9
|
+
get localPeerId(): import("@dxos/keys").PublicKey;
|
|
10
|
+
get remotePeerId(): import("@dxos/keys").PublicKey;
|
|
11
|
+
get rpc(): Client;
|
|
12
|
+
protected abstract getHandlers(): Promise<Server>;
|
|
13
|
+
onOpen(context: ExtensionContext): Promise<void>;
|
|
14
|
+
onClose(err?: Error | undefined): Promise<void>;
|
|
15
|
+
close(): void;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=rpc-extension.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc-extension.d.ts","sourceRoot":"","sources":["../../../src/rpc-extension.ts"],"names":[],"mappings":"AAOA,OAAO,EAAoC,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAElF,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEjE,8BAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,CAAE,YAAW,iBAAiB;IAIjE,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,IAAI,CAAC,CAAuB;gBAEP,OAAO,EAAE,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAEpG,IAAI,SAAS,YAEZ;IAED,IAAI,WAAW,mCAEd;IAED,IAAI,YAAY,mCAEf;IAED,IAAI,GAAG,IAAI,MAAM,CAGhB;IAED,SAAS,CAAC,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAG3C,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBhD,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,KAAK;CAGN"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/teleport",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "Stream muxer.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -22,21 +22,21 @@
|
|
|
22
22
|
"debug": "^4.3.3",
|
|
23
23
|
"randombytes": "^2.1.0",
|
|
24
24
|
"varint": "6.0.0",
|
|
25
|
-
"@dxos/context": "0.1.
|
|
26
|
-
"@dxos/debug": "0.1.
|
|
27
|
-
"@dxos/keys": "0.1.
|
|
28
|
-
"@dxos/log": "0.1.
|
|
29
|
-
"@dxos/node-std": "0.1.
|
|
30
|
-
"@dxos/protocols": "0.1.
|
|
31
|
-
"@dxos/rpc": "0.1.
|
|
32
|
-
"@dxos/util": "0.1.
|
|
25
|
+
"@dxos/context": "0.1.19",
|
|
26
|
+
"@dxos/debug": "0.1.19",
|
|
27
|
+
"@dxos/keys": "0.1.19",
|
|
28
|
+
"@dxos/log": "0.1.19",
|
|
29
|
+
"@dxos/node-std": "0.1.19",
|
|
30
|
+
"@dxos/protocols": "0.1.19",
|
|
31
|
+
"@dxos/rpc": "0.1.19",
|
|
32
|
+
"@dxos/util": "0.1.19"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/randombytes": "^2.0.0",
|
|
36
36
|
"@types/varint": "6.0.0",
|
|
37
37
|
"typescript": "^4.8.4",
|
|
38
38
|
"wait-for-expect": "^3.0.2",
|
|
39
|
-
"@dxos/async": "0.1.
|
|
39
|
+
"@dxos/async": "0.1.19"
|
|
40
40
|
},
|
|
41
41
|
"publishConfig": {
|
|
42
42
|
"access": "public"
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import assert from 'node:assert';
|
|
6
|
+
|
|
7
|
+
import { synchronized } from '@dxos/async';
|
|
8
|
+
import { createProtoRpcPeer, ProtoRpcPeer, ProtoRpcPeerOptions } from '@dxos/rpc';
|
|
9
|
+
|
|
10
|
+
import { ExtensionContext, TeleportExtension } from './teleport';
|
|
11
|
+
|
|
12
|
+
export abstract class RpcExtension<Client, Server> implements TeleportExtension {
|
|
13
|
+
private _extensionContext!: ExtensionContext;
|
|
14
|
+
private _rpc?: ProtoRpcPeer<Client>;
|
|
15
|
+
|
|
16
|
+
constructor(private readonly _params: Omit<ProtoRpcPeerOptions<Client, Server>, 'port' | 'handlers'>) {}
|
|
17
|
+
|
|
18
|
+
get initiator() {
|
|
19
|
+
return this._extensionContext.initiator;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get localPeerId() {
|
|
23
|
+
return this._extensionContext.localPeerId;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get remotePeerId() {
|
|
27
|
+
return this._extensionContext.remotePeerId;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get rpc(): Client {
|
|
31
|
+
assert(this._rpc);
|
|
32
|
+
return this._rpc.rpc;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
protected abstract getHandlers(): Promise<Server>;
|
|
36
|
+
|
|
37
|
+
@synchronized
|
|
38
|
+
async onOpen(context: ExtensionContext): Promise<void> {
|
|
39
|
+
this._extensionContext = context;
|
|
40
|
+
|
|
41
|
+
const handlers = await this.getHandlers();
|
|
42
|
+
|
|
43
|
+
const port = context.createPort('rpc', {
|
|
44
|
+
contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
|
|
45
|
+
});
|
|
46
|
+
this._rpc = createProtoRpcPeer({
|
|
47
|
+
...this._params,
|
|
48
|
+
handlers,
|
|
49
|
+
port
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
await this._rpc.open();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@synchronized
|
|
56
|
+
async onClose(err?: Error | undefined): Promise<void> {
|
|
57
|
+
await this._rpc?.close();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
close() {
|
|
61
|
+
this._extensionContext.close();
|
|
62
|
+
}
|
|
63
|
+
}
|