@dxos/teleport 0.3.8-next.f4e0086 → 0.3.9-main.14901ff
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-C7IP5EHF.mjs → chunk-M7U4KJA7.mjs} +102 -50
- package/dist/lib/browser/chunk-M7U4KJA7.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +1 -1
- package/dist/lib/node/chunk-GVV33WCQ.cjs +1952 -0
- package/dist/lib/node/chunk-GVV33WCQ.cjs.map +7 -0
- package/dist/lib/node/index.cjs +18 -1897
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +6 -1885
- package/dist/lib/node/testing/index.cjs.map +4 -4
- package/dist/types/src/muxing/muxer.d.ts +5 -1
- package/dist/types/src/muxing/muxer.d.ts.map +1 -1
- package/dist/types/src/teleport.d.ts +3 -1
- package/dist/types/src/teleport.d.ts.map +1 -1
- package/package.json +12 -12
- package/src/muxing/muxer.ts +42 -7
- package/src/teleport.ts +13 -2
- package/src/testing/test-builder.ts +1 -1
- package/dist/lib/browser/chunk-C7IP5EHF.mjs.map +0 -7
package/dist/lib/node/index.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,1903 +15,26 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
Framer: () => Framer,
|
|
34
|
-
Muxer: () => Muxer,
|
|
19
|
+
var node_exports = {};
|
|
20
|
+
__export(node_exports, {
|
|
21
|
+
Framer: () => import_chunk_GVV33WCQ.Framer,
|
|
22
|
+
Muxer: () => import_chunk_GVV33WCQ.Muxer,
|
|
35
23
|
RpcExtension: () => RpcExtension,
|
|
36
|
-
Teleport: () => Teleport,
|
|
37
|
-
TestBuilder: () => TestBuilder,
|
|
38
|
-
TestConnection: () => TestConnection,
|
|
39
|
-
TestExtension: () => TestExtension,
|
|
40
|
-
TestExtensionWithStreams: () => TestExtensionWithStreams,
|
|
41
|
-
TestPeer: () => TestPeer,
|
|
42
|
-
decodeFrame: () => decodeFrame,
|
|
43
|
-
encodeFrame: () => encodeFrame
|
|
24
|
+
Teleport: () => import_chunk_GVV33WCQ.Teleport,
|
|
25
|
+
TestBuilder: () => import_chunk_GVV33WCQ.TestBuilder,
|
|
26
|
+
TestConnection: () => import_chunk_GVV33WCQ.TestConnection,
|
|
27
|
+
TestExtension: () => import_chunk_GVV33WCQ.TestExtension,
|
|
28
|
+
TestExtensionWithStreams: () => import_chunk_GVV33WCQ.TestExtensionWithStreams,
|
|
29
|
+
TestPeer: () => import_chunk_GVV33WCQ.TestPeer,
|
|
30
|
+
decodeFrame: () => import_chunk_GVV33WCQ.decodeFrame,
|
|
31
|
+
encodeFrame: () => import_chunk_GVV33WCQ.encodeFrame
|
|
44
32
|
});
|
|
45
|
-
module.exports = __toCommonJS(
|
|
46
|
-
|
|
47
|
-
// packages/core/mesh/teleport/src/muxing/framer.ts
|
|
48
|
-
var import_node_stream = require("node:stream");
|
|
49
|
-
var import_async = require("@dxos/async");
|
|
33
|
+
module.exports = __toCommonJS(node_exports);
|
|
34
|
+
var import_chunk_GVV33WCQ = require("./chunk-GVV33WCQ.cjs");
|
|
50
35
|
var import_invariant = require("@dxos/invariant");
|
|
51
|
-
var import_log = require("@dxos/log");
|
|
52
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/framer.ts";
|
|
53
|
-
var FRAME_LENGTH_SIZE = 2;
|
|
54
|
-
var Framer = class {
|
|
55
|
-
constructor() {
|
|
56
|
-
// private readonly _tagBuffer = Buffer.alloc(4)
|
|
57
|
-
this._messageCb = void 0;
|
|
58
|
-
this._subscribeCb = void 0;
|
|
59
|
-
this._buffer = void 0;
|
|
60
|
-
this._sendCallbacks = [];
|
|
61
|
-
this._bytesSent = 0;
|
|
62
|
-
this._bytesReceived = 0;
|
|
63
|
-
this._writable = true;
|
|
64
|
-
this.drain = new import_async.Event();
|
|
65
|
-
// TODO(egorgripasov): Consider using a Transform stream if it provides better backpressure handling.
|
|
66
|
-
this._stream = new import_node_stream.Duplex({
|
|
67
|
-
objectMode: false,
|
|
68
|
-
read: () => {
|
|
69
|
-
this._processResponseQueue();
|
|
70
|
-
},
|
|
71
|
-
write: (chunk, encoding, callback) => {
|
|
72
|
-
(0, import_invariant.invariant)(!this._subscribeCb, "Internal Framer bug. Concurrent writes detected.", {
|
|
73
|
-
F: __dxlog_file,
|
|
74
|
-
L: 40,
|
|
75
|
-
S: this,
|
|
76
|
-
A: [
|
|
77
|
-
"!this._subscribeCb",
|
|
78
|
-
"'Internal Framer bug. Concurrent writes detected.'"
|
|
79
|
-
]
|
|
80
|
-
});
|
|
81
|
-
this._bytesReceived += chunk.length;
|
|
82
|
-
if (this._buffer && this._buffer.length > 0) {
|
|
83
|
-
this._buffer = Buffer.concat([
|
|
84
|
-
this._buffer,
|
|
85
|
-
chunk
|
|
86
|
-
]);
|
|
87
|
-
} else {
|
|
88
|
-
this._buffer = chunk;
|
|
89
|
-
}
|
|
90
|
-
if (this._messageCb) {
|
|
91
|
-
this._popFrames();
|
|
92
|
-
callback();
|
|
93
|
-
} else {
|
|
94
|
-
this._subscribeCb = () => {
|
|
95
|
-
this._popFrames();
|
|
96
|
-
this._subscribeCb = void 0;
|
|
97
|
-
callback();
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
this.port = {
|
|
103
|
-
send: (message) => {
|
|
104
|
-
return new Promise((resolve) => {
|
|
105
|
-
const frame = encodeFrame(message);
|
|
106
|
-
this._bytesSent += frame.length;
|
|
107
|
-
this._writable = this._stream.push(frame);
|
|
108
|
-
if (!this._writable) {
|
|
109
|
-
this._sendCallbacks.push(resolve);
|
|
110
|
-
} else {
|
|
111
|
-
resolve();
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
},
|
|
115
|
-
subscribe: (callback) => {
|
|
116
|
-
(0, import_invariant.invariant)(!this._messageCb, "Rpc port already has a message listener.", {
|
|
117
|
-
F: __dxlog_file,
|
|
118
|
-
L: 79,
|
|
119
|
-
S: this,
|
|
120
|
-
A: [
|
|
121
|
-
"!this._messageCb",
|
|
122
|
-
"'Rpc port already has a message listener.'"
|
|
123
|
-
]
|
|
124
|
-
});
|
|
125
|
-
this._messageCb = callback;
|
|
126
|
-
this._subscribeCb?.();
|
|
127
|
-
return () => {
|
|
128
|
-
this._messageCb = void 0;
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
get stream() {
|
|
134
|
-
return this._stream;
|
|
135
|
-
}
|
|
136
|
-
get bytesSent() {
|
|
137
|
-
return this._bytesSent;
|
|
138
|
-
}
|
|
139
|
-
get bytesReceived() {
|
|
140
|
-
return this._bytesReceived;
|
|
141
|
-
}
|
|
142
|
-
get writable() {
|
|
143
|
-
return this._writable;
|
|
144
|
-
}
|
|
145
|
-
_processResponseQueue() {
|
|
146
|
-
const responseQueue = this._sendCallbacks;
|
|
147
|
-
this._sendCallbacks = [];
|
|
148
|
-
this._writable = true;
|
|
149
|
-
this.drain.emit();
|
|
150
|
-
responseQueue.forEach((cb) => cb());
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Attempts to pop frames from the buffer and call the message callback.
|
|
154
|
-
*/
|
|
155
|
-
_popFrames() {
|
|
156
|
-
let offset = 0;
|
|
157
|
-
while (offset < this._buffer.length) {
|
|
158
|
-
const frame = decodeFrame(this._buffer, offset);
|
|
159
|
-
if (!frame) {
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
offset += frame.bytesConsumed;
|
|
163
|
-
this._messageCb(frame.payload);
|
|
164
|
-
}
|
|
165
|
-
if (offset < this._buffer.length) {
|
|
166
|
-
this._buffer = this._buffer.subarray(offset);
|
|
167
|
-
} else {
|
|
168
|
-
this._buffer = void 0;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
destroy() {
|
|
172
|
-
if (this._stream.readableLength > 0) {
|
|
173
|
-
import_log.log.info("framer destroyed while there are still read bytes in the buffer.", void 0, {
|
|
174
|
-
F: __dxlog_file,
|
|
175
|
-
L: 140,
|
|
176
|
-
S: this,
|
|
177
|
-
C: (f, a) => f(...a)
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
if (this._stream.writableLength > 0) {
|
|
181
|
-
import_log.log.warn("framer destroyed while there are still write bytes in the buffer.", void 0, {
|
|
182
|
-
F: __dxlog_file,
|
|
183
|
-
L: 143,
|
|
184
|
-
S: this,
|
|
185
|
-
C: (f, a) => f(...a)
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
this._stream.destroy();
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
var decodeFrame = (buffer, offset) => {
|
|
192
|
-
if (buffer.length < offset + FRAME_LENGTH_SIZE) {
|
|
193
|
-
return void 0;
|
|
194
|
-
}
|
|
195
|
-
const frameLength = buffer.readUInt16BE(offset);
|
|
196
|
-
const bytesConsumed = FRAME_LENGTH_SIZE + frameLength;
|
|
197
|
-
if (buffer.length < offset + bytesConsumed) {
|
|
198
|
-
return void 0;
|
|
199
|
-
}
|
|
200
|
-
const payload = buffer.subarray(offset + FRAME_LENGTH_SIZE, offset + bytesConsumed);
|
|
201
|
-
return {
|
|
202
|
-
payload,
|
|
203
|
-
bytesConsumed
|
|
204
|
-
};
|
|
205
|
-
};
|
|
206
|
-
var encodeFrame = (payload) => {
|
|
207
|
-
const frame = Buffer.allocUnsafe(FRAME_LENGTH_SIZE + payload.length);
|
|
208
|
-
frame.writeUInt16BE(payload.length, 0);
|
|
209
|
-
frame.set(payload, FRAME_LENGTH_SIZE);
|
|
210
|
-
return frame;
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
// packages/core/mesh/teleport/src/muxing/muxer.ts
|
|
214
|
-
var import_node_stream2 = require("node:stream");
|
|
215
|
-
var import_async3 = require("@dxos/async");
|
|
216
|
-
var import_context = require("@dxos/context");
|
|
217
|
-
var import_debug = require("@dxos/debug");
|
|
218
|
-
var import_invariant3 = require("@dxos/invariant");
|
|
219
|
-
var import_log3 = require("@dxos/log");
|
|
220
|
-
var import_protocols = require("@dxos/protocols");
|
|
221
|
-
|
|
222
|
-
// packages/core/mesh/teleport/src/muxing/balancer.ts
|
|
223
|
-
var varint = __toESM(require("varint"));
|
|
224
|
-
var import_async2 = require("@dxos/async");
|
|
225
|
-
var import_invariant2 = require("@dxos/invariant");
|
|
226
|
-
var import_log2 = require("@dxos/log");
|
|
227
|
-
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/balancer.ts";
|
|
228
|
-
var MAX_CHUNK_SIZE = 8192;
|
|
229
|
-
var Balancer = class {
|
|
230
|
-
constructor(_sysChannelId) {
|
|
231
|
-
this._sysChannelId = _sysChannelId;
|
|
232
|
-
this._lastCallerIndex = 0;
|
|
233
|
-
this._channels = [];
|
|
234
|
-
this._framer = new Framer();
|
|
235
|
-
this._sendBuffers = /* @__PURE__ */ new Map();
|
|
236
|
-
this._receiveBuffers = /* @__PURE__ */ new Map();
|
|
237
|
-
this._sending = false;
|
|
238
|
-
this.incomingData = new import_async2.Event();
|
|
239
|
-
this.stream = this._framer.stream;
|
|
240
|
-
this._channels.push(_sysChannelId);
|
|
241
|
-
this._framer.port.subscribe(this._processIncomingMessage.bind(this));
|
|
242
|
-
}
|
|
243
|
-
get bytesSent() {
|
|
244
|
-
return this._framer.bytesSent;
|
|
245
|
-
}
|
|
246
|
-
get bytesReceived() {
|
|
247
|
-
return this._framer.bytesReceived;
|
|
248
|
-
}
|
|
249
|
-
get buffersCount() {
|
|
250
|
-
return this._sendBuffers.size;
|
|
251
|
-
}
|
|
252
|
-
addChannel(channel) {
|
|
253
|
-
this._channels.push(channel);
|
|
254
|
-
}
|
|
255
|
-
pushData(data, trigger, channelId) {
|
|
256
|
-
this._enqueueChunk(data, trigger, channelId);
|
|
257
|
-
this._sendChunks().catch((err) => import_log2.log.catch(err, void 0, {
|
|
258
|
-
F: __dxlog_file2,
|
|
259
|
-
L: 75,
|
|
260
|
-
S: this,
|
|
261
|
-
C: (f, a) => f(...a)
|
|
262
|
-
}));
|
|
263
|
-
}
|
|
264
|
-
destroy() {
|
|
265
|
-
if (this._sendBuffers.size !== 0) {
|
|
266
|
-
import_log2.log.info("destroying balancer with pending calls", void 0, {
|
|
267
|
-
F: __dxlog_file2,
|
|
268
|
-
L: 80,
|
|
269
|
-
S: this,
|
|
270
|
-
C: (f, a) => f(...a)
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
this._sendBuffers.clear();
|
|
274
|
-
this._framer.destroy();
|
|
275
|
-
}
|
|
276
|
-
_processIncomingMessage(msg) {
|
|
277
|
-
const { channelId, dataLength, chunk } = decodeChunk(msg, (channelId2) => !this._receiveBuffers.has(channelId2));
|
|
278
|
-
if (!this._receiveBuffers.has(channelId)) {
|
|
279
|
-
if (chunk.length < dataLength) {
|
|
280
|
-
this._receiveBuffers.set(channelId, {
|
|
281
|
-
buffer: Buffer.from(chunk),
|
|
282
|
-
msgLength: dataLength
|
|
283
|
-
});
|
|
284
|
-
} else {
|
|
285
|
-
this.incomingData.emit(chunk);
|
|
286
|
-
}
|
|
287
|
-
} else {
|
|
288
|
-
const channelBuffer = this._receiveBuffers.get(channelId);
|
|
289
|
-
channelBuffer.buffer = Buffer.concat([
|
|
290
|
-
channelBuffer.buffer,
|
|
291
|
-
chunk
|
|
292
|
-
]);
|
|
293
|
-
if (channelBuffer.buffer.length < channelBuffer.msgLength) {
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
const msg2 = channelBuffer.buffer;
|
|
297
|
-
this._receiveBuffers.delete(channelId);
|
|
298
|
-
this.incomingData.emit(msg2);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
_getNextCallerId() {
|
|
302
|
-
if (this._sendBuffers.has(this._sysChannelId)) {
|
|
303
|
-
return this._sysChannelId;
|
|
304
|
-
}
|
|
305
|
-
const index = this._lastCallerIndex;
|
|
306
|
-
this._lastCallerIndex = (this._lastCallerIndex + 1) % this._channels.length;
|
|
307
|
-
return this._channels[index];
|
|
308
|
-
}
|
|
309
|
-
_enqueueChunk(data, trigger, channelId) {
|
|
310
|
-
if (!this._channels.includes(channelId)) {
|
|
311
|
-
throw new Error(`Unknown channel ${channelId}`);
|
|
312
|
-
}
|
|
313
|
-
if (!this._sendBuffers.has(channelId)) {
|
|
314
|
-
this._sendBuffers.set(channelId, []);
|
|
315
|
-
}
|
|
316
|
-
const sendBuffer = this._sendBuffers.get(channelId);
|
|
317
|
-
const chunks = [];
|
|
318
|
-
for (let idx = 0; idx < data.length; idx += MAX_CHUNK_SIZE) {
|
|
319
|
-
chunks.push(data.subarray(idx, idx + MAX_CHUNK_SIZE));
|
|
320
|
-
}
|
|
321
|
-
chunks.forEach((chunk, index) => {
|
|
322
|
-
const msg = encodeChunk({
|
|
323
|
-
chunk,
|
|
324
|
-
channelId,
|
|
325
|
-
dataLength: index === 0 ? data.length : void 0
|
|
326
|
-
});
|
|
327
|
-
sendBuffer.push({
|
|
328
|
-
msg,
|
|
329
|
-
trigger: index === chunks.length - 1 ? trigger : void 0
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
// get the next chunk or null if there are no chunks remaining
|
|
334
|
-
_getNextChunk() {
|
|
335
|
-
let chunk;
|
|
336
|
-
while (this._sendBuffers.size > 0) {
|
|
337
|
-
const channelId = this._getNextCallerId();
|
|
338
|
-
const sendBuffer = this._sendBuffers.get(channelId);
|
|
339
|
-
if (!sendBuffer) {
|
|
340
|
-
continue;
|
|
341
|
-
}
|
|
342
|
-
chunk = sendBuffer.shift();
|
|
343
|
-
if (!chunk) {
|
|
344
|
-
continue;
|
|
345
|
-
}
|
|
346
|
-
if (sendBuffer.length === 0) {
|
|
347
|
-
this._sendBuffers.delete(channelId);
|
|
348
|
-
}
|
|
349
|
-
return chunk;
|
|
350
|
-
}
|
|
351
|
-
return null;
|
|
352
|
-
}
|
|
353
|
-
async _sendChunks() {
|
|
354
|
-
if (this._sending) {
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
this._sending = true;
|
|
358
|
-
let chunk;
|
|
359
|
-
chunk = this._getNextChunk();
|
|
360
|
-
while (chunk) {
|
|
361
|
-
if (!this._framer.writable) {
|
|
362
|
-
(0, import_log2.log)("PAUSE for drain", void 0, {
|
|
363
|
-
F: __dxlog_file2,
|
|
364
|
-
L: 179,
|
|
365
|
-
S: this,
|
|
366
|
-
C: (f, a) => f(...a)
|
|
367
|
-
});
|
|
368
|
-
await this._framer.drain.waitForCount(1);
|
|
369
|
-
(0, import_log2.log)("RESUME for drain", void 0, {
|
|
370
|
-
F: __dxlog_file2,
|
|
371
|
-
L: 181,
|
|
372
|
-
S: this,
|
|
373
|
-
C: (f, a) => f(...a)
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
try {
|
|
377
|
-
await this._framer.port.send(chunk.msg);
|
|
378
|
-
chunk.trigger?.wake();
|
|
379
|
-
} catch (err) {
|
|
380
|
-
(0, import_log2.log)("Error sending chunk", {
|
|
381
|
-
err
|
|
382
|
-
}, {
|
|
383
|
-
F: __dxlog_file2,
|
|
384
|
-
L: 187,
|
|
385
|
-
S: this,
|
|
386
|
-
C: (f, a) => f(...a)
|
|
387
|
-
});
|
|
388
|
-
chunk.trigger?.throw(err);
|
|
389
|
-
}
|
|
390
|
-
chunk = this._getNextChunk();
|
|
391
|
-
}
|
|
392
|
-
(0, import_invariant2.invariant)(this._sendBuffers.size === 0, "sendBuffers not empty", {
|
|
393
|
-
F: __dxlog_file2,
|
|
394
|
-
L: 192,
|
|
395
|
-
S: this,
|
|
396
|
-
A: [
|
|
397
|
-
"this._sendBuffers.size === 0",
|
|
398
|
-
"'sendBuffers not empty'"
|
|
399
|
-
]
|
|
400
|
-
});
|
|
401
|
-
this._sending = false;
|
|
402
|
-
}
|
|
403
|
-
};
|
|
404
|
-
var encodeChunk = ({ channelId, dataLength, chunk }) => {
|
|
405
|
-
const channelTagLength = varint.encodingLength(channelId);
|
|
406
|
-
const dataLengthLength = dataLength ? varint.encodingLength(dataLength) : 0;
|
|
407
|
-
const message = Buffer.allocUnsafe(channelTagLength + dataLengthLength + chunk.length);
|
|
408
|
-
varint.encode(channelId, message);
|
|
409
|
-
if (dataLength) {
|
|
410
|
-
varint.encode(dataLength, message, channelTagLength);
|
|
411
|
-
}
|
|
412
|
-
message.set(chunk, channelTagLength + dataLengthLength);
|
|
413
|
-
return message;
|
|
414
|
-
};
|
|
415
|
-
var decodeChunk = (data, withLength) => {
|
|
416
|
-
const channelId = varint.decode(data);
|
|
417
|
-
let dataLength;
|
|
418
|
-
let offset = varint.decode.bytes;
|
|
419
|
-
if (withLength(channelId)) {
|
|
420
|
-
dataLength = varint.decode(data, offset);
|
|
421
|
-
offset += varint.decode.bytes;
|
|
422
|
-
}
|
|
423
|
-
const chunk = data.subarray(offset);
|
|
424
|
-
return {
|
|
425
|
-
channelId,
|
|
426
|
-
dataLength,
|
|
427
|
-
chunk
|
|
428
|
-
};
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
// packages/core/mesh/teleport/src/muxing/muxer.ts
|
|
432
|
-
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/muxer.ts";
|
|
433
|
-
var Command = import_protocols.schema.getCodecForType("dxos.mesh.muxer.Command");
|
|
434
|
-
var DEFAULT_SEND_COMMAND_TIMEOUT = 6e4;
|
|
435
|
-
var DESTROY_COMMAND_SEND_TIMEOUT = 5e3;
|
|
436
|
-
var STATS_INTERVAL = 1e3;
|
|
437
|
-
var MAX_SAFE_FRAME_SIZE = 1e6;
|
|
438
|
-
var SYSTEM_CHANNEL_ID = 0;
|
|
439
|
-
var GRACEFUL_CLOSE_TIMEOUT = 3e3;
|
|
440
|
-
var Muxer = class {
|
|
441
|
-
constructor() {
|
|
442
|
-
this._balancer = new Balancer(SYSTEM_CHANNEL_ID);
|
|
443
|
-
this._channelsByLocalId = /* @__PURE__ */ new Map();
|
|
444
|
-
this._channelsByTag = /* @__PURE__ */ new Map();
|
|
445
|
-
this._ctx = new import_context.Context();
|
|
446
|
-
this._nextId = 1;
|
|
447
|
-
this._closing = false;
|
|
448
|
-
this._destroying = false;
|
|
449
|
-
this._disposed = false;
|
|
450
|
-
this._lastStats = void 0;
|
|
451
|
-
this._lastChannelStats = /* @__PURE__ */ new Map();
|
|
452
|
-
this.afterClosed = new import_async3.Event();
|
|
453
|
-
this.statsUpdated = new import_async3.Event();
|
|
454
|
-
this.stream = this._balancer.stream;
|
|
455
|
-
this._balancer.incomingData.on(async (msg) => {
|
|
456
|
-
await this._handleCommand(Command.decode(msg));
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* Creates a duplex Node.js-style stream.
|
|
461
|
-
* The remote peer is expected to call `createStream` with the same tag.
|
|
462
|
-
* The stream is immediately readable and writable.
|
|
463
|
-
* NOTE: The data will be buffered until the stream is opened remotely with the same tag (may cause a memory leak).
|
|
464
|
-
*/
|
|
465
|
-
async createStream(tag, opts = {}) {
|
|
466
|
-
const channel = this._getOrCreateStream({
|
|
467
|
-
tag,
|
|
468
|
-
contentType: opts.contentType
|
|
469
|
-
});
|
|
470
|
-
(0, import_invariant3.invariant)(!channel.push, `Channel already open: ${tag}`, {
|
|
471
|
-
F: __dxlog_file3,
|
|
472
|
-
L: 140,
|
|
473
|
-
S: this,
|
|
474
|
-
A: [
|
|
475
|
-
"!channel.push",
|
|
476
|
-
"`Channel already open: ${tag}`"
|
|
477
|
-
]
|
|
478
|
-
});
|
|
479
|
-
const stream = new import_node_stream2.Duplex({
|
|
480
|
-
write: (data, encoding, callback) => {
|
|
481
|
-
this._sendData(channel, data).then(() => callback()).catch(callback);
|
|
482
|
-
},
|
|
483
|
-
read: () => {
|
|
484
|
-
}
|
|
485
|
-
});
|
|
486
|
-
channel.push = (data) => {
|
|
487
|
-
channel.stats.bytesReceived += data.length;
|
|
488
|
-
stream.push(data);
|
|
489
|
-
};
|
|
490
|
-
channel.destroy = (err) => {
|
|
491
|
-
stream.destroy(err);
|
|
492
|
-
};
|
|
493
|
-
try {
|
|
494
|
-
await this._sendCommand({
|
|
495
|
-
openChannel: {
|
|
496
|
-
id: channel.id,
|
|
497
|
-
tag: channel.tag,
|
|
498
|
-
contentType: channel.contentType
|
|
499
|
-
}
|
|
500
|
-
}, SYSTEM_CHANNEL_ID);
|
|
501
|
-
} catch (err) {
|
|
502
|
-
this._destroyChannel(channel, err);
|
|
503
|
-
throw err;
|
|
504
|
-
}
|
|
505
|
-
return stream;
|
|
506
|
-
}
|
|
507
|
-
/**
|
|
508
|
-
* Creates an RPC port.
|
|
509
|
-
* The remote peer is expected to call `createPort` with the same tag.
|
|
510
|
-
* The port is immediately usable.
|
|
511
|
-
* NOTE: The data will be buffered until the stream is opened remotely with the same tag (may cause a memory leak).
|
|
512
|
-
*/
|
|
513
|
-
async createPort(tag, opts = {}) {
|
|
514
|
-
const channel = this._getOrCreateStream({
|
|
515
|
-
tag,
|
|
516
|
-
contentType: opts.contentType
|
|
517
|
-
});
|
|
518
|
-
(0, import_invariant3.invariant)(!channel.push, `Channel already open: ${tag}`, {
|
|
519
|
-
F: __dxlog_file3,
|
|
520
|
-
L: 192,
|
|
521
|
-
S: this,
|
|
522
|
-
A: [
|
|
523
|
-
"!channel.push",
|
|
524
|
-
"`Channel already open: ${tag}`"
|
|
525
|
-
]
|
|
526
|
-
});
|
|
527
|
-
let inboundBuffer = [];
|
|
528
|
-
let callback;
|
|
529
|
-
channel.push = (data) => {
|
|
530
|
-
channel.stats.bytesReceived += data.length;
|
|
531
|
-
if (callback) {
|
|
532
|
-
callback(data);
|
|
533
|
-
} else {
|
|
534
|
-
inboundBuffer.push(data);
|
|
535
|
-
}
|
|
536
|
-
};
|
|
537
|
-
const port = {
|
|
538
|
-
send: async (data, timeout) => {
|
|
539
|
-
await this._sendData(channel, data, timeout);
|
|
540
|
-
},
|
|
541
|
-
subscribe: (cb) => {
|
|
542
|
-
(0, import_invariant3.invariant)(!callback, "Only one subscriber is allowed", {
|
|
543
|
-
F: __dxlog_file3,
|
|
544
|
-
L: 214,
|
|
545
|
-
S: this,
|
|
546
|
-
A: [
|
|
547
|
-
"!callback",
|
|
548
|
-
"'Only one subscriber is allowed'"
|
|
549
|
-
]
|
|
550
|
-
});
|
|
551
|
-
callback = cb;
|
|
552
|
-
for (const data of inboundBuffer) {
|
|
553
|
-
cb(data);
|
|
554
|
-
}
|
|
555
|
-
inboundBuffer = [];
|
|
556
|
-
}
|
|
557
|
-
};
|
|
558
|
-
try {
|
|
559
|
-
await this._sendCommand({
|
|
560
|
-
openChannel: {
|
|
561
|
-
id: channel.id,
|
|
562
|
-
tag: channel.tag,
|
|
563
|
-
contentType: channel.contentType
|
|
564
|
-
}
|
|
565
|
-
}, SYSTEM_CHANNEL_ID);
|
|
566
|
-
} catch (err) {
|
|
567
|
-
this._destroyChannel(channel, err);
|
|
568
|
-
throw err;
|
|
569
|
-
}
|
|
570
|
-
return port;
|
|
571
|
-
}
|
|
572
|
-
// initiate graceful close
|
|
573
|
-
async close(err) {
|
|
574
|
-
if (this._destroying) {
|
|
575
|
-
(0, import_log3.log)("already destroying, ignoring graceful close request", void 0, {
|
|
576
|
-
F: __dxlog_file3,
|
|
577
|
-
L: 247,
|
|
578
|
-
S: this,
|
|
579
|
-
C: (f, a) => f(...a)
|
|
580
|
-
});
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
if (this._closing) {
|
|
584
|
-
(0, import_log3.log)("already closing, ignoring graceful close request", void 0, {
|
|
585
|
-
F: __dxlog_file3,
|
|
586
|
-
L: 251,
|
|
587
|
-
S: this,
|
|
588
|
-
C: (f, a) => f(...a)
|
|
589
|
-
});
|
|
590
|
-
return;
|
|
591
|
-
}
|
|
592
|
-
this._closing = true;
|
|
593
|
-
await this._sendCommand({
|
|
594
|
-
close: {
|
|
595
|
-
error: err?.message
|
|
596
|
-
}
|
|
597
|
-
}, SYSTEM_CHANNEL_ID, DESTROY_COMMAND_SEND_TIMEOUT).catch(async (err2) => {
|
|
598
|
-
(0, import_log3.log)("error sending close command", {
|
|
599
|
-
err: err2
|
|
600
|
-
}, {
|
|
601
|
-
F: __dxlog_file3,
|
|
602
|
-
L: 266,
|
|
603
|
-
S: this,
|
|
604
|
-
C: (f, a) => f(...a)
|
|
605
|
-
});
|
|
606
|
-
await this.dispose(err2);
|
|
607
|
-
});
|
|
608
|
-
await Promise.race([
|
|
609
|
-
new Promise((_resolve, reject) => {
|
|
610
|
-
setTimeout(() => {
|
|
611
|
-
reject(new import_protocols.TimeoutError("gracefully closing muxer"));
|
|
612
|
-
}, GRACEFUL_CLOSE_TIMEOUT);
|
|
613
|
-
}),
|
|
614
|
-
(async () => {
|
|
615
|
-
await this.dispose(err);
|
|
616
|
-
})()
|
|
617
|
-
]);
|
|
618
|
-
}
|
|
619
|
-
// force close without confirmation
|
|
620
|
-
async destroy(err) {
|
|
621
|
-
if (this._destroying) {
|
|
622
|
-
(0, import_log3.log)("already destroying, ignoring destroy request", void 0, {
|
|
623
|
-
F: __dxlog_file3,
|
|
624
|
-
L: 287,
|
|
625
|
-
S: this,
|
|
626
|
-
C: (f, a) => f(...a)
|
|
627
|
-
});
|
|
628
|
-
return;
|
|
629
|
-
}
|
|
630
|
-
this._destroying = true;
|
|
631
|
-
void this._ctx.dispose();
|
|
632
|
-
if (this._closing) {
|
|
633
|
-
(0, import_log3.log)("destroy cancelling graceful close", void 0, {
|
|
634
|
-
F: __dxlog_file3,
|
|
635
|
-
L: 293,
|
|
636
|
-
S: this,
|
|
637
|
-
C: (f, a) => f(...a)
|
|
638
|
-
});
|
|
639
|
-
this._closing = false;
|
|
640
|
-
} else {
|
|
641
|
-
await this._sendCommand({
|
|
642
|
-
close: {
|
|
643
|
-
error: err?.message
|
|
644
|
-
}
|
|
645
|
-
}, SYSTEM_CHANNEL_ID).catch(async (err2) => {
|
|
646
|
-
(0, import_log3.log)("error sending courtesy close command", {
|
|
647
|
-
err: err2
|
|
648
|
-
}, {
|
|
649
|
-
F: __dxlog_file3,
|
|
650
|
-
L: 306,
|
|
651
|
-
S: this,
|
|
652
|
-
C: (f, a) => f(...a)
|
|
653
|
-
});
|
|
654
|
-
});
|
|
655
|
-
}
|
|
656
|
-
this.dispose(err).catch((err2) => {
|
|
657
|
-
(0, import_log3.log)("error disposing after destroy", {
|
|
658
|
-
err: err2
|
|
659
|
-
}, {
|
|
660
|
-
F: __dxlog_file3,
|
|
661
|
-
L: 311,
|
|
662
|
-
S: this,
|
|
663
|
-
C: (f, a) => f(...a)
|
|
664
|
-
});
|
|
665
|
-
});
|
|
666
|
-
}
|
|
667
|
-
// complete the termination, graceful or otherwise
|
|
668
|
-
async dispose(err) {
|
|
669
|
-
if (this._disposed) {
|
|
670
|
-
(0, import_log3.log)("already destroyed, ignoring dispose request", void 0, {
|
|
671
|
-
F: __dxlog_file3,
|
|
672
|
-
L: 319,
|
|
673
|
-
S: this,
|
|
674
|
-
C: (f, a) => f(...a)
|
|
675
|
-
});
|
|
676
|
-
return;
|
|
677
|
-
}
|
|
678
|
-
void this._ctx.dispose();
|
|
679
|
-
await this._balancer.destroy();
|
|
680
|
-
for (const channel of this._channelsByTag.values()) {
|
|
681
|
-
channel.destroy?.(err);
|
|
682
|
-
}
|
|
683
|
-
this._disposed = true;
|
|
684
|
-
this.afterClosed.emit(err);
|
|
685
|
-
this._channelsByLocalId.clear();
|
|
686
|
-
this._channelsByTag.clear();
|
|
687
|
-
}
|
|
688
|
-
async _handleCommand(cmd) {
|
|
689
|
-
if (this._disposed) {
|
|
690
|
-
import_log3.log.warn("Received command after disposed", {
|
|
691
|
-
cmd
|
|
692
|
-
}, {
|
|
693
|
-
F: __dxlog_file3,
|
|
694
|
-
L: 341,
|
|
695
|
-
S: this,
|
|
696
|
-
C: (f, a) => f(...a)
|
|
697
|
-
});
|
|
698
|
-
return;
|
|
699
|
-
}
|
|
700
|
-
if (cmd.close) {
|
|
701
|
-
if (!this._closing) {
|
|
702
|
-
(0, import_log3.log)("received peer close, initiating my own graceful close", void 0, {
|
|
703
|
-
F: __dxlog_file3,
|
|
704
|
-
L: 347,
|
|
705
|
-
S: this,
|
|
706
|
-
C: (f, a) => f(...a)
|
|
707
|
-
});
|
|
708
|
-
await this.close();
|
|
709
|
-
} else {
|
|
710
|
-
(0, import_log3.log)("received close from peer, already closing", void 0, {
|
|
711
|
-
F: __dxlog_file3,
|
|
712
|
-
L: 350,
|
|
713
|
-
S: this,
|
|
714
|
-
C: (f, a) => f(...a)
|
|
715
|
-
});
|
|
716
|
-
}
|
|
717
|
-
return;
|
|
718
|
-
}
|
|
719
|
-
if (cmd.openChannel) {
|
|
720
|
-
const channel = this._getOrCreateStream({
|
|
721
|
-
tag: cmd.openChannel.tag,
|
|
722
|
-
contentType: cmd.openChannel.contentType
|
|
723
|
-
});
|
|
724
|
-
channel.remoteId = cmd.openChannel.id;
|
|
725
|
-
for (const data of channel.buffer) {
|
|
726
|
-
await this._sendCommand({
|
|
727
|
-
data: {
|
|
728
|
-
channelId: channel.remoteId,
|
|
729
|
-
data
|
|
730
|
-
}
|
|
731
|
-
}, channel.id);
|
|
732
|
-
}
|
|
733
|
-
channel.buffer = [];
|
|
734
|
-
} else if (cmd.data) {
|
|
735
|
-
const stream = this._channelsByLocalId.get(cmd.data.channelId) ?? (0, import_debug.failUndefined)();
|
|
736
|
-
if (!stream.push) {
|
|
737
|
-
import_log3.log.warn("Received data for channel before it was opened", {
|
|
738
|
-
tag: stream.tag
|
|
739
|
-
}, {
|
|
740
|
-
F: __dxlog_file3,
|
|
741
|
-
L: 379,
|
|
742
|
-
S: this,
|
|
743
|
-
C: (f, a) => f(...a)
|
|
744
|
-
});
|
|
745
|
-
return;
|
|
746
|
-
}
|
|
747
|
-
stream.push(cmd.data.data);
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
async _sendCommand(cmd, channelId = -1, timeout = DEFAULT_SEND_COMMAND_TIMEOUT) {
|
|
751
|
-
if (this._disposed) {
|
|
752
|
-
import_log3.log.info("ignoring sendCommand after disposed", {
|
|
753
|
-
cmd
|
|
754
|
-
}, {
|
|
755
|
-
F: __dxlog_file3,
|
|
756
|
-
L: 388,
|
|
757
|
-
S: this,
|
|
758
|
-
C: (f, a) => f(...a)
|
|
759
|
-
});
|
|
760
|
-
return;
|
|
761
|
-
}
|
|
762
|
-
try {
|
|
763
|
-
const trigger = new import_async3.Trigger();
|
|
764
|
-
this._balancer.pushData(Command.encode(cmd), trigger, channelId);
|
|
765
|
-
await trigger.wait({
|
|
766
|
-
timeout
|
|
767
|
-
});
|
|
768
|
-
} catch (err) {
|
|
769
|
-
await this.destroy(err);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
_getOrCreateStream(params) {
|
|
773
|
-
if (this._channelsByTag.size === 0) {
|
|
774
|
-
(0, import_async3.scheduleTaskInterval)(this._ctx, async () => this._emitStats(), STATS_INTERVAL);
|
|
775
|
-
}
|
|
776
|
-
let channel = this._channelsByTag.get(params.tag);
|
|
777
|
-
if (!channel) {
|
|
778
|
-
channel = {
|
|
779
|
-
id: this._nextId++,
|
|
780
|
-
remoteId: null,
|
|
781
|
-
tag: params.tag,
|
|
782
|
-
contentType: params.contentType,
|
|
783
|
-
buffer: [],
|
|
784
|
-
push: null,
|
|
785
|
-
destroy: null,
|
|
786
|
-
stats: {
|
|
787
|
-
bytesSent: 0,
|
|
788
|
-
bytesReceived: 0
|
|
789
|
-
}
|
|
790
|
-
};
|
|
791
|
-
this._channelsByTag.set(channel.tag, channel);
|
|
792
|
-
this._channelsByLocalId.set(channel.id, channel);
|
|
793
|
-
this._balancer.addChannel(channel.id);
|
|
794
|
-
}
|
|
795
|
-
return channel;
|
|
796
|
-
}
|
|
797
|
-
async _sendData(channel, data, timeout) {
|
|
798
|
-
if (data.length > MAX_SAFE_FRAME_SIZE) {
|
|
799
|
-
import_log3.log.warn("frame size exceeds maximum safe value", {
|
|
800
|
-
size: data.length,
|
|
801
|
-
threshold: MAX_SAFE_FRAME_SIZE
|
|
802
|
-
}, {
|
|
803
|
-
F: __dxlog_file3,
|
|
804
|
-
L: 429,
|
|
805
|
-
S: this,
|
|
806
|
-
C: (f, a) => f(...a)
|
|
807
|
-
});
|
|
808
|
-
}
|
|
809
|
-
channel.stats.bytesSent += data.length;
|
|
810
|
-
if (channel.remoteId === null) {
|
|
811
|
-
channel.buffer.push(data);
|
|
812
|
-
return;
|
|
813
|
-
}
|
|
814
|
-
await this._sendCommand({
|
|
815
|
-
data: {
|
|
816
|
-
channelId: channel.remoteId,
|
|
817
|
-
data
|
|
818
|
-
}
|
|
819
|
-
}, channel.id, timeout);
|
|
820
|
-
}
|
|
821
|
-
_destroyChannel(channel, err) {
|
|
822
|
-
if (channel.destroy) {
|
|
823
|
-
channel.destroy(err);
|
|
824
|
-
}
|
|
825
|
-
this._channelsByLocalId.delete(channel.id);
|
|
826
|
-
this._channelsByTag.delete(channel.tag);
|
|
827
|
-
}
|
|
828
|
-
async _emitStats() {
|
|
829
|
-
if (this._disposed || this._destroying) {
|
|
830
|
-
this._lastStats = void 0;
|
|
831
|
-
this._lastChannelStats.clear();
|
|
832
|
-
return;
|
|
833
|
-
}
|
|
834
|
-
const bytesSent = this._balancer.bytesSent;
|
|
835
|
-
const bytesReceived = this._balancer.bytesReceived;
|
|
836
|
-
const now = Date.now();
|
|
837
|
-
const interval = this._lastStats ? (now - this._lastStats.timestamp) / 1e3 : 0;
|
|
838
|
-
const calculateThroughput = (current, last) => last ? {
|
|
839
|
-
bytesSentRate: interval ? (current.bytesSent - last.bytesSent) / interval : void 0,
|
|
840
|
-
bytesReceivedRate: interval ? (current.bytesReceived - last.bytesReceived) / interval : void 0
|
|
841
|
-
} : {};
|
|
842
|
-
this._lastStats = {
|
|
843
|
-
timestamp: now,
|
|
844
|
-
channels: Array.from(this._channelsByTag.values()).map((channel) => {
|
|
845
|
-
const stats = {
|
|
846
|
-
id: channel.id,
|
|
847
|
-
tag: channel.tag,
|
|
848
|
-
contentType: channel.contentType,
|
|
849
|
-
writeBufferSize: channel.buffer.length,
|
|
850
|
-
bytesSent: channel.stats.bytesSent,
|
|
851
|
-
bytesReceived: channel.stats.bytesReceived,
|
|
852
|
-
...calculateThroughput(channel.stats, this._lastChannelStats.get(channel.id))
|
|
853
|
-
};
|
|
854
|
-
this._lastChannelStats.set(channel.id, stats);
|
|
855
|
-
return stats;
|
|
856
|
-
}),
|
|
857
|
-
bytesSent,
|
|
858
|
-
bytesReceived,
|
|
859
|
-
...calculateThroughput({
|
|
860
|
-
bytesSent,
|
|
861
|
-
bytesReceived
|
|
862
|
-
}, this._lastStats),
|
|
863
|
-
readBufferSize: this._balancer.stream.readableLength,
|
|
864
|
-
writeBufferSize: this._balancer.stream.writableLength
|
|
865
|
-
};
|
|
866
|
-
this.statsUpdated.emit(this._lastStats);
|
|
867
|
-
}
|
|
868
|
-
};
|
|
869
|
-
|
|
870
|
-
// packages/core/mesh/teleport/src/teleport.ts
|
|
871
|
-
var import_async5 = require("@dxos/async");
|
|
872
|
-
var import_context3 = require("@dxos/context");
|
|
873
|
-
var import_debug2 = require("@dxos/debug");
|
|
874
|
-
var import_invariant4 = require("@dxos/invariant");
|
|
875
|
-
var import_keys = require("@dxos/keys");
|
|
876
|
-
var import_log5 = require("@dxos/log");
|
|
877
|
-
var import_protocols3 = require("@dxos/protocols");
|
|
878
|
-
|
|
879
|
-
// packages/core/mesh/teleport/src/control-extension.ts
|
|
880
|
-
var import_async4 = require("@dxos/async");
|
|
881
|
-
var import_context2 = require("@dxos/context");
|
|
882
|
-
var import_log4 = require("@dxos/log");
|
|
883
|
-
var import_protocols2 = require("@dxos/protocols");
|
|
884
36
|
var import_rpc = require("@dxos/rpc");
|
|
885
|
-
var
|
|
886
|
-
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/control-extension.ts";
|
|
887
|
-
var HEARTBEAT_RTT_WARN_THRESH = 1e4;
|
|
888
|
-
var ControlExtension = class {
|
|
889
|
-
constructor(opts, localPeerId, remotePeerId) {
|
|
890
|
-
this.opts = opts;
|
|
891
|
-
this.localPeerId = localPeerId;
|
|
892
|
-
this.remotePeerId = remotePeerId;
|
|
893
|
-
this._ctx = new import_context2.Context({
|
|
894
|
-
onError: (err) => {
|
|
895
|
-
this._extensionContext.close(err);
|
|
896
|
-
}
|
|
897
|
-
});
|
|
898
|
-
this.onExtensionRegistered = new import_util.Callback();
|
|
899
|
-
}
|
|
900
|
-
async registerExtension(name) {
|
|
901
|
-
await this._rpc.rpc.Control.registerExtension({
|
|
902
|
-
name
|
|
903
|
-
});
|
|
904
|
-
}
|
|
905
|
-
async onOpen(extensionContext) {
|
|
906
|
-
this._extensionContext = extensionContext;
|
|
907
|
-
this._rpc = (0, import_rpc.createProtoRpcPeer)({
|
|
908
|
-
requested: {
|
|
909
|
-
Control: import_protocols2.schema.getService("dxos.mesh.teleport.control.ControlService")
|
|
910
|
-
},
|
|
911
|
-
exposed: {
|
|
912
|
-
Control: import_protocols2.schema.getService("dxos.mesh.teleport.control.ControlService")
|
|
913
|
-
},
|
|
914
|
-
handlers: {
|
|
915
|
-
Control: {
|
|
916
|
-
registerExtension: async (request) => {
|
|
917
|
-
this.onExtensionRegistered.call(request.name);
|
|
918
|
-
},
|
|
919
|
-
heartbeat: async (request) => {
|
|
920
|
-
(0, import_log4.log)("received heartbeat request", {
|
|
921
|
-
ts: request.requestTimestamp,
|
|
922
|
-
localPeerId: this.localPeerId.truncate(),
|
|
923
|
-
remotePeerId: this.remotePeerId.truncate()
|
|
924
|
-
}, {
|
|
925
|
-
F: __dxlog_file4,
|
|
926
|
-
L: 66,
|
|
927
|
-
S: this,
|
|
928
|
-
C: (f, a) => f(...a)
|
|
929
|
-
});
|
|
930
|
-
return {
|
|
931
|
-
requestTimestamp: request.requestTimestamp
|
|
932
|
-
};
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
},
|
|
936
|
-
port: await extensionContext.createPort("rpc", {
|
|
937
|
-
contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
|
|
938
|
-
}),
|
|
939
|
-
timeout: this.opts.heartbeatTimeout
|
|
940
|
-
});
|
|
941
|
-
await this._rpc.open();
|
|
942
|
-
(0, import_async4.scheduleTaskInterval)(this._ctx, async () => {
|
|
943
|
-
const reqTS = /* @__PURE__ */ new Date();
|
|
944
|
-
try {
|
|
945
|
-
const resp = await (0, import_async4.asyncTimeout)(this._rpc.rpc.Control.heartbeat({
|
|
946
|
-
requestTimestamp: reqTS
|
|
947
|
-
}), this.opts.heartbeatTimeout);
|
|
948
|
-
const now = Date.now();
|
|
949
|
-
if (resp.requestTimestamp instanceof Date) {
|
|
950
|
-
if (now - resp.requestTimestamp.getTime() > (HEARTBEAT_RTT_WARN_THRESH < this.opts.heartbeatTimeout ? HEARTBEAT_RTT_WARN_THRESH : this.opts.heartbeatTimeout / 2)) {
|
|
951
|
-
import_log4.log.warn(`heartbeat RTT for Teleport > ${HEARTBEAT_RTT_WARN_THRESH / 1e3}s`, {
|
|
952
|
-
rtt: now - resp.requestTimestamp.getTime(),
|
|
953
|
-
localPeerId: this.localPeerId.truncate(),
|
|
954
|
-
remotePeerId: this.remotePeerId.truncate()
|
|
955
|
-
}, {
|
|
956
|
-
F: __dxlog_file4,
|
|
957
|
-
L: 103,
|
|
958
|
-
S: this,
|
|
959
|
-
C: (f, a) => f(...a)
|
|
960
|
-
});
|
|
961
|
-
} else {
|
|
962
|
-
(0, import_log4.log)("heartbeat RTT", {
|
|
963
|
-
rtt: now - resp.requestTimestamp.getTime(),
|
|
964
|
-
localPeerId: this.localPeerId.truncate(),
|
|
965
|
-
remotePeerId: this.remotePeerId.truncate()
|
|
966
|
-
}, {
|
|
967
|
-
F: __dxlog_file4,
|
|
968
|
-
L: 109,
|
|
969
|
-
S: this,
|
|
970
|
-
C: (f, a) => f(...a)
|
|
971
|
-
});
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
} catch (err) {
|
|
975
|
-
const now = Date.now();
|
|
976
|
-
if (err instanceof import_protocols2.RpcClosedError) {
|
|
977
|
-
(0, import_log4.log)("ignoring RpcClosedError in heartbeat", void 0, {
|
|
978
|
-
F: __dxlog_file4,
|
|
979
|
-
L: 119,
|
|
980
|
-
S: this,
|
|
981
|
-
C: (f, a) => f(...a)
|
|
982
|
-
});
|
|
983
|
-
return;
|
|
984
|
-
}
|
|
985
|
-
if (err instanceof import_async4.TimeoutError) {
|
|
986
|
-
(0, import_log4.log)("timeout waiting for heartbeat response", {
|
|
987
|
-
err,
|
|
988
|
-
delay: now - reqTS.getTime()
|
|
989
|
-
}, {
|
|
990
|
-
F: __dxlog_file4,
|
|
991
|
-
L: 123,
|
|
992
|
-
S: this,
|
|
993
|
-
C: (f, a) => f(...a)
|
|
994
|
-
});
|
|
995
|
-
this.opts.onTimeout(err);
|
|
996
|
-
} else {
|
|
997
|
-
import_log4.log.info("other error waiting for heartbeat response", {
|
|
998
|
-
err,
|
|
999
|
-
delay: now - reqTS.getTime()
|
|
1000
|
-
}, {
|
|
1001
|
-
F: __dxlog_file4,
|
|
1002
|
-
L: 126,
|
|
1003
|
-
S: this,
|
|
1004
|
-
C: (f, a) => f(...a)
|
|
1005
|
-
});
|
|
1006
|
-
this.opts.onTimeout(err);
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
}, this.opts.heartbeatInterval);
|
|
1010
|
-
}
|
|
1011
|
-
async onClose(err) {
|
|
1012
|
-
await this._ctx.dispose();
|
|
1013
|
-
await this._rpc.close();
|
|
1014
|
-
}
|
|
1015
|
-
async onAbort(err) {
|
|
1016
|
-
await this._ctx.dispose();
|
|
1017
|
-
await this._rpc.abort();
|
|
1018
|
-
}
|
|
1019
|
-
};
|
|
1020
|
-
|
|
1021
|
-
// packages/core/mesh/teleport/src/teleport.ts
|
|
1022
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
1023
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1024
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
1025
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
1026
|
-
else
|
|
1027
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
1028
|
-
if (d = decorators[i])
|
|
1029
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1030
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1031
|
-
}
|
|
1032
|
-
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts";
|
|
1033
|
-
var CONTROL_HEARTBEAT_INTERVAL = 1e4;
|
|
1034
|
-
var CONTROL_HEARTBEAT_TIMEOUT = 6e4;
|
|
1035
|
-
var Teleport = class {
|
|
1036
|
-
constructor({ initiator, localPeerId, remotePeerId }) {
|
|
1037
|
-
this._ctx = new import_context3.Context({
|
|
1038
|
-
onError: (err) => {
|
|
1039
|
-
void this.destroy(err).catch(() => {
|
|
1040
|
-
import_log5.log.error("Error during destroy", err, {
|
|
1041
|
-
F: __dxlog_file5,
|
|
1042
|
-
L: 38,
|
|
1043
|
-
S: this,
|
|
1044
|
-
C: (f, a) => f(...a)
|
|
1045
|
-
});
|
|
1046
|
-
});
|
|
1047
|
-
}
|
|
1048
|
-
});
|
|
1049
|
-
this._muxer = new Muxer();
|
|
1050
|
-
this._extensions = /* @__PURE__ */ new Map();
|
|
1051
|
-
this._remoteExtensions = /* @__PURE__ */ new Set();
|
|
1052
|
-
this._open = false;
|
|
1053
|
-
this._destroying = false;
|
|
1054
|
-
this._aborting = false;
|
|
1055
|
-
(0, import_invariant4.invariant)(typeof initiator === "boolean", void 0, {
|
|
1056
|
-
F: __dxlog_file5,
|
|
1057
|
-
L: 55,
|
|
1058
|
-
S: this,
|
|
1059
|
-
A: [
|
|
1060
|
-
"typeof initiator === 'boolean'",
|
|
1061
|
-
""
|
|
1062
|
-
]
|
|
1063
|
-
});
|
|
1064
|
-
(0, import_invariant4.invariant)(import_keys.PublicKey.isPublicKey(localPeerId), void 0, {
|
|
1065
|
-
F: __dxlog_file5,
|
|
1066
|
-
L: 56,
|
|
1067
|
-
S: this,
|
|
1068
|
-
A: [
|
|
1069
|
-
"PublicKey.isPublicKey(localPeerId)",
|
|
1070
|
-
""
|
|
1071
|
-
]
|
|
1072
|
-
});
|
|
1073
|
-
(0, import_invariant4.invariant)(import_keys.PublicKey.isPublicKey(remotePeerId), void 0, {
|
|
1074
|
-
F: __dxlog_file5,
|
|
1075
|
-
L: 57,
|
|
1076
|
-
S: this,
|
|
1077
|
-
A: [
|
|
1078
|
-
"PublicKey.isPublicKey(remotePeerId)",
|
|
1079
|
-
""
|
|
1080
|
-
]
|
|
1081
|
-
});
|
|
1082
|
-
this.initiator = initiator;
|
|
1083
|
-
this.localPeerId = localPeerId;
|
|
1084
|
-
this.remotePeerId = remotePeerId;
|
|
1085
|
-
this._control = new ControlExtension({
|
|
1086
|
-
heartbeatInterval: CONTROL_HEARTBEAT_INTERVAL,
|
|
1087
|
-
heartbeatTimeout: CONTROL_HEARTBEAT_TIMEOUT,
|
|
1088
|
-
onTimeout: () => {
|
|
1089
|
-
if (this._destroying || this._aborting) {
|
|
1090
|
-
return;
|
|
1091
|
-
}
|
|
1092
|
-
import_log5.log.info("abort teleport due to onTimeout in ControlExtension", void 0, {
|
|
1093
|
-
F: __dxlog_file5,
|
|
1094
|
-
L: 70,
|
|
1095
|
-
S: this,
|
|
1096
|
-
C: (f, a) => f(...a)
|
|
1097
|
-
});
|
|
1098
|
-
this.abort(new import_protocols3.TimeoutError("control extension")).catch((err) => import_log5.log.catch(err, void 0, {
|
|
1099
|
-
F: __dxlog_file5,
|
|
1100
|
-
L: 71,
|
|
1101
|
-
S: this,
|
|
1102
|
-
C: (f, a) => f(...a)
|
|
1103
|
-
}));
|
|
1104
|
-
}
|
|
1105
|
-
}, this.localPeerId, this.remotePeerId);
|
|
1106
|
-
this._control.onExtensionRegistered.set(async (name) => {
|
|
1107
|
-
(0, import_log5.log)("remote extension", {
|
|
1108
|
-
name
|
|
1109
|
-
}, {
|
|
1110
|
-
F: __dxlog_file5,
|
|
1111
|
-
L: 79,
|
|
1112
|
-
S: this,
|
|
1113
|
-
C: (f, a) => f(...a)
|
|
1114
|
-
});
|
|
1115
|
-
(0, import_invariant4.invariant)(!this._remoteExtensions.has(name), "Remote extension already exists", {
|
|
1116
|
-
F: __dxlog_file5,
|
|
1117
|
-
L: 80,
|
|
1118
|
-
S: this,
|
|
1119
|
-
A: [
|
|
1120
|
-
"!this._remoteExtensions.has(name)",
|
|
1121
|
-
"'Remote extension already exists'"
|
|
1122
|
-
]
|
|
1123
|
-
});
|
|
1124
|
-
this._remoteExtensions.add(name);
|
|
1125
|
-
if (this._extensions.has(name)) {
|
|
1126
|
-
try {
|
|
1127
|
-
await this._openExtension(name);
|
|
1128
|
-
} catch (err) {
|
|
1129
|
-
await this.destroy(err);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
});
|
|
1133
|
-
{
|
|
1134
|
-
this._muxer.stream.on("close", async () => {
|
|
1135
|
-
if (this._destroying || this._aborting) {
|
|
1136
|
-
(0, import_log5.log)("destroy teleport due to muxer stream close, skipping due to already destroying/aborting", void 0, {
|
|
1137
|
-
F: __dxlog_file5,
|
|
1138
|
-
L: 96,
|
|
1139
|
-
S: this,
|
|
1140
|
-
C: (f, a) => f(...a)
|
|
1141
|
-
});
|
|
1142
|
-
return;
|
|
1143
|
-
}
|
|
1144
|
-
await this.destroy();
|
|
1145
|
-
});
|
|
1146
|
-
this._muxer.stream.on("error", async (err) => {
|
|
1147
|
-
await this.destroy(err);
|
|
1148
|
-
});
|
|
1149
|
-
}
|
|
1150
|
-
this._muxer.statsUpdated.on((stats) => {
|
|
1151
|
-
import_log5.log.trace("dxos.mesh.teleport.stats", {
|
|
1152
|
-
localPeerId,
|
|
1153
|
-
remotePeerId,
|
|
1154
|
-
bytesSent: stats.bytesSent,
|
|
1155
|
-
bytesSentRate: stats.bytesSentRate,
|
|
1156
|
-
bytesReceived: stats.bytesReceived,
|
|
1157
|
-
bytesReceivedRate: stats.bytesReceivedRate,
|
|
1158
|
-
channels: stats.channels
|
|
1159
|
-
}, {
|
|
1160
|
-
F: __dxlog_file5,
|
|
1161
|
-
L: 109,
|
|
1162
|
-
S: this,
|
|
1163
|
-
C: (f, a) => f(...a)
|
|
1164
|
-
});
|
|
1165
|
-
});
|
|
1166
|
-
}
|
|
1167
|
-
get stream() {
|
|
1168
|
-
return this._muxer.stream;
|
|
1169
|
-
}
|
|
1170
|
-
get stats() {
|
|
1171
|
-
return this._muxer.statsUpdated;
|
|
1172
|
-
}
|
|
1173
|
-
/**
|
|
1174
|
-
* Blocks until the handshake is complete.
|
|
1175
|
-
*/
|
|
1176
|
-
async open() {
|
|
1177
|
-
this._setExtension("dxos.mesh.teleport.control", this._control);
|
|
1178
|
-
await this._openExtension("dxos.mesh.teleport.control");
|
|
1179
|
-
this._open = true;
|
|
1180
|
-
}
|
|
1181
|
-
async close(err) {
|
|
1182
|
-
await this.destroy(err);
|
|
1183
|
-
}
|
|
1184
|
-
async abort(err) {
|
|
1185
|
-
if (this._aborting || this._destroying) {
|
|
1186
|
-
return;
|
|
1187
|
-
}
|
|
1188
|
-
this._aborting = true;
|
|
1189
|
-
if (this._ctx.disposed) {
|
|
1190
|
-
return;
|
|
1191
|
-
}
|
|
1192
|
-
await this._ctx.dispose();
|
|
1193
|
-
for (const extension of this._extensions.values()) {
|
|
1194
|
-
try {
|
|
1195
|
-
await extension.onAbort(err);
|
|
1196
|
-
} catch (err2) {
|
|
1197
|
-
import_log5.log.catch(err2, void 0, {
|
|
1198
|
-
F: __dxlog_file5,
|
|
1199
|
-
L: 162,
|
|
1200
|
-
S: this,
|
|
1201
|
-
C: (f, a) => f(...a)
|
|
1202
|
-
});
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
await this._muxer.destroy(err);
|
|
1206
|
-
}
|
|
1207
|
-
async destroy(err) {
|
|
1208
|
-
if (this._destroying || this._aborting) {
|
|
1209
|
-
return;
|
|
1210
|
-
}
|
|
1211
|
-
this._destroying = true;
|
|
1212
|
-
if (this._ctx.disposed) {
|
|
1213
|
-
return;
|
|
1214
|
-
}
|
|
1215
|
-
await this._ctx.dispose();
|
|
1216
|
-
for (const extension of this._extensions.values()) {
|
|
1217
|
-
try {
|
|
1218
|
-
await extension.onClose(err);
|
|
1219
|
-
} catch (err2) {
|
|
1220
|
-
import_log5.log.catch(err2, void 0, {
|
|
1221
|
-
F: __dxlog_file5,
|
|
1222
|
-
L: 186,
|
|
1223
|
-
S: this,
|
|
1224
|
-
C: (f, a) => f(...a)
|
|
1225
|
-
});
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
await this._muxer.close();
|
|
1229
|
-
}
|
|
1230
|
-
addExtension(name, extension) {
|
|
1231
|
-
if (!this._open) {
|
|
1232
|
-
throw new Error("Not open");
|
|
1233
|
-
}
|
|
1234
|
-
(0, import_log5.log)("addExtension", {
|
|
1235
|
-
name
|
|
1236
|
-
}, {
|
|
1237
|
-
F: __dxlog_file5,
|
|
1238
|
-
L: 198,
|
|
1239
|
-
S: this,
|
|
1240
|
-
C: (f, a) => f(...a)
|
|
1241
|
-
});
|
|
1242
|
-
this._setExtension(name, extension);
|
|
1243
|
-
(0, import_async5.scheduleTask)(this._ctx, async () => {
|
|
1244
|
-
try {
|
|
1245
|
-
await this._control.registerExtension(name);
|
|
1246
|
-
} catch (err) {
|
|
1247
|
-
if (err instanceof import_protocols3.RpcClosedError) {
|
|
1248
|
-
return;
|
|
1249
|
-
}
|
|
1250
|
-
throw err;
|
|
1251
|
-
}
|
|
1252
|
-
});
|
|
1253
|
-
if (this._remoteExtensions.has(name)) {
|
|
1254
|
-
(0, import_async5.scheduleTask)(this._ctx, async () => {
|
|
1255
|
-
await this._openExtension(name);
|
|
1256
|
-
});
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
_setExtension(extensionName, extension) {
|
|
1260
|
-
(0, import_invariant4.invariant)(!extensionName.includes("/"), "Invalid extension name", {
|
|
1261
|
-
F: __dxlog_file5,
|
|
1262
|
-
L: 222,
|
|
1263
|
-
S: this,
|
|
1264
|
-
A: [
|
|
1265
|
-
"!extensionName.includes('/')",
|
|
1266
|
-
"'Invalid extension name'"
|
|
1267
|
-
]
|
|
1268
|
-
});
|
|
1269
|
-
(0, import_invariant4.invariant)(!this._extensions.has(extensionName), "Extension already exists", {
|
|
1270
|
-
F: __dxlog_file5,
|
|
1271
|
-
L: 223,
|
|
1272
|
-
S: this,
|
|
1273
|
-
A: [
|
|
1274
|
-
"!this._extensions.has(extensionName)",
|
|
1275
|
-
"'Extension already exists'"
|
|
1276
|
-
]
|
|
1277
|
-
});
|
|
1278
|
-
this._extensions.set(extensionName, extension);
|
|
1279
|
-
}
|
|
1280
|
-
async _openExtension(extensionName) {
|
|
1281
|
-
(0, import_log5.log)("open extension", {
|
|
1282
|
-
extensionName
|
|
1283
|
-
}, {
|
|
1284
|
-
F: __dxlog_file5,
|
|
1285
|
-
L: 228,
|
|
1286
|
-
S: this,
|
|
1287
|
-
C: (f, a) => f(...a)
|
|
1288
|
-
});
|
|
1289
|
-
const extension = this._extensions.get(extensionName) ?? (0, import_debug2.failUndefined)();
|
|
1290
|
-
const context = {
|
|
1291
|
-
initiator: this.initiator,
|
|
1292
|
-
localPeerId: this.localPeerId,
|
|
1293
|
-
remotePeerId: this.remotePeerId,
|
|
1294
|
-
createPort: async (channelName, opts) => {
|
|
1295
|
-
(0, import_invariant4.invariant)(!channelName.includes("/"), "Invalid channel name", {
|
|
1296
|
-
F: __dxlog_file5,
|
|
1297
|
-
L: 236,
|
|
1298
|
-
S: this,
|
|
1299
|
-
A: [
|
|
1300
|
-
"!channelName.includes('/')",
|
|
1301
|
-
"'Invalid channel name'"
|
|
1302
|
-
]
|
|
1303
|
-
});
|
|
1304
|
-
return this._muxer.createPort(`${extensionName}/${channelName}`, opts);
|
|
1305
|
-
},
|
|
1306
|
-
createStream: async (channelName, opts) => {
|
|
1307
|
-
(0, import_invariant4.invariant)(!channelName.includes("/"), "Invalid channel name", {
|
|
1308
|
-
F: __dxlog_file5,
|
|
1309
|
-
L: 240,
|
|
1310
|
-
S: this,
|
|
1311
|
-
A: [
|
|
1312
|
-
"!channelName.includes('/')",
|
|
1313
|
-
"'Invalid channel name'"
|
|
1314
|
-
]
|
|
1315
|
-
});
|
|
1316
|
-
return this._muxer.createStream(`${extensionName}/${channelName}`, opts);
|
|
1317
|
-
},
|
|
1318
|
-
close: (err) => {
|
|
1319
|
-
void (0, import_async5.runInContextAsync)(this._ctx, async () => {
|
|
1320
|
-
await this.close(err);
|
|
1321
|
-
});
|
|
1322
|
-
}
|
|
1323
|
-
};
|
|
1324
|
-
await extension.onOpen(context);
|
|
1325
|
-
(0, import_log5.log)("extension opened", {
|
|
1326
|
-
extensionName
|
|
1327
|
-
}, {
|
|
1328
|
-
F: __dxlog_file5,
|
|
1329
|
-
L: 251,
|
|
1330
|
-
S: this,
|
|
1331
|
-
C: (f, a) => f(...a)
|
|
1332
|
-
});
|
|
1333
|
-
}
|
|
1334
|
-
};
|
|
1335
|
-
_ts_decorate([
|
|
1336
|
-
import_async5.synchronized
|
|
1337
|
-
], Teleport.prototype, "abort", null);
|
|
1338
|
-
_ts_decorate([
|
|
1339
|
-
import_async5.synchronized
|
|
1340
|
-
], Teleport.prototype, "destroy", null);
|
|
1341
|
-
|
|
1342
|
-
// packages/core/mesh/teleport/src/testing/test-builder.ts
|
|
1343
|
-
var import_node_stream3 = require("node:stream");
|
|
1344
|
-
var import_invariant5 = require("@dxos/invariant");
|
|
1345
|
-
var import_keys2 = require("@dxos/keys");
|
|
1346
|
-
var import_log6 = require("@dxos/log");
|
|
1347
|
-
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/testing/test-builder.ts";
|
|
1348
|
-
var TestBuilder = class {
|
|
1349
|
-
constructor() {
|
|
1350
|
-
this._peers = /* @__PURE__ */ new Set();
|
|
1351
|
-
}
|
|
1352
|
-
createPeer(opts) {
|
|
1353
|
-
const peer = opts.factory();
|
|
1354
|
-
this._peers.add(peer);
|
|
1355
|
-
return peer;
|
|
1356
|
-
}
|
|
1357
|
-
*createPeers(opts) {
|
|
1358
|
-
while (true) {
|
|
1359
|
-
yield this.createPeer(opts);
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
async destroy() {
|
|
1363
|
-
await Promise.all(Array.from(this._peers).map((agent) => agent.destroy()));
|
|
1364
|
-
}
|
|
1365
|
-
async connect(peer1, peer2) {
|
|
1366
|
-
(0, import_invariant5.invariant)(peer1 !== peer2, void 0, {
|
|
1367
|
-
F: __dxlog_file6,
|
|
1368
|
-
L: 37,
|
|
1369
|
-
S: this,
|
|
1370
|
-
A: [
|
|
1371
|
-
"peer1 !== peer2",
|
|
1372
|
-
""
|
|
1373
|
-
]
|
|
1374
|
-
});
|
|
1375
|
-
(0, import_invariant5.invariant)(this._peers.has(peer1), void 0, {
|
|
1376
|
-
F: __dxlog_file6,
|
|
1377
|
-
L: 38,
|
|
1378
|
-
S: this,
|
|
1379
|
-
A: [
|
|
1380
|
-
"this._peers.has(peer1)",
|
|
1381
|
-
""
|
|
1382
|
-
]
|
|
1383
|
-
});
|
|
1384
|
-
(0, import_invariant5.invariant)(this._peers.has(peer1), void 0, {
|
|
1385
|
-
F: __dxlog_file6,
|
|
1386
|
-
L: 39,
|
|
1387
|
-
S: this,
|
|
1388
|
-
A: [
|
|
1389
|
-
"this._peers.has(peer1)",
|
|
1390
|
-
""
|
|
1391
|
-
]
|
|
1392
|
-
});
|
|
1393
|
-
const connection1 = peer1.createConnection({
|
|
1394
|
-
initiator: true,
|
|
1395
|
-
remotePeerId: peer2.peerId
|
|
1396
|
-
});
|
|
1397
|
-
const connection2 = peer2.createConnection({
|
|
1398
|
-
initiator: false,
|
|
1399
|
-
remotePeerId: peer1.peerId
|
|
1400
|
-
});
|
|
1401
|
-
pipeStreams(connection1.teleport.stream, connection2.teleport.stream);
|
|
1402
|
-
await Promise.all([
|
|
1403
|
-
peer1.openConnection(connection1),
|
|
1404
|
-
peer2.openConnection(connection2)
|
|
1405
|
-
]);
|
|
1406
|
-
return [
|
|
1407
|
-
connection1,
|
|
1408
|
-
connection2
|
|
1409
|
-
];
|
|
1410
|
-
}
|
|
1411
|
-
async disconnect(peer1, peer2) {
|
|
1412
|
-
(0, import_invariant5.invariant)(peer1 !== peer2, void 0, {
|
|
1413
|
-
F: __dxlog_file6,
|
|
1414
|
-
L: 51,
|
|
1415
|
-
S: this,
|
|
1416
|
-
A: [
|
|
1417
|
-
"peer1 !== peer2",
|
|
1418
|
-
""
|
|
1419
|
-
]
|
|
1420
|
-
});
|
|
1421
|
-
(0, import_invariant5.invariant)(this._peers.has(peer1), void 0, {
|
|
1422
|
-
F: __dxlog_file6,
|
|
1423
|
-
L: 52,
|
|
1424
|
-
S: this,
|
|
1425
|
-
A: [
|
|
1426
|
-
"this._peers.has(peer1)",
|
|
1427
|
-
""
|
|
1428
|
-
]
|
|
1429
|
-
});
|
|
1430
|
-
(0, import_invariant5.invariant)(this._peers.has(peer1), void 0, {
|
|
1431
|
-
F: __dxlog_file6,
|
|
1432
|
-
L: 53,
|
|
1433
|
-
S: this,
|
|
1434
|
-
A: [
|
|
1435
|
-
"this._peers.has(peer1)",
|
|
1436
|
-
""
|
|
1437
|
-
]
|
|
1438
|
-
});
|
|
1439
|
-
const connection1 = Array.from(peer1.connections).find((connection) => connection.remotePeerId.equals(peer2.peerId));
|
|
1440
|
-
const connection2 = Array.from(peer2.connections).find((connection) => connection.remotePeerId.equals(peer1.peerId));
|
|
1441
|
-
(0, import_invariant5.invariant)(connection1, void 0, {
|
|
1442
|
-
F: __dxlog_file6,
|
|
1443
|
-
L: 62,
|
|
1444
|
-
S: this,
|
|
1445
|
-
A: [
|
|
1446
|
-
"connection1",
|
|
1447
|
-
""
|
|
1448
|
-
]
|
|
1449
|
-
});
|
|
1450
|
-
(0, import_invariant5.invariant)(connection2, void 0, {
|
|
1451
|
-
F: __dxlog_file6,
|
|
1452
|
-
L: 63,
|
|
1453
|
-
S: this,
|
|
1454
|
-
A: [
|
|
1455
|
-
"connection2",
|
|
1456
|
-
""
|
|
1457
|
-
]
|
|
1458
|
-
});
|
|
1459
|
-
await Promise.all([
|
|
1460
|
-
peer1.closeConnection(connection1),
|
|
1461
|
-
peer2.closeConnection(connection2)
|
|
1462
|
-
]);
|
|
1463
|
-
}
|
|
1464
|
-
};
|
|
1465
|
-
var TestPeer = class {
|
|
1466
|
-
constructor(peerId = import_keys2.PublicKey.random()) {
|
|
1467
|
-
this.peerId = peerId;
|
|
1468
|
-
this.connections = /* @__PURE__ */ new Set();
|
|
1469
|
-
}
|
|
1470
|
-
async onOpen(connection) {
|
|
1471
|
-
}
|
|
1472
|
-
async onClose(connection) {
|
|
1473
|
-
}
|
|
1474
|
-
createConnection({ initiator, remotePeerId }) {
|
|
1475
|
-
const connection = new TestConnection(this.peerId, remotePeerId, initiator);
|
|
1476
|
-
this.connections.add(connection);
|
|
1477
|
-
return connection;
|
|
1478
|
-
}
|
|
1479
|
-
async openConnection(connection) {
|
|
1480
|
-
(0, import_invariant5.invariant)(this.connections.has(connection), void 0, {
|
|
1481
|
-
F: __dxlog_file6,
|
|
1482
|
-
L: 84,
|
|
1483
|
-
S: this,
|
|
1484
|
-
A: [
|
|
1485
|
-
"this.connections.has(connection)",
|
|
1486
|
-
""
|
|
1487
|
-
]
|
|
1488
|
-
});
|
|
1489
|
-
await connection.teleport.open();
|
|
1490
|
-
await this.onOpen(connection);
|
|
1491
|
-
}
|
|
1492
|
-
async closeConnection(connection) {
|
|
1493
|
-
(0, import_invariant5.invariant)(this.connections.has(connection), void 0, {
|
|
1494
|
-
F: __dxlog_file6,
|
|
1495
|
-
L: 90,
|
|
1496
|
-
S: this,
|
|
1497
|
-
A: [
|
|
1498
|
-
"this.connections.has(connection)",
|
|
1499
|
-
""
|
|
1500
|
-
]
|
|
1501
|
-
});
|
|
1502
|
-
await this.onClose(connection);
|
|
1503
|
-
await connection.teleport.close();
|
|
1504
|
-
this.connections.delete(connection);
|
|
1505
|
-
}
|
|
1506
|
-
async destroy() {
|
|
1507
|
-
for (const teleport of this.connections) {
|
|
1508
|
-
await this.closeConnection(teleport);
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
};
|
|
1512
|
-
var pipeStreams = (stream1, stream2) => {
|
|
1513
|
-
(0, import_node_stream3.pipeline)(stream1, stream2, (err) => {
|
|
1514
|
-
if (err && err.code !== "ERR_STREAM_PREMATURE_CLOSE") {
|
|
1515
|
-
import_log6.log.catch(err, void 0, {
|
|
1516
|
-
F: __dxlog_file6,
|
|
1517
|
-
L: 106,
|
|
1518
|
-
S: void 0,
|
|
1519
|
-
C: (f, a) => f(...a)
|
|
1520
|
-
});
|
|
1521
|
-
}
|
|
1522
|
-
});
|
|
1523
|
-
(0, import_node_stream3.pipeline)(stream2, stream1, (err) => {
|
|
1524
|
-
if (err && err.code !== "ERR_STREAM_PREMATURE_CLOSE") {
|
|
1525
|
-
import_log6.log.catch(err, void 0, {
|
|
1526
|
-
F: __dxlog_file6,
|
|
1527
|
-
L: 111,
|
|
1528
|
-
S: void 0,
|
|
1529
|
-
C: (f, a) => f(...a)
|
|
1530
|
-
});
|
|
1531
|
-
}
|
|
1532
|
-
});
|
|
1533
|
-
};
|
|
1534
|
-
var TestConnection = class {
|
|
1535
|
-
constructor(localPeerId, remotePeerId, initiator) {
|
|
1536
|
-
this.localPeerId = localPeerId;
|
|
1537
|
-
this.remotePeerId = remotePeerId;
|
|
1538
|
-
this.initiator = initiator;
|
|
1539
|
-
this.teleport = new Teleport({
|
|
1540
|
-
initiator,
|
|
1541
|
-
localPeerId,
|
|
1542
|
-
remotePeerId
|
|
1543
|
-
});
|
|
1544
|
-
}
|
|
1545
|
-
};
|
|
1546
|
-
|
|
1547
|
-
// packages/core/mesh/teleport/src/testing/test-extension.ts
|
|
1548
|
-
var import_async6 = require("@dxos/async");
|
|
1549
|
-
var import_invariant6 = require("@dxos/invariant");
|
|
1550
|
-
var import_log7 = require("@dxos/log");
|
|
1551
|
-
var import_protocols4 = require("@dxos/protocols");
|
|
1552
|
-
var import_rpc2 = require("@dxos/rpc");
|
|
1553
|
-
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/testing/test-extension.ts";
|
|
1554
|
-
var TestExtension = class {
|
|
1555
|
-
constructor(callbacks = {}) {
|
|
1556
|
-
this.callbacks = callbacks;
|
|
1557
|
-
this.open = new import_async6.Trigger();
|
|
1558
|
-
this.closed = new import_async6.Trigger();
|
|
1559
|
-
this.aborted = new import_async6.Trigger();
|
|
1560
|
-
}
|
|
1561
|
-
get remotePeerId() {
|
|
1562
|
-
return this.extensionContext?.remotePeerId;
|
|
1563
|
-
}
|
|
1564
|
-
async onOpen(context) {
|
|
1565
|
-
(0, import_log7.log)("onOpen", {
|
|
1566
|
-
localPeerId: context.localPeerId,
|
|
1567
|
-
remotePeerId: context.remotePeerId
|
|
1568
|
-
}, {
|
|
1569
|
-
F: __dxlog_file7,
|
|
1570
|
-
L: 34,
|
|
1571
|
-
S: this,
|
|
1572
|
-
C: (f, a) => f(...a)
|
|
1573
|
-
});
|
|
1574
|
-
this.extensionContext = context;
|
|
1575
|
-
this._rpc = (0, import_rpc2.createProtoRpcPeer)({
|
|
1576
|
-
port: await context.createPort("rpc", {
|
|
1577
|
-
contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
|
|
1578
|
-
}),
|
|
1579
|
-
requested: {
|
|
1580
|
-
TestService: import_protocols4.schema.getService("example.testing.rpc.TestService")
|
|
1581
|
-
},
|
|
1582
|
-
exposed: {
|
|
1583
|
-
TestService: import_protocols4.schema.getService("example.testing.rpc.TestService")
|
|
1584
|
-
},
|
|
1585
|
-
handlers: {
|
|
1586
|
-
TestService: {
|
|
1587
|
-
voidCall: async (request) => {
|
|
1588
|
-
},
|
|
1589
|
-
testCall: async (request) => {
|
|
1590
|
-
return {
|
|
1591
|
-
data: request.data
|
|
1592
|
-
};
|
|
1593
|
-
}
|
|
1594
|
-
}
|
|
1595
|
-
},
|
|
1596
|
-
timeout: 2e3
|
|
1597
|
-
});
|
|
1598
|
-
await this._rpc.open();
|
|
1599
|
-
await this.callbacks.onOpen?.();
|
|
1600
|
-
this.open.wake();
|
|
1601
|
-
}
|
|
1602
|
-
async onClose(err) {
|
|
1603
|
-
(0, import_log7.log)("onClose", {
|
|
1604
|
-
err
|
|
1605
|
-
}, {
|
|
1606
|
-
F: __dxlog_file7,
|
|
1607
|
-
L: 68,
|
|
1608
|
-
S: this,
|
|
1609
|
-
C: (f, a) => f(...a)
|
|
1610
|
-
});
|
|
1611
|
-
await this.callbacks.onClose?.();
|
|
1612
|
-
this.closed.wake();
|
|
1613
|
-
await this._rpc?.close();
|
|
1614
|
-
}
|
|
1615
|
-
async onAbort(err) {
|
|
1616
|
-
(0, import_log7.log)("onAbort", {
|
|
1617
|
-
err
|
|
1618
|
-
}, {
|
|
1619
|
-
F: __dxlog_file7,
|
|
1620
|
-
L: 75,
|
|
1621
|
-
S: this,
|
|
1622
|
-
C: (f, a) => f(...a)
|
|
1623
|
-
});
|
|
1624
|
-
await this.callbacks.onAbort?.();
|
|
1625
|
-
this.aborted.wake();
|
|
1626
|
-
await this._rpc?.abort();
|
|
1627
|
-
}
|
|
1628
|
-
async test(message = "test") {
|
|
1629
|
-
await this.open.wait({
|
|
1630
|
-
timeout: 1500
|
|
1631
|
-
});
|
|
1632
|
-
const res = await (0, import_async6.asyncTimeout)(this._rpc.rpc.TestService.testCall({
|
|
1633
|
-
data: message
|
|
1634
|
-
}), 1500);
|
|
1635
|
-
(0, import_invariant6.invariant)(res.data === message, void 0, {
|
|
1636
|
-
F: __dxlog_file7,
|
|
1637
|
-
L: 84,
|
|
1638
|
-
S: this,
|
|
1639
|
-
A: [
|
|
1640
|
-
"res.data === message",
|
|
1641
|
-
""
|
|
1642
|
-
]
|
|
1643
|
-
});
|
|
1644
|
-
}
|
|
1645
|
-
/**
|
|
1646
|
-
* Force-close the connection.
|
|
1647
|
-
*/
|
|
1648
|
-
async closeConnection(err) {
|
|
1649
|
-
this.extensionContext?.close(err);
|
|
1650
|
-
}
|
|
1651
|
-
};
|
|
1652
|
-
|
|
1653
|
-
// packages/core/mesh/teleport/src/testing/test-extension-with-streams.ts
|
|
1654
|
-
var import_node_crypto = require("node:crypto");
|
|
1655
|
-
var import_async7 = require("@dxos/async");
|
|
1656
|
-
var import_invariant7 = require("@dxos/invariant");
|
|
1657
|
-
var import_log8 = require("@dxos/log");
|
|
1658
|
-
var import_protocols5 = require("@dxos/protocols");
|
|
1659
|
-
var import_rpc3 = require("@dxos/rpc");
|
|
1660
|
-
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/testing/test-extension-with-streams.ts";
|
|
1661
|
-
var TestExtensionWithStreams = class {
|
|
1662
|
-
constructor(callbacks = {}) {
|
|
1663
|
-
this.callbacks = callbacks;
|
|
1664
|
-
this.open = new import_async7.Trigger();
|
|
1665
|
-
this.closed = new import_async7.Trigger();
|
|
1666
|
-
this.aborted = new import_async7.Trigger();
|
|
1667
|
-
this._streams = /* @__PURE__ */ new Map();
|
|
1668
|
-
}
|
|
1669
|
-
get remotePeerId() {
|
|
1670
|
-
return this.extensionContext?.remotePeerId;
|
|
1671
|
-
}
|
|
1672
|
-
async _openStream(streamTag, interval = 5, chunkSize = 2048) {
|
|
1673
|
-
(0, import_invariant7.invariant)(!this._streams.has(streamTag), `Stream already exists: ${streamTag}`, {
|
|
1674
|
-
F: __dxlog_file8,
|
|
1675
|
-
L: 39,
|
|
1676
|
-
S: this,
|
|
1677
|
-
A: [
|
|
1678
|
-
"!this._streams.has(streamTag)",
|
|
1679
|
-
"`Stream already exists: ${streamTag}`"
|
|
1680
|
-
]
|
|
1681
|
-
});
|
|
1682
|
-
const networkStream = await this.extensionContext.createStream(streamTag, {
|
|
1683
|
-
contentType: "application/x-test-stream"
|
|
1684
|
-
});
|
|
1685
|
-
const streamEntry = {
|
|
1686
|
-
networkStream,
|
|
1687
|
-
bytesSent: 0,
|
|
1688
|
-
bytesReceived: 0,
|
|
1689
|
-
sendErrors: 0,
|
|
1690
|
-
receiveErrors: 0,
|
|
1691
|
-
startTimestamp: Date.now()
|
|
1692
|
-
};
|
|
1693
|
-
const pushChunk = () => {
|
|
1694
|
-
streamEntry.timer = setTimeout(() => {
|
|
1695
|
-
const chunk = (0, import_node_crypto.randomBytes)(chunkSize);
|
|
1696
|
-
if (!networkStream.write(chunk, "binary", (err) => {
|
|
1697
|
-
if (!err) {
|
|
1698
|
-
streamEntry.bytesSent += chunk.length;
|
|
1699
|
-
} else {
|
|
1700
|
-
streamEntry.sendErrors += 1;
|
|
1701
|
-
}
|
|
1702
|
-
})) {
|
|
1703
|
-
networkStream.once("drain", pushChunk);
|
|
1704
|
-
} else {
|
|
1705
|
-
process.nextTick(pushChunk);
|
|
1706
|
-
}
|
|
1707
|
-
}, interval);
|
|
1708
|
-
};
|
|
1709
|
-
pushChunk();
|
|
1710
|
-
this._streams.set(streamTag, streamEntry);
|
|
1711
|
-
networkStream.on("data", (data) => {
|
|
1712
|
-
streamEntry.bytesReceived += data.length;
|
|
1713
|
-
});
|
|
1714
|
-
networkStream.on("error", (err) => {
|
|
1715
|
-
streamEntry.receiveErrors += 1;
|
|
1716
|
-
});
|
|
1717
|
-
networkStream.on("close", () => {
|
|
1718
|
-
networkStream.removeAllListeners();
|
|
1719
|
-
});
|
|
1720
|
-
streamEntry.reportingTimer = setInterval(() => {
|
|
1721
|
-
const { bytesSent, bytesReceived, sendErrors, receiveErrors } = streamEntry;
|
|
1722
|
-
import_log8.log.trace("dxos.test.stream-stats", {
|
|
1723
|
-
streamTag,
|
|
1724
|
-
bytesSent,
|
|
1725
|
-
bytesReceived,
|
|
1726
|
-
sendErrors,
|
|
1727
|
-
receiveErrors,
|
|
1728
|
-
from: this.extensionContext?.localPeerId,
|
|
1729
|
-
to: this.extensionContext?.remotePeerId
|
|
1730
|
-
}, {
|
|
1731
|
-
F: __dxlog_file8,
|
|
1732
|
-
L: 93,
|
|
1733
|
-
S: this,
|
|
1734
|
-
C: (f, a) => f(...a)
|
|
1735
|
-
});
|
|
1736
|
-
}, 100);
|
|
1737
|
-
}
|
|
1738
|
-
_closeStream(streamTag) {
|
|
1739
|
-
(0, import_invariant7.invariant)(this._streams.has(streamTag), `Stream does not exist: ${streamTag}`, {
|
|
1740
|
-
F: __dxlog_file8,
|
|
1741
|
-
L: 106,
|
|
1742
|
-
S: this,
|
|
1743
|
-
A: [
|
|
1744
|
-
"this._streams.has(streamTag)",
|
|
1745
|
-
"`Stream does not exist: ${streamTag}`"
|
|
1746
|
-
]
|
|
1747
|
-
});
|
|
1748
|
-
const stream = this._streams.get(streamTag);
|
|
1749
|
-
clearTimeout(stream.timer);
|
|
1750
|
-
clearTimeout(stream.reportingTimer);
|
|
1751
|
-
const { bytesSent, bytesReceived, sendErrors, receiveErrors, startTimestamp } = stream;
|
|
1752
|
-
stream.networkStream.destroy();
|
|
1753
|
-
this._streams.delete(streamTag);
|
|
1754
|
-
return {
|
|
1755
|
-
bytesSent,
|
|
1756
|
-
bytesReceived,
|
|
1757
|
-
sendErrors,
|
|
1758
|
-
receiveErrors,
|
|
1759
|
-
runningTime: Date.now() - (startTimestamp ?? 0)
|
|
1760
|
-
};
|
|
1761
|
-
}
|
|
1762
|
-
async onOpen(context) {
|
|
1763
|
-
(0, import_log8.log)("onOpen", {
|
|
1764
|
-
localPeerId: context.localPeerId,
|
|
1765
|
-
remotePeerId: context.remotePeerId
|
|
1766
|
-
}, {
|
|
1767
|
-
F: __dxlog_file8,
|
|
1768
|
-
L: 128,
|
|
1769
|
-
S: this,
|
|
1770
|
-
C: (f, a) => f(...a)
|
|
1771
|
-
});
|
|
1772
|
-
this.extensionContext = context;
|
|
1773
|
-
this._rpc = (0, import_rpc3.createProtoRpcPeer)({
|
|
1774
|
-
port: await context.createPort("rpc", {
|
|
1775
|
-
contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
|
|
1776
|
-
}),
|
|
1777
|
-
requested: {
|
|
1778
|
-
TestServiceWithStreams: import_protocols5.schema.getService("example.testing.rpc.TestServiceWithStreams")
|
|
1779
|
-
},
|
|
1780
|
-
exposed: {
|
|
1781
|
-
TestServiceWithStreams: import_protocols5.schema.getService("example.testing.rpc.TestServiceWithStreams")
|
|
1782
|
-
},
|
|
1783
|
-
handlers: {
|
|
1784
|
-
TestServiceWithStreams: {
|
|
1785
|
-
requestTestStream: async (request) => {
|
|
1786
|
-
const { data: streamTag, streamLoadInterval, streamLoadChunkSize } = request;
|
|
1787
|
-
await this._openStream(streamTag, streamLoadInterval, streamLoadChunkSize);
|
|
1788
|
-
return {
|
|
1789
|
-
data: streamTag
|
|
1790
|
-
};
|
|
1791
|
-
},
|
|
1792
|
-
closeTestStream: async (request) => {
|
|
1793
|
-
const streamTag = request.data;
|
|
1794
|
-
const { bytesSent, bytesReceived, sendErrors, receiveErrors, runningTime } = this._closeStream(streamTag);
|
|
1795
|
-
return {
|
|
1796
|
-
data: streamTag,
|
|
1797
|
-
bytesSent,
|
|
1798
|
-
bytesReceived,
|
|
1799
|
-
sendErrors,
|
|
1800
|
-
receiveErrors,
|
|
1801
|
-
runningTime
|
|
1802
|
-
};
|
|
1803
|
-
}
|
|
1804
|
-
}
|
|
1805
|
-
},
|
|
1806
|
-
timeout: 2e3
|
|
1807
|
-
});
|
|
1808
|
-
await this._rpc.open();
|
|
1809
|
-
await this.callbacks.onOpen?.();
|
|
1810
|
-
this.open.wake();
|
|
1811
|
-
}
|
|
1812
|
-
async onClose(err) {
|
|
1813
|
-
(0, import_log8.log)("onClose", {
|
|
1814
|
-
err
|
|
1815
|
-
}, {
|
|
1816
|
-
F: __dxlog_file8,
|
|
1817
|
-
L: 179,
|
|
1818
|
-
S: this,
|
|
1819
|
-
C: (f, a) => f(...a)
|
|
1820
|
-
});
|
|
1821
|
-
await this.callbacks.onClose?.();
|
|
1822
|
-
this.closed.wake();
|
|
1823
|
-
for (const [streamTag, stream] of Object.entries(this._streams)) {
|
|
1824
|
-
(0, import_log8.log)("closing stream", {
|
|
1825
|
-
streamTag
|
|
1826
|
-
}, {
|
|
1827
|
-
F: __dxlog_file8,
|
|
1828
|
-
L: 183,
|
|
1829
|
-
S: this,
|
|
1830
|
-
C: (f, a) => f(...a)
|
|
1831
|
-
});
|
|
1832
|
-
clearTimeout(stream.interval);
|
|
1833
|
-
stream.networkStream.destroy();
|
|
1834
|
-
}
|
|
1835
|
-
await this._rpc?.close();
|
|
1836
|
-
}
|
|
1837
|
-
async onAbort(err) {
|
|
1838
|
-
(0, import_log8.log)("onAbort", {
|
|
1839
|
-
err
|
|
1840
|
-
}, {
|
|
1841
|
-
F: __dxlog_file8,
|
|
1842
|
-
L: 191,
|
|
1843
|
-
S: this,
|
|
1844
|
-
C: (f, a) => f(...a)
|
|
1845
|
-
});
|
|
1846
|
-
await this.callbacks.onAbort?.();
|
|
1847
|
-
this.aborted.wake();
|
|
1848
|
-
await this._rpc?.abort();
|
|
1849
|
-
}
|
|
1850
|
-
async addNewStream(streamLoadInterval, streamLoadChunkSize, streamTag) {
|
|
1851
|
-
await this.open.wait({
|
|
1852
|
-
timeout: 1500
|
|
1853
|
-
});
|
|
1854
|
-
if (!streamTag) {
|
|
1855
|
-
streamTag = `stream-${(0, import_node_crypto.randomBytes)(4).toString("hex")}`;
|
|
1856
|
-
}
|
|
1857
|
-
const { data } = await this._rpc.rpc.TestServiceWithStreams.requestTestStream({
|
|
1858
|
-
data: streamTag,
|
|
1859
|
-
streamLoadInterval,
|
|
1860
|
-
streamLoadChunkSize
|
|
1861
|
-
});
|
|
1862
|
-
(0, import_invariant7.invariant)(data === streamTag, void 0, {
|
|
1863
|
-
F: __dxlog_file8,
|
|
1864
|
-
L: 207,
|
|
1865
|
-
S: this,
|
|
1866
|
-
A: [
|
|
1867
|
-
"data === streamTag",
|
|
1868
|
-
""
|
|
1869
|
-
]
|
|
1870
|
-
});
|
|
1871
|
-
await this._openStream(streamTag, streamLoadInterval, streamLoadChunkSize);
|
|
1872
|
-
return streamTag;
|
|
1873
|
-
}
|
|
1874
|
-
async closeStream(streamTag) {
|
|
1875
|
-
await this.open.wait({
|
|
1876
|
-
timeout: 1500
|
|
1877
|
-
});
|
|
1878
|
-
const { data, bytesSent, bytesReceived, sendErrors, receiveErrors, runningTime } = await this._rpc.rpc.TestServiceWithStreams.closeTestStream({
|
|
1879
|
-
data: streamTag
|
|
1880
|
-
});
|
|
1881
|
-
(0, import_invariant7.invariant)(data === streamTag, void 0, {
|
|
1882
|
-
F: __dxlog_file8,
|
|
1883
|
-
L: 220,
|
|
1884
|
-
S: this,
|
|
1885
|
-
A: [
|
|
1886
|
-
"data === streamTag",
|
|
1887
|
-
""
|
|
1888
|
-
]
|
|
1889
|
-
});
|
|
1890
|
-
const local = this._closeStream(streamTag);
|
|
1891
|
-
return {
|
|
1892
|
-
streamTag,
|
|
1893
|
-
stats: {
|
|
1894
|
-
local,
|
|
1895
|
-
remote: {
|
|
1896
|
-
bytesSent,
|
|
1897
|
-
bytesReceived,
|
|
1898
|
-
sendErrors,
|
|
1899
|
-
receiveErrors,
|
|
1900
|
-
runningTime
|
|
1901
|
-
}
|
|
1902
|
-
}
|
|
1903
|
-
};
|
|
1904
|
-
}
|
|
1905
|
-
/**
|
|
1906
|
-
* Force-close the connection.
|
|
1907
|
-
*/
|
|
1908
|
-
async closeConnection(err) {
|
|
1909
|
-
this.extensionContext?.close(err);
|
|
1910
|
-
}
|
|
1911
|
-
};
|
|
1912
|
-
|
|
1913
|
-
// packages/core/mesh/teleport/src/rpc-extension.ts
|
|
1914
|
-
var import_invariant8 = require("@dxos/invariant");
|
|
1915
|
-
var import_rpc4 = require("@dxos/rpc");
|
|
1916
|
-
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/rpc-extension.ts";
|
|
37
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/rpc-extension.ts";
|
|
1917
38
|
var RpcExtension = class {
|
|
1918
39
|
constructor(_rpcParams) {
|
|
1919
40
|
this._rpcParams = _rpcParams;
|
|
@@ -1929,8 +50,8 @@ var RpcExtension = class {
|
|
|
1929
50
|
return this._extensionContext.remotePeerId;
|
|
1930
51
|
}
|
|
1931
52
|
get rpc() {
|
|
1932
|
-
(0,
|
|
1933
|
-
F:
|
|
53
|
+
(0, import_invariant.invariant)(this._rpc, void 0, {
|
|
54
|
+
F: __dxlog_file,
|
|
1934
55
|
L: 32,
|
|
1935
56
|
S: this,
|
|
1936
57
|
A: [
|
|
@@ -1949,7 +70,7 @@ var RpcExtension = class {
|
|
|
1949
70
|
const port = await context.createPort("rpc", {
|
|
1950
71
|
contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
|
|
1951
72
|
});
|
|
1952
|
-
this._rpc = (0,
|
|
73
|
+
this._rpc = (0, import_rpc.createProtoRpcPeer)({
|
|
1953
74
|
...this._rpcParams,
|
|
1954
75
|
handlers,
|
|
1955
76
|
port
|