@dxos/teleport 0.1.53-next.e9dc2bc → 0.1.54-main.270ec56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/{chunk-EIJETGTE.mjs → chunk-7TGKNWZQ.mjs} +174 -55
- package/dist/lib/browser/chunk-7TGKNWZQ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +202 -4
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +1 -1
- package/dist/lib/node/index.cjs +371 -53
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +169 -50
- package/dist/lib/node/testing/index.cjs.map +4 -4
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/muxing/balancer.d.ts +23 -0
- package/dist/types/src/muxing/balancer.d.ts.map +1 -0
- package/dist/types/src/muxing/framer.d.ts +3 -0
- package/dist/types/src/muxing/framer.d.ts.map +1 -1
- package/dist/types/src/muxing/muxer.d.ts +4 -2
- package/dist/types/src/muxing/muxer.d.ts.map +1 -1
- package/dist/types/src/teleport.d.ts +2 -2
- package/dist/types/src/teleport.d.ts.map +1 -1
- package/dist/types/src/testing/test-extension-with-streams.d.ts +42 -0
- package/dist/types/src/testing/test-extension-with-streams.d.ts.map +1 -0
- package/package.json +11 -11
- package/src/index.ts +1 -0
- package/src/muxing/balancer.ts +106 -0
- package/src/muxing/framer.ts +20 -1
- package/src/muxing/muxer.test.ts +7 -7
- package/src/muxing/muxer.ts +95 -44
- package/src/rpc-extension.ts +1 -1
- package/src/teleport.ts +5 -5
- package/src/testing/test-extension-with-streams.ts +244 -0
- package/src/testing/test-extension.ts +4 -4
- package/dist/lib/browser/chunk-EIJETGTE.mjs.map +0 -7
|
@@ -6,6 +6,7 @@ import invariant from "tiny-invariant";
|
|
|
6
6
|
import * as varint from "varint";
|
|
7
7
|
var Framer = class {
|
|
8
8
|
constructor() {
|
|
9
|
+
this._responseQueue = [];
|
|
9
10
|
this._stream = new Duplex({
|
|
10
11
|
objectMode: false,
|
|
11
12
|
read: () => {
|
|
@@ -34,7 +35,14 @@ var Framer = class {
|
|
|
34
35
|
});
|
|
35
36
|
this.port = {
|
|
36
37
|
send: (message) => {
|
|
37
|
-
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
const canContinue = this._stream.push(encodeFrame(message));
|
|
40
|
+
if (!canContinue) {
|
|
41
|
+
this._responseQueue.push(resolve);
|
|
42
|
+
} else {
|
|
43
|
+
process.nextTick(resolve);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
38
46
|
},
|
|
39
47
|
subscribe: (callback) => {
|
|
40
48
|
var _a;
|
|
@@ -46,10 +54,16 @@ var Framer = class {
|
|
|
46
54
|
};
|
|
47
55
|
}
|
|
48
56
|
};
|
|
57
|
+
this.stream.on("drain", this._processResponseQueue.bind(this));
|
|
49
58
|
}
|
|
50
59
|
get stream() {
|
|
51
60
|
return this._stream;
|
|
52
61
|
}
|
|
62
|
+
_processResponseQueue() {
|
|
63
|
+
const responseQueue = this._responseQueue;
|
|
64
|
+
this._responseQueue = [];
|
|
65
|
+
responseQueue.forEach((cb) => cb());
|
|
66
|
+
}
|
|
53
67
|
/**
|
|
54
68
|
* Attempts to pop frames from the buffer and call the message callback.
|
|
55
69
|
*/
|
|
@@ -70,6 +84,7 @@ var Framer = class {
|
|
|
70
84
|
}
|
|
71
85
|
}
|
|
72
86
|
destroy() {
|
|
87
|
+
this._stream.removeAllListeners("drain");
|
|
73
88
|
this._stream.destroy();
|
|
74
89
|
}
|
|
75
90
|
};
|
|
@@ -104,17 +119,94 @@ var encodeFrame = (payload) => {
|
|
|
104
119
|
// packages/core/mesh/teleport/src/muxing/muxer.ts
|
|
105
120
|
import { Duplex as Duplex2 } from "@dxos/node-std/stream";
|
|
106
121
|
import invariant2 from "tiny-invariant";
|
|
107
|
-
import { Event,
|
|
122
|
+
import { scheduleTaskInterval, Event, Trigger } from "@dxos/async";
|
|
108
123
|
import { Context } from "@dxos/context";
|
|
109
124
|
import { failUndefined } from "@dxos/debug";
|
|
110
125
|
import { log } from "@dxos/log";
|
|
111
126
|
import { schema } from "@dxos/protocols";
|
|
127
|
+
|
|
128
|
+
// packages/core/mesh/teleport/src/muxing/balancer.ts
|
|
129
|
+
var Balancer = class {
|
|
130
|
+
constructor(_port, _sysChannelId) {
|
|
131
|
+
this._port = _port;
|
|
132
|
+
this._sysChannelId = _sysChannelId;
|
|
133
|
+
this._lastCallerIndex = 0;
|
|
134
|
+
this._channels = [];
|
|
135
|
+
this._calls = /* @__PURE__ */ new Map();
|
|
136
|
+
this._channels.push(_sysChannelId);
|
|
137
|
+
}
|
|
138
|
+
addChannel(channel) {
|
|
139
|
+
this._channels.push(channel);
|
|
140
|
+
}
|
|
141
|
+
pushChunk(msg, trigger, channelId) {
|
|
142
|
+
const noCalls = this._calls.size === 0;
|
|
143
|
+
if (!this._channels.includes(channelId)) {
|
|
144
|
+
throw new Error(`Unknown channel ${channelId}`);
|
|
145
|
+
}
|
|
146
|
+
if (!this._calls.has(channelId)) {
|
|
147
|
+
this._calls.set(channelId, []);
|
|
148
|
+
}
|
|
149
|
+
const channelCalls = this._calls.get(channelId);
|
|
150
|
+
channelCalls.push({
|
|
151
|
+
msg,
|
|
152
|
+
trigger
|
|
153
|
+
});
|
|
154
|
+
if (noCalls) {
|
|
155
|
+
process.nextTick(async () => {
|
|
156
|
+
await this._processCalls();
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
destroy() {
|
|
161
|
+
this._calls.clear();
|
|
162
|
+
}
|
|
163
|
+
_getNextCallerId() {
|
|
164
|
+
if (this._calls.has(this._sysChannelId)) {
|
|
165
|
+
return this._sysChannelId;
|
|
166
|
+
}
|
|
167
|
+
const index = this._lastCallerIndex;
|
|
168
|
+
this._lastCallerIndex = (this._lastCallerIndex + 1) % this._channels.length;
|
|
169
|
+
return this._channels[index];
|
|
170
|
+
}
|
|
171
|
+
_getNextCall() {
|
|
172
|
+
let call;
|
|
173
|
+
while (!call) {
|
|
174
|
+
const channelId = this._getNextCallerId();
|
|
175
|
+
const channelCalls = this._calls.get(channelId);
|
|
176
|
+
if (!channelCalls) {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
call = channelCalls.shift();
|
|
180
|
+
if (channelCalls.length === 0) {
|
|
181
|
+
this._calls.delete(channelId);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return call;
|
|
185
|
+
}
|
|
186
|
+
async _processCalls() {
|
|
187
|
+
if (this._calls.size === 0) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const call = this._getNextCall();
|
|
191
|
+
try {
|
|
192
|
+
await this._port.send(call.msg);
|
|
193
|
+
call.trigger.wake();
|
|
194
|
+
} catch (err) {
|
|
195
|
+
call.trigger.throw(err);
|
|
196
|
+
}
|
|
197
|
+
await this._processCalls();
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// packages/core/mesh/teleport/src/muxing/muxer.ts
|
|
112
202
|
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/muxer.ts";
|
|
113
203
|
var Command = schema.getCodecForType("dxos.mesh.muxer.Command");
|
|
114
204
|
var STATS_INTERVAL = 1e3;
|
|
205
|
+
var SYSTEM_CHANNEL_ID = -1;
|
|
115
206
|
var Muxer = class {
|
|
116
207
|
constructor() {
|
|
117
208
|
this._framer = new Framer();
|
|
209
|
+
this._balancer = new Balancer(this._framer.port, SYSTEM_CHANNEL_ID);
|
|
118
210
|
this.stream = this._framer.stream;
|
|
119
211
|
this._channelsByLocalId = /* @__PURE__ */ new Map();
|
|
120
212
|
this._channelsByTag = /* @__PURE__ */ new Map();
|
|
@@ -124,8 +216,8 @@ var Muxer = class {
|
|
|
124
216
|
this.close = new Event();
|
|
125
217
|
this.statsUpdated = new Event();
|
|
126
218
|
this._ctx = new Context();
|
|
127
|
-
this._framer.port.subscribe((msg) => {
|
|
128
|
-
this._handleCommand(Command.decode(msg));
|
|
219
|
+
this._framer.port.subscribe(async (msg) => {
|
|
220
|
+
await this._handleCommand(Command.decode(msg));
|
|
129
221
|
});
|
|
130
222
|
scheduleTaskInterval(this._ctx, async () => this._emitStats(), STATS_INTERVAL);
|
|
131
223
|
}
|
|
@@ -135,7 +227,7 @@ var Muxer = class {
|
|
|
135
227
|
* The stream is immediately readable and writable.
|
|
136
228
|
* NOTE: The data will be buffered until the stream is opened remotely with the same tag (may cause a memory leak).
|
|
137
229
|
*/
|
|
138
|
-
createStream(tag, opts = {}) {
|
|
230
|
+
async createStream(tag, opts = {}) {
|
|
139
231
|
const channel = this._getOrCreateStream({
|
|
140
232
|
tag,
|
|
141
233
|
contentType: opts.contentType
|
|
@@ -143,8 +235,7 @@ var Muxer = class {
|
|
|
143
235
|
invariant2(!channel.push, `Channel already open: ${tag}`);
|
|
144
236
|
const stream = new Duplex2({
|
|
145
237
|
write: (data, encoding, callback) => {
|
|
146
|
-
this._sendData(channel, data);
|
|
147
|
-
callback();
|
|
238
|
+
this._sendData(channel, data).then(() => callback()).catch(callback);
|
|
148
239
|
},
|
|
149
240
|
read: () => {
|
|
150
241
|
}
|
|
@@ -156,13 +247,18 @@ var Muxer = class {
|
|
|
156
247
|
channel.destroy = (err) => {
|
|
157
248
|
stream.destroy(err);
|
|
158
249
|
};
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
250
|
+
try {
|
|
251
|
+
await this._sendCommand({
|
|
252
|
+
openChannel: {
|
|
253
|
+
id: channel.id,
|
|
254
|
+
tag: channel.tag,
|
|
255
|
+
contentType: channel.contentType
|
|
256
|
+
}
|
|
257
|
+
}, SYSTEM_CHANNEL_ID);
|
|
258
|
+
} catch (err) {
|
|
259
|
+
this._destroyChannel(channel, err);
|
|
260
|
+
throw err;
|
|
261
|
+
}
|
|
166
262
|
return stream;
|
|
167
263
|
}
|
|
168
264
|
/**
|
|
@@ -171,7 +267,7 @@ var Muxer = class {
|
|
|
171
267
|
* The port is immediately usable.
|
|
172
268
|
* NOTE: The data will be buffered until the stream is opened remotely with the same tag (may cause a memory leak).
|
|
173
269
|
*/
|
|
174
|
-
createPort(tag, opts = {}) {
|
|
270
|
+
async createPort(tag, opts = {}) {
|
|
175
271
|
const channel = this._getOrCreateStream({
|
|
176
272
|
tag,
|
|
177
273
|
contentType: opts.contentType
|
|
@@ -188,8 +284,8 @@ var Muxer = class {
|
|
|
188
284
|
}
|
|
189
285
|
};
|
|
190
286
|
const port = {
|
|
191
|
-
send: (data) => {
|
|
192
|
-
this._sendData(channel, data);
|
|
287
|
+
send: async (data) => {
|
|
288
|
+
await this._sendData(channel, data);
|
|
193
289
|
},
|
|
194
290
|
subscribe: (cb) => {
|
|
195
291
|
invariant2(!callback, "Only one subscriber is allowed");
|
|
@@ -200,13 +296,18 @@ var Muxer = class {
|
|
|
200
296
|
inboundBuffer = [];
|
|
201
297
|
}
|
|
202
298
|
};
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
299
|
+
try {
|
|
300
|
+
await this._sendCommand({
|
|
301
|
+
openChannel: {
|
|
302
|
+
id: channel.id,
|
|
303
|
+
tag: channel.tag,
|
|
304
|
+
contentType: channel.contentType
|
|
305
|
+
}
|
|
306
|
+
}, SYSTEM_CHANNEL_ID);
|
|
307
|
+
} catch (err) {
|
|
308
|
+
this._destroyChannel(channel, err);
|
|
309
|
+
throw err;
|
|
310
|
+
}
|
|
210
311
|
return port;
|
|
211
312
|
}
|
|
212
313
|
/**
|
|
@@ -217,12 +318,15 @@ var Muxer = class {
|
|
|
217
318
|
return;
|
|
218
319
|
}
|
|
219
320
|
this._destroying = true;
|
|
220
|
-
this._sendCommand({
|
|
321
|
+
Promise.resolve(this._sendCommand({
|
|
221
322
|
destroy: {
|
|
222
323
|
error: err == null ? void 0 : err.message
|
|
223
324
|
}
|
|
325
|
+
}, SYSTEM_CHANNEL_ID)).then(() => {
|
|
326
|
+
this._dispose();
|
|
327
|
+
}).catch((err2) => {
|
|
328
|
+
this._dispose(err2);
|
|
224
329
|
});
|
|
225
|
-
this._dispose();
|
|
226
330
|
void this._ctx.dispose();
|
|
227
331
|
}
|
|
228
332
|
_dispose(err) {
|
|
@@ -231,6 +335,7 @@ var Muxer = class {
|
|
|
231
335
|
return;
|
|
232
336
|
}
|
|
233
337
|
this._destroyed = true;
|
|
338
|
+
this._balancer.destroy();
|
|
234
339
|
this._framer.destroy();
|
|
235
340
|
for (const channel of this._channelsByTag.values()) {
|
|
236
341
|
(_a = channel.destroy) == null ? void 0 : _a.call(channel, err);
|
|
@@ -239,20 +344,22 @@ var Muxer = class {
|
|
|
239
344
|
this._channelsByLocalId.clear();
|
|
240
345
|
this._channelsByTag.clear();
|
|
241
346
|
}
|
|
242
|
-
_handleCommand(cmd) {
|
|
347
|
+
async _handleCommand(cmd) {
|
|
243
348
|
var _a;
|
|
244
349
|
log("Received command", {
|
|
245
350
|
cmd
|
|
246
351
|
}, {
|
|
247
352
|
F: __dxlog_file,
|
|
248
|
-
L:
|
|
353
|
+
L: 239,
|
|
249
354
|
S: this,
|
|
250
355
|
C: (f, a) => f(...a)
|
|
251
356
|
});
|
|
252
357
|
if (this._destroyed || this._destroying) {
|
|
253
|
-
log.warn("Received command after destroy",
|
|
358
|
+
log.warn("Received command after destroy", {
|
|
359
|
+
cmd
|
|
360
|
+
}, {
|
|
254
361
|
F: __dxlog_file,
|
|
255
|
-
L:
|
|
362
|
+
L: 242,
|
|
256
363
|
S: this,
|
|
257
364
|
C: (f, a) => f(...a)
|
|
258
365
|
});
|
|
@@ -265,12 +372,12 @@ var Muxer = class {
|
|
|
265
372
|
});
|
|
266
373
|
channel.remoteId = cmd.openChannel.id;
|
|
267
374
|
for (const data of channel.buffer) {
|
|
268
|
-
this._sendCommand({
|
|
375
|
+
await this._sendCommand({
|
|
269
376
|
data: {
|
|
270
377
|
channelId: channel.remoteId,
|
|
271
378
|
data
|
|
272
379
|
}
|
|
273
|
-
});
|
|
380
|
+
}, channel.id);
|
|
274
381
|
}
|
|
275
382
|
channel.buffer = [];
|
|
276
383
|
} else if (cmd.data) {
|
|
@@ -280,7 +387,7 @@ var Muxer = class {
|
|
|
280
387
|
tag: stream.tag
|
|
281
388
|
}, {
|
|
282
389
|
F: __dxlog_file,
|
|
283
|
-
L:
|
|
390
|
+
L: 269,
|
|
284
391
|
S: this,
|
|
285
392
|
C: (f, a) => f(...a)
|
|
286
393
|
});
|
|
@@ -291,10 +398,14 @@ var Muxer = class {
|
|
|
291
398
|
this._dispose();
|
|
292
399
|
}
|
|
293
400
|
}
|
|
294
|
-
_sendCommand(cmd) {
|
|
295
|
-
|
|
401
|
+
async _sendCommand(cmd, channelId = -1) {
|
|
402
|
+
try {
|
|
403
|
+
const trigger = new Trigger();
|
|
404
|
+
this._balancer.pushChunk(Command.encode(cmd), trigger, channelId);
|
|
405
|
+
await trigger.wait();
|
|
406
|
+
} catch (err) {
|
|
296
407
|
this.destroy(err);
|
|
297
|
-
}
|
|
408
|
+
}
|
|
298
409
|
}
|
|
299
410
|
_getOrCreateStream(params) {
|
|
300
411
|
let channel = this._channelsByTag.get(params.tag);
|
|
@@ -314,21 +425,29 @@ var Muxer = class {
|
|
|
314
425
|
};
|
|
315
426
|
this._channelsByTag.set(channel.tag, channel);
|
|
316
427
|
this._channelsByLocalId.set(channel.id, channel);
|
|
428
|
+
this._balancer.addChannel(channel.id);
|
|
317
429
|
}
|
|
318
430
|
return channel;
|
|
319
431
|
}
|
|
320
|
-
_sendData(channel, data) {
|
|
432
|
+
async _sendData(channel, data) {
|
|
321
433
|
channel.stats.bytesSent += data.length;
|
|
322
434
|
if (channel.remoteId === null) {
|
|
323
435
|
channel.buffer.push(data);
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
await this._sendCommand({
|
|
439
|
+
data: {
|
|
440
|
+
channelId: channel.remoteId,
|
|
441
|
+
data
|
|
442
|
+
}
|
|
443
|
+
}, channel.id);
|
|
444
|
+
}
|
|
445
|
+
_destroyChannel(channel, err) {
|
|
446
|
+
if (channel.destroy) {
|
|
447
|
+
channel.destroy(err);
|
|
331
448
|
}
|
|
449
|
+
this._channelsByLocalId.delete(channel.id);
|
|
450
|
+
this._channelsByTag.delete(channel.tag);
|
|
332
451
|
}
|
|
333
452
|
async _emitStats() {
|
|
334
453
|
if (this._destroyed || this._destroying) {
|
|
@@ -514,11 +633,11 @@ var Teleport = class {
|
|
|
514
633
|
initiator: this.initiator,
|
|
515
634
|
localPeerId: this.localPeerId,
|
|
516
635
|
remotePeerId: this.remotePeerId,
|
|
517
|
-
createPort: (channelName, opts) => {
|
|
636
|
+
createPort: async (channelName, opts) => {
|
|
518
637
|
invariant3(!channelName.includes("/"), "Invalid channel name");
|
|
519
638
|
return this._muxer.createPort(`${extensionName}/${channelName}`, opts);
|
|
520
639
|
},
|
|
521
|
-
createStream: (channelName, opts) => {
|
|
640
|
+
createStream: async (channelName, opts) => {
|
|
522
641
|
invariant3(!channelName.includes("/"), "Invalid channel name");
|
|
523
642
|
return this._muxer.createStream(`${extensionName}/${channelName}`, opts);
|
|
524
643
|
},
|
|
@@ -570,7 +689,7 @@ var ControlExtension = class {
|
|
|
570
689
|
}
|
|
571
690
|
}
|
|
572
691
|
},
|
|
573
|
-
port: extensionContext.createPort("rpc", {
|
|
692
|
+
port: await extensionContext.createPort("rpc", {
|
|
574
693
|
contentType: 'application/x-protobuf; messagType="dxos.rpc.Message"'
|
|
575
694
|
})
|
|
576
695
|
});
|
|
@@ -596,7 +715,7 @@ var ControlExtension = class {
|
|
|
596
715
|
|
|
597
716
|
// packages/core/mesh/teleport/src/testing/test-extension.ts
|
|
598
717
|
import invariant4 from "tiny-invariant";
|
|
599
|
-
import { asyncTimeout as asyncTimeout2, Trigger } from "@dxos/async";
|
|
718
|
+
import { asyncTimeout as asyncTimeout2, Trigger as Trigger2 } from "@dxos/async";
|
|
600
719
|
import { log as log3 } from "@dxos/log";
|
|
601
720
|
import { schema as schema3 } from "@dxos/protocols";
|
|
602
721
|
import { createProtoRpcPeer as createProtoRpcPeer2 } from "@dxos/rpc";
|
|
@@ -604,8 +723,8 @@ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src
|
|
|
604
723
|
var TestExtension = class {
|
|
605
724
|
constructor(callbacks = {}) {
|
|
606
725
|
this.callbacks = callbacks;
|
|
607
|
-
this.open = new
|
|
608
|
-
this.closed = new
|
|
726
|
+
this.open = new Trigger2();
|
|
727
|
+
this.closed = new Trigger2();
|
|
609
728
|
}
|
|
610
729
|
get remotePeerId() {
|
|
611
730
|
var _a;
|
|
@@ -624,7 +743,7 @@ var TestExtension = class {
|
|
|
624
743
|
});
|
|
625
744
|
this.extensionContext = context;
|
|
626
745
|
this._rpc = createProtoRpcPeer2({
|
|
627
|
-
port: context.createPort("rpc", {
|
|
746
|
+
port: await context.createPort("rpc", {
|
|
628
747
|
contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
|
|
629
748
|
}),
|
|
630
749
|
requested: {
|
|
@@ -644,7 +763,7 @@ var TestExtension = class {
|
|
|
644
763
|
}
|
|
645
764
|
}
|
|
646
765
|
},
|
|
647
|
-
timeout:
|
|
766
|
+
timeout: 2e3
|
|
648
767
|
});
|
|
649
768
|
await this._rpc.open();
|
|
650
769
|
await ((_b = (_a = this.callbacks).onOpen) == null ? void 0 : _b.call(_a));
|
|
@@ -666,11 +785,11 @@ var TestExtension = class {
|
|
|
666
785
|
}
|
|
667
786
|
async test(message = "test") {
|
|
668
787
|
await this.open.wait({
|
|
669
|
-
timeout:
|
|
788
|
+
timeout: 1500
|
|
670
789
|
});
|
|
671
790
|
const res = await asyncTimeout2(this._rpc.rpc.TestService.testCall({
|
|
672
791
|
data: message
|
|
673
|
-
}),
|
|
792
|
+
}), 1500);
|
|
674
793
|
invariant4(res.data === message);
|
|
675
794
|
}
|
|
676
795
|
/**
|
|
@@ -690,4 +809,4 @@ export {
|
|
|
690
809
|
Teleport,
|
|
691
810
|
TestExtension
|
|
692
811
|
};
|
|
693
|
-
//# sourceMappingURL=chunk-
|
|
812
|
+
//# sourceMappingURL=chunk-7TGKNWZQ.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/muxing/framer.ts", "../../../src/muxing/muxer.ts", "../../../src/muxing/balancer.ts", "../../../src/teleport.ts", "../../../src/testing/test-extension.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport { Duplex } from 'node:stream';\nimport invariant from 'tiny-invariant';\nimport * as varint from 'varint';\n\nimport { RpcPort } from './rpc-port';\n\n/**\n * Framer that turns a stream of binary messages into a framed RpcPort.\n *\n * Buffers are written prefixed by their length encoded as a varint.\n */\nexport class Framer {\n // private readonly _tagBuffer = Buffer.alloc(4)\n private _messageCb?: (msg: Uint8Array) => void;\n private _subscribeCb?: () => void;\n private _buffer?: Buffer; // The rest of the bytes from the previous write call.\n private _responseQueue: (() => void)[] = [];\n\n private readonly _stream = new Duplex({\n objectMode: false,\n read: () => {},\n write: (chunk, encoding, callback) => {\n invariant(!this._subscribeCb, 'Internal Framer bug. Concurrent writes detected.');\n\n if (this._buffer && this._buffer.length > 0) {\n this._buffer = Buffer.concat([this._buffer, chunk]);\n } else {\n this._buffer = chunk;\n }\n\n if (this._messageCb) {\n this._popFrames();\n callback();\n } else {\n this._subscribeCb = () => {\n // Schedule the processing of the chunk after the peer subscribes to the messages.\n this._popFrames();\n this._subscribeCb = undefined;\n callback();\n };\n }\n },\n });\n\n public readonly port: RpcPort = {\n send: (message) => {\n // log('write', { len: message.length, frame: Buffer.from(message).toString('hex') })\n return new Promise<void>((resolve) => {\n const canContinue = this._stream.push(encodeFrame(message));\n if (!canContinue) {\n this._responseQueue.push(resolve);\n } else {\n process.nextTick(resolve);\n }\n });\n },\n subscribe: (callback) => {\n invariant(!this._messageCb, 'Rpc port already has a message listener.');\n this._messageCb = callback;\n this._subscribeCb?.();\n return () => {\n this._messageCb = undefined;\n };\n },\n };\n\n get stream(): Duplex {\n return this._stream;\n }\n\n constructor() {\n this.stream.on('drain', this._processResponseQueue.bind(this));\n }\n\n private _processResponseQueue() {\n const responseQueue = this._responseQueue;\n this._responseQueue = [];\n responseQueue.forEach((cb) => cb());\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.removeAllListeners('drain');\n this._stream.destroy();\n }\n}\n\n/**\n * Attempts to read a frame from the input buffer.\n */\nexport const decodeFrame = (buffer: Buffer, offset: number): { payload: Buffer; bytesConsumed: number } | undefined => {\n try {\n const frameLength = varint.decode(buffer, offset);\n const tagLength = varint.decode.bytes;\n\n if (buffer.length < offset + tagLength + frameLength) {\n // Not enough bytes to read the frame.\n return undefined;\n }\n\n const payload = buffer.subarray(offset + tagLength, offset + tagLength + frameLength);\n\n return {\n payload,\n bytesConsumed: tagLength + frameLength,\n };\n } catch (err) {\n if (err instanceof RangeError) {\n // Not enough bytes to read the tag.\n return undefined;\n } else {\n throw err;\n }\n }\n};\n\nexport const encodeFrame = (payload: Uint8Array): Buffer => {\n const tagLength = varint.encodingLength(payload.length);\n const frame = Buffer.allocUnsafe(tagLength + payload.length);\n varint.encode(payload.length, frame);\n frame.set(payload, tagLength);\n return frame;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { Duplex } from 'node:stream';\nimport invariant from 'tiny-invariant';\n\nimport { scheduleTaskInterval, Event, Trigger } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\nimport { ConnectionInfo } from '@dxos/protocols/proto/dxos/devtools/swarm';\nimport { Command } from '@dxos/protocols/proto/dxos/mesh/muxer';\n\nimport { Balancer } from './balancer';\nimport { Framer } from './framer';\nimport { RpcPort } from './rpc-port';\n\nconst Command = schema.getCodecForType('dxos.mesh.muxer.Command');\n\nexport type CleanupCb = void | (() => void);\n\nexport type CreateChannelOpts = {\n /**\n * MIME type of the wire content.\n *\n * Examples:\n * - application/octet-stream\n * - application/x-protobuf; messageType=\"dxos.rpc.Message\"\n */\n contentType?: string;\n};\n\nconst STATS_INTERVAL = 1000;\n\nconst SYSTEM_CHANNEL_ID = -1;\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 private readonly _balancer = new Balancer(this._framer.port, SYSTEM_CHANNEL_ID);\n public readonly stream = this._framer.stream;\n\n private readonly _channelsByLocalId = new Map<number, Channel>();\n private readonly _channelsByTag = new Map<string, Channel>();\n\n private _nextId = 0;\n private _destroyed = false;\n private _destroying = false;\n\n public close = new Event<Error | undefined>();\n\n public statsUpdated = new Event<ConnectionInfo.StreamStats[]>();\n\n private readonly _ctx = new Context();\n\n constructor() {\n // Add a channel for control messages.\n this._framer.port.subscribe(async (msg) => {\n await this._handleCommand(Command.decode(msg));\n });\n\n scheduleTaskInterval(this._ctx, async () => this._emitStats(), STATS_INTERVAL);\n }\n\n /**\n * Creates a duplex Node.js-style stream.\n * The remote peer is expected to call `createStream` with the same tag.\n * The stream is immediately readable and writable.\n * NOTE: The data will be buffered until the stream is opened remotely with the same tag (may cause a memory leak).\n */\n async createStream(tag: string, opts: CreateChannelOpts = {}): Promise<Duplex> {\n const channel = this._getOrCreateStream({\n tag,\n contentType: opts.contentType,\n });\n invariant(!channel.push, `Channel already open: ${tag}`);\n\n const stream = new Duplex({\n write: (data, encoding, callback) => {\n this._sendData(channel, data)\n .then(() => callback())\n .catch(callback);\n // TODO(dmaretskyi): Should we error if sending data has errored?\n },\n read: () => {}, // No-op. We will push data when we receive it.\n });\n\n channel.push = (data) => {\n channel.stats.bytesReceived += data.length;\n stream.push(data);\n };\n channel.destroy = (err) => {\n // TODO(dmaretskyi): Call stream.end() instead?\n stream.destroy(err);\n };\n\n // NOTE: Make sure channel.push is set before sending the command.\n try {\n await this._sendCommand(\n {\n openChannel: {\n id: channel.id,\n tag: channel.tag,\n contentType: channel.contentType,\n },\n },\n SYSTEM_CHANNEL_ID,\n );\n } catch (err: any) {\n this._destroyChannel(channel, err);\n throw err;\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 async createPort(tag: string, opts: CreateChannelOpts = {}): Promise<RpcPort> {\n const channel = this._getOrCreateStream({\n tag,\n contentType: opts.contentType,\n });\n invariant(!channel.push, `Channel already open: ${tag}`);\n\n // We need to buffer incoming data until the port is subscribed to.\n let inboundBuffer: Uint8Array[] = [];\n let callback: ((data: Uint8Array) => void) | undefined;\n\n channel.push = (data) => {\n channel.stats.bytesReceived += data.length;\n if (callback) {\n callback(data);\n } else {\n inboundBuffer.push(data);\n }\n };\n\n const port: RpcPort = {\n send: async (data: Uint8Array) => {\n await this._sendData(channel, data);\n // TODO(dmaretskyi): Debugging.\n // appendFileSync('log.json', JSON.stringify(schema.getCodecForType('dxos.rpc.RpcMessage').decode(data), null, 2) + '\\n')\n },\n subscribe: (cb: (data: Uint8Array) => void) => {\n invariant(!callback, 'Only one subscriber is allowed');\n callback = cb;\n for (const data of inboundBuffer) {\n cb(data);\n }\n inboundBuffer = [];\n },\n };\n\n // NOTE: Make sure channel.push is set before sending the command.\n try {\n await this._sendCommand(\n {\n openChannel: {\n id: channel.id,\n tag: channel.tag,\n contentType: channel.contentType,\n },\n },\n SYSTEM_CHANNEL_ID,\n );\n } catch (err: any) {\n this._destroyChannel(channel, err);\n throw err;\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 Promise.resolve(\n this._sendCommand(\n {\n destroy: {\n error: err?.message,\n },\n },\n SYSTEM_CHANNEL_ID,\n ),\n )\n .then(() => {\n this._dispose();\n })\n .catch((err: any) => {\n this._dispose(err);\n });\n void this._ctx.dispose();\n }\n\n private _dispose(err?: Error) {\n if (this._destroyed) {\n return;\n }\n\n this._destroyed = true;\n this._balancer.destroy();\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 async _handleCommand(cmd: Command) {\n log('Received command', { cmd });\n\n if (this._destroyed || this._destroying) {\n log.warn('Received command after destroy', { cmd });\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 await this._sendCommand(\n {\n data: {\n channelId: channel.remoteId!,\n data,\n },\n },\n channel.id,\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 async _sendCommand(cmd: Command, channelId = -1) {\n try {\n const trigger = new Trigger<void>();\n this._balancer.pushChunk(Command.encode(cmd), trigger, channelId);\n await trigger.wait();\n } catch (err: any) {\n this.destroy(err);\n }\n }\n\n private _getOrCreateStream(params: CreateChannelInternalParams): Channel {\n let channel = this._channelsByTag.get(params.tag);\n if (!channel) {\n channel = {\n id: this._nextId++,\n remoteId: null,\n tag: params.tag,\n contentType: params.contentType,\n buffer: [],\n push: null,\n destroy: null,\n stats: {\n bytesSent: 0,\n bytesReceived: 0,\n },\n };\n this._channelsByTag.set(channel.tag, channel);\n this._channelsByLocalId.set(channel.id, channel);\n this._balancer.addChannel(channel.id);\n }\n return channel;\n }\n\n private async _sendData(channel: Channel, data: Uint8Array): Promise<void> {\n channel.stats.bytesSent += data.length;\n if (channel.remoteId === null) {\n // Remote side has not opened the channel yet.\n channel.buffer.push(data);\n return;\n }\n await this._sendCommand(\n {\n data: {\n channelId: channel.remoteId,\n data,\n },\n },\n channel.id,\n );\n }\n\n private _destroyChannel(channel: Channel, err?: Error) {\n if (channel.destroy) {\n channel.destroy(err);\n }\n this._channelsByLocalId.delete(channel.id);\n this._channelsByTag.delete(channel.tag);\n }\n\n private async _emitStats() {\n if (this._destroyed || this._destroying) {\n return;\n }\n\n this.statsUpdated.emit(\n Array.from(this._channelsByTag.values()).map((channel) => ({\n id: channel.id,\n tag: channel.tag,\n bytesSent: channel.stats.bytesSent,\n bytesReceived: channel.stats.bytesReceived,\n })),\n );\n }\n}\n\ntype Channel = {\n /**\n * Our local channel ID.\n * Incoming Data commands will have this ID.\n */\n id: number;\n tag: string;\n\n /**\n * Remote id is set when we receive an OpenChannel command.\n * The originating Data commands should carry this id.\n */\n remoteId: null | number;\n\n contentType?: string;\n\n /**\n * Send buffer.\n */\n buffer: Uint8Array[];\n\n /**\n * Set when we initialize a NodeJS stream or an RPC port consuming the channel.\n */\n push: null | ((data: Uint8Array) => void);\n\n destroy: null | ((err?: Error) => void);\n\n stats: {\n bytesSent: number;\n bytesReceived: number;\n };\n};\n\ntype CreateChannelInternalParams = {\n tag: string;\n contentType?: string;\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { Trigger } from '@dxos/async';\n\n// TODO(egorgripasov): Is BinaryPort a better name?\nimport { RpcPort } from './rpc-port';\n\ntype Chunk = {\n msg: Uint8Array;\n trigger: Trigger;\n};\n\n/**\n * Load balancer for handling asynchronous calls from multiple channels.\n *\n * Manages a queue of calls from different channels and ensures that the calls\n * are processed in a balanced manner in a round-robin fashion.\n */\nexport class Balancer {\n private _lastCallerIndex = 0;\n private _channels: number[] = [];\n\n // TODO(egorgripasov): Will cause a memory leak if channels do not appreciate the backpressure.\n private _calls: Map<number, Chunk[]> = new Map();\n\n constructor(private readonly _port: RpcPort, private readonly _sysChannelId: number) {\n this._channels.push(_sysChannelId);\n }\n\n addChannel(channel: number) {\n this._channels.push(channel);\n }\n\n pushChunk(msg: Uint8Array, trigger: Trigger, channelId: number) {\n const noCalls = this._calls.size === 0;\n\n if (!this._channels.includes(channelId)) {\n throw new Error(`Unknown channel ${channelId}`);\n }\n\n if (!this._calls.has(channelId)) {\n this._calls.set(channelId, []);\n }\n\n const channelCalls = this._calls.get(channelId)!;\n channelCalls.push({ msg, trigger });\n\n // Start processing calls if this is the first call.\n if (noCalls) {\n process.nextTick(async () => {\n await this._processCalls();\n });\n }\n }\n\n destroy() {\n this._calls.clear();\n }\n\n private _getNextCallerId() {\n if (this._calls.has(this._sysChannelId)) {\n return this._sysChannelId;\n }\n\n const index = this._lastCallerIndex;\n this._lastCallerIndex = (this._lastCallerIndex + 1) % this._channels.length;\n\n return this._channels[index];\n }\n\n private _getNextCall(): Chunk {\n let call;\n while (!call) {\n const channelId = this._getNextCallerId();\n const channelCalls = this._calls.get(channelId);\n if (!channelCalls) {\n continue;\n }\n\n call = channelCalls.shift();\n if (channelCalls.length === 0) {\n this._calls.delete(channelId);\n }\n }\n return call;\n }\n\n private async _processCalls() {\n if (this._calls.size === 0) {\n return;\n }\n\n const call = this._getNextCall();\n\n try {\n await this._port.send(call.msg);\n call.trigger.wake();\n } catch (err: any) {\n call.trigger.throw(err);\n }\n\n await this._processCalls();\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { Duplex } from 'node:stream';\nimport invariant from 'tiny-invariant';\n\nimport { asyncTimeout, scheduleTaskInterval, runInContextAsync, synchronized, scheduleTask, Event } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { schema, RpcClosedError } from '@dxos/protocols';\nimport { ConnectionInfo } from '@dxos/protocols/proto/dxos/devtools/swarm';\nimport { ControlService } from '@dxos/protocols/proto/dxos/mesh/teleport/control';\nimport { createProtoRpcPeer, ProtoRpcPeer } from '@dxos/rpc';\nimport { Callback } from '@dxos/util';\n\nimport { CreateChannelOpts, Muxer, RpcPort } from './muxing';\n\nexport type TeleportParams = {\n initiator: boolean;\n localPeerId: PublicKey;\n remotePeerId: PublicKey;\n};\n\nexport class Teleport {\n public readonly initiator: boolean;\n public readonly localPeerId: PublicKey;\n public readonly remotePeerId: PublicKey;\n\n private readonly _ctx = new Context({\n onError: (err) => {\n void this.destroy(err).catch(() => {\n log.error('Error during destroy', err);\n });\n },\n });\n\n private readonly _muxer = new Muxer();\n\n private readonly _control = new ControlExtension({\n heartbeatInterval: 10_000,\n heartbeatTimeout: 10_000,\n onTimeout: () => {\n this.destroy(new Error('Connection timed out')).catch((err) => log.catch(err));\n },\n });\n\n private readonly _extensions = new Map<string, TeleportExtension>();\n private readonly _remoteExtensions = new Set<string>();\n\n private _open = false;\n\n constructor({ initiator, localPeerId, remotePeerId }: TeleportParams) {\n invariant(typeof initiator === 'boolean');\n invariant(PublicKey.isPublicKey(localPeerId));\n invariant(PublicKey.isPublicKey(remotePeerId));\n invariant(typeof initiator === 'boolean');\n this.initiator = initiator;\n this.localPeerId = localPeerId;\n this.remotePeerId = remotePeerId;\n\n this._control.onExtensionRegistered.set(async (name) => {\n log('remote extension', { name });\n invariant(!this._remoteExtensions.has(name), 'Remote extension already exists');\n this._remoteExtensions.add(name);\n\n if (this._extensions.has(name)) {\n try {\n await this._openExtension(name);\n } catch (err: any) {\n await this.destroy(err);\n }\n }\n });\n\n {\n // Destroy Teleport when the stream is closed.\n this._muxer.stream.on('close', async () => {\n await this.destroy();\n });\n\n this._muxer.stream.on('error', async (err) => {\n await this.destroy(err);\n });\n }\n }\n\n get stream(): Duplex {\n return this._muxer.stream;\n }\n\n get stats(): Event<ConnectionInfo.StreamStats[]> {\n return this._muxer.statsUpdated;\n }\n\n /**\n * Blocks until the handshake is complete.\n */\n async open() {\n this._setExtension('dxos.mesh.teleport.control', this._control);\n await this._openExtension('dxos.mesh.teleport.control');\n this._open = true;\n }\n\n async close(err?: Error) {\n // TODO(dmaretskyi): Try soft close.\n\n await this.destroy(err);\n }\n\n @synchronized\n async destroy(err?: Error) {\n if (this._ctx.disposed) {\n return;\n }\n\n await this._ctx.dispose();\n\n for (const extension of this._extensions.values()) {\n try {\n await extension.onClose(err);\n } catch (err: any) {\n log.catch(err);\n }\n }\n\n this._muxer.destroy(err);\n }\n\n addExtension(name: string, extension: TeleportExtension) {\n if (!this._open) {\n throw new Error('Not open');\n }\n\n log('addExtension', { name });\n this._setExtension(name, extension);\n\n // Perform the registration in a separate tick as this might block while the remote side is opening the extension.\n scheduleTask(this._ctx, async () => {\n try {\n await this._control.registerExtension(name);\n } catch (err) {\n if (err instanceof RpcClosedError) {\n return;\n }\n throw err;\n }\n });\n\n if (this._remoteExtensions.has(name)) {\n // Open the extension in a separate tick.\n scheduleTask(this._ctx, async () => {\n await this._openExtension(name);\n });\n }\n }\n\n private _setExtension(extensionName: string, extension: TeleportExtension) {\n invariant(!extensionName.includes('/'), 'Invalid extension name');\n invariant(!this._extensions.has(extensionName), 'Extension already exists');\n this._extensions.set(extensionName, extension);\n }\n\n private async _openExtension(extensionName: string) {\n log('open extension', { extensionName });\n const extension = this._extensions.get(extensionName) ?? failUndefined();\n\n const context: ExtensionContext = {\n initiator: this.initiator,\n localPeerId: this.localPeerId,\n remotePeerId: this.remotePeerId,\n createPort: async (channelName: string, opts?: CreateChannelOpts) => {\n invariant(!channelName.includes('/'), 'Invalid channel name');\n return this._muxer.createPort(`${extensionName}/${channelName}`, opts);\n },\n createStream: async (channelName: string, opts?: CreateChannelOpts) => {\n invariant(!channelName.includes('/'), 'Invalid channel name');\n return this._muxer.createStream(`${extensionName}/${channelName}`, opts);\n },\n close: (err) => {\n void runInContextAsync(this._ctx, async () => {\n await this.close(err);\n });\n },\n };\n\n await extension.onOpen(context);\n log('extension opened', { extensionName });\n }\n}\n\nexport type ExtensionContext = {\n /**\n * One of the peers will be designated an initiator.\n */\n initiator: boolean;\n localPeerId: PublicKey;\n remotePeerId: PublicKey;\n createStream(tag: string, opts?: CreateChannelOpts): Promise<Duplex>;\n createPort(tag: string, opts?: CreateChannelOpts): Promise<RpcPort>;\n close(err?: Error): void;\n};\n\nexport interface TeleportExtension {\n onOpen(context: ExtensionContext): Promise<void>;\n onClose(err?: Error): Promise<void>;\n}\n\ntype ControlExtensionOpts = {\n heartbeatInterval: number;\n heartbeatTimeout: number;\n onTimeout: () => void;\n};\n\nclass ControlExtension implements TeleportExtension {\n private readonly _ctx = new Context({\n onError: (err) => {\n this._extensionContext.close(err);\n },\n });\n\n private _extensionContext!: ExtensionContext;\n private _rpc!: ProtoRpcPeer<{ Control: ControlService }>;\n\n public readonly onExtensionRegistered = new Callback<(extensionName: string) => void>();\n\n constructor(private readonly opts: ControlExtensionOpts) {}\n\n async onOpen(extensionContext: ExtensionContext): Promise<void> {\n this._extensionContext = extensionContext;\n\n // NOTE: Make sure that RPC timeout is greater than the heartbeat timeout.\n // TODO(dmaretskyi): Allow overwriting the timeout on individual RPC calls?\n this._rpc = createProtoRpcPeer<ControlRpcBundle, ControlRpcBundle>({\n requested: {\n Control: schema.getService('dxos.mesh.teleport.control.ControlService'),\n },\n exposed: {\n Control: schema.getService('dxos.mesh.teleport.control.ControlService'),\n },\n handlers: {\n Control: {\n registerExtension: async (request) => {\n this.onExtensionRegistered.call(request.name);\n },\n heartbeat: async (request) => {\n // Ok.\n },\n },\n },\n port: await extensionContext.createPort('rpc', {\n contentType: 'application/x-protobuf; messagType=\"dxos.rpc.Message\"',\n }),\n });\n\n await this._rpc.open();\n\n scheduleTaskInterval(\n this._ctx,\n async () => {\n try {\n await asyncTimeout(this._rpc.rpc.Control.heartbeat(), this.opts.heartbeatTimeout);\n } catch (err: any) {\n this.opts.onTimeout();\n }\n },\n this.opts.heartbeatInterval,\n );\n }\n\n async onClose(err?: Error): Promise<void> {\n await this._ctx.dispose();\n await this._rpc.close();\n }\n\n async registerExtension(name: string) {\n await this._rpc.rpc.Control.registerExtension({ name });\n }\n}\n\ntype ControlRpcBundle = {\n Control: ControlService;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport invariant from 'tiny-invariant';\n\nimport { asyncTimeout, Trigger } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\nimport { TestService } from '@dxos/protocols/proto/example/testing/rpc';\nimport { createProtoRpcPeer, ProtoRpcPeer } from '@dxos/rpc';\n\nimport { ExtensionContext, TeleportExtension } from '../teleport';\n\ninterface TestExtensionCallbacks {\n onOpen?: () => Promise<void>;\n onClose?: () => Promise<void>;\n}\n\nexport class TestExtension implements TeleportExtension {\n public readonly open = new Trigger();\n public readonly closed = new Trigger();\n public extensionContext: ExtensionContext | undefined;\n private _rpc!: ProtoRpcPeer<{ TestService: TestService }>;\n\n constructor(public readonly callbacks: TestExtensionCallbacks = {}) {}\n\n get remotePeerId() {\n return this.extensionContext?.remotePeerId;\n }\n\n async onOpen(context: ExtensionContext) {\n log('onOpen', { localPeerId: context.localPeerId, remotePeerId: context.remotePeerId });\n this.extensionContext = context;\n this._rpc = createProtoRpcPeer<{ TestService: TestService }, { TestService: TestService }>({\n port: await 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: 2000,\n });\n\n await this._rpc.open();\n await this.callbacks.onOpen?.();\n\n this.open.wake();\n }\n\n async onClose(err?: Error) {\n log('onClose', { err });\n await this.callbacks.onClose?.();\n this.closed.wake();\n await this._rpc?.close();\n }\n\n async test(message = 'test') {\n await this.open.wait({ timeout: 1500 });\n const res = await asyncTimeout(this._rpc.rpc.TestService.testCall({ data: message }), 1500);\n invariant(res.data === message);\n }\n\n /**\n * Force-close the connection.\n */\n async closeConnection(err?: Error) {\n this.extensionContext?.close(err);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Duplex", "invariant", "varint", "Framer", "constructor", "_responseQueue", "_stream", "Duplex", "objectMode", "read", "write", "chunk", "encoding", "callback", "invariant", "_subscribeCb", "_buffer", "length", "Buffer", "concat", "_messageCb", "_popFrames", "undefined", "port", "send", "message", "Promise", "resolve", "canContinue", "push", "encodeFrame", "process", "nextTick", "subscribe", "stream", "on", "_processResponseQueue", "bind", "responseQueue", "forEach", "cb", "offset", "frame", "decodeFrame", "bytesConsumed", "payload", "subarray", "destroy", "removeAllListeners", "buffer", "frameLength", "decode", "tagLength", "bytes", "err", "RangeError", "encodingLength", "allocUnsafe", "varint", "encode", "set", "Duplex", "invariant", "scheduleTaskInterval", "Event", "Trigger", "Context", "failUndefined", "log", "schema", "Balancer", "constructor", "_port", "_sysChannelId", "_lastCallerIndex", "_channels", "_calls", "Map", "push", "addChannel", "channel", "pushChunk", "msg", "trigger", "channelId", "noCalls", "size", "includes", "Error", "has", "set", "channelCalls", "get", "process", "nextTick", "_processCalls", "destroy", "clear", "_getNextCallerId", "index", "length", "_getNextCall", "call", "shift", "delete", "send", "wake", "err", "throw", "Command", "schema", "getCodecForType", "STATS_INTERVAL", "SYSTEM_CHANNEL_ID", "Muxer", "constructor", "_framer", "Framer", "_balancer", "Balancer", "port", "stream", "_channelsByLocalId", "Map", "_channelsByTag", "_nextId", "_destroyed", "_destroying", "close", "Event", "statsUpdated", "_ctx", "Context", "subscribe", "msg", "_handleCommand", "decode", "scheduleTaskInterval", "_emitStats", "createStream", "tag", "opts", "channel", "_getOrCreateStream", "contentType", "invariant", "push", "Duplex", "write", "data", "encoding", "callback", "_sendData", "then", "catch", "read", "stats", "bytesReceived", "length", "destroy", "err", "_sendCommand", "openChannel", "id", "_destroyChannel", "createPort", "inboundBuffer", "send", "cb", "Promise", "resolve", "error", "message", "_dispose", "dispose", "values", "emit", "clear", "cmd", "log", "warn", "remoteId", "buffer", "channelId", "get", "failUndefined", "trigger", "Trigger", "pushChunk", "encode", "wait", "params", "bytesSent", "set", "addChannel", "delete", "Array", "from", "map", "invariant", "asyncTimeout", "scheduleTaskInterval", "runInContextAsync", "synchronized", "scheduleTask", "Context", "failUndefined", "PublicKey", "log", "schema", "RpcClosedError", "createProtoRpcPeer", "Callback", "Teleport", "constructor", "initiator", "localPeerId", "remotePeerId", "_ctx", "Context", "onError", "err", "destroy", "catch", "log", "error", "_muxer", "Muxer", "_control", "ControlExtension", "heartbeatInterval", "heartbeatTimeout", "onTimeout", "Error", "_extensions", "Map", "_remoteExtensions", "Set", "_open", "invariant", "PublicKey", "isPublicKey", "onExtensionRegistered", "set", "name", "has", "add", "_openExtension", "stream", "on", "stats", "statsUpdated", "open", "_setExtension", "close", "disposed", "dispose", "extension", "values", "onClose", "addExtension", "scheduleTask", "registerExtension", "RpcClosedError", "extensionName", "includes", "get", "failUndefined", "context", "createPort", "channelName", "opts", "createStream", "runInContextAsync", "onOpen", "synchronized", "_extensionContext", "Callback", "extensionContext", "_rpc", "createProtoRpcPeer", "requested", "Control", "schema", "getService", "exposed", "handlers", "request", "call", "heartbeat", "port", "contentType", "scheduleTaskInterval", "asyncTimeout", "rpc", "invariant", "asyncTimeout", "Trigger", "log", "schema", "createProtoRpcPeer", "TestExtension", "constructor", "callbacks", "open", "closed", "remotePeerId", "extensionContext", "onOpen", "context", "localPeerId", "_rpc", "port", "createPort", "contentType", "requested", "TestService", "getService", "exposed", "handlers", "voidCall", "request", "testCall", "data", "timeout", "wake", "onClose", "err", "close", "test", "message", "wait", "res", "rpc", "closeConnection"]
|
|
7
|
+
}
|