@dxos/teleport 0.1.54 → 0.1.55-main.0618d91
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-7TGKNWZQ.mjs → chunk-GGVQ27WJ.mjs} +606 -138
- package/dist/lib/browser/chunk-GGVQ27WJ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +10 -200
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +7 -128
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/node/index.cjs +434 -165
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +484 -147
- package/dist/lib/node/testing/index.cjs.map +4 -4
- package/dist/types/src/index.d.ts +1 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/muxing/balancer.d.ts +22 -8
- package/dist/types/src/muxing/balancer.d.ts.map +1 -1
- package/dist/types/src/muxing/balancer.test.d.ts +2 -0
- package/dist/types/src/muxing/balancer.test.d.ts.map +1 -0
- package/dist/types/src/muxing/framer.d.ts +5 -2
- package/dist/types/src/muxing/framer.d.ts.map +1 -1
- package/dist/types/src/muxing/muxer.d.ts +8 -4
- package/dist/types/src/muxing/muxer.d.ts.map +1 -1
- package/dist/types/src/teleport.d.ts +2 -3
- package/dist/types/src/teleport.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +1 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-extension-with-streams.d.ts +4 -4
- package/dist/types/src/testing/test-extension-with-streams.d.ts.map +1 -1
- package/package.json +11 -11
- package/src/index.ts +1 -2
- package/src/muxing/balancer.test.ts +50 -0
- package/src/muxing/balancer.ts +127 -34
- package/src/muxing/framer.test.ts +1 -15
- package/src/muxing/framer.ts +43 -35
- package/src/muxing/muxer.ts +35 -24
- package/src/teleport.ts +22 -15
- package/src/testing/index.ts +1 -0
- package/src/testing/test-extension-with-streams.ts +31 -12
- package/dist/lib/browser/chunk-7TGKNWZQ.mjs.map +0 -7
|
@@ -1,18 +1,39 @@
|
|
|
1
1
|
import "@dxos/node-std/globals";
|
|
2
2
|
|
|
3
|
+
// packages/core/mesh/teleport/src/testing/test-builder.ts
|
|
4
|
+
import { pipeline } from "@dxos/node-std/stream";
|
|
5
|
+
import invariant4 from "tiny-invariant";
|
|
6
|
+
import { PublicKey as PublicKey2 } from "@dxos/keys";
|
|
7
|
+
import { log as log4 } from "@dxos/log";
|
|
8
|
+
|
|
9
|
+
// packages/core/mesh/teleport/src/teleport.ts
|
|
10
|
+
import invariant3 from "tiny-invariant";
|
|
11
|
+
import { asyncTimeout, scheduleTaskInterval as scheduleTaskInterval2, runInContextAsync, synchronized, scheduleTask } from "@dxos/async";
|
|
12
|
+
import { Context as Context2 } from "@dxos/context";
|
|
13
|
+
import { failUndefined as failUndefined2 } from "@dxos/debug";
|
|
14
|
+
import { PublicKey } from "@dxos/keys";
|
|
15
|
+
import { log as log3 } from "@dxos/log";
|
|
16
|
+
import { schema as schema2, RpcClosedError } from "@dxos/protocols";
|
|
17
|
+
import { createProtoRpcPeer } from "@dxos/rpc";
|
|
18
|
+
import { Callback } from "@dxos/util";
|
|
19
|
+
|
|
3
20
|
// packages/core/mesh/teleport/src/muxing/framer.ts
|
|
4
21
|
import { Duplex } from "@dxos/node-std/stream";
|
|
5
22
|
import invariant from "tiny-invariant";
|
|
6
|
-
|
|
23
|
+
var FRAME_LENGTH_SIZE = 2;
|
|
7
24
|
var Framer = class {
|
|
8
25
|
constructor() {
|
|
9
|
-
this.
|
|
26
|
+
this._sendCallbacks = [];
|
|
27
|
+
this._bytesSent = 0;
|
|
28
|
+
this._bytesReceived = 0;
|
|
10
29
|
this._stream = new Duplex({
|
|
11
30
|
objectMode: false,
|
|
12
31
|
read: () => {
|
|
32
|
+
this._processResponseQueue();
|
|
13
33
|
},
|
|
14
34
|
write: (chunk, encoding, callback) => {
|
|
15
35
|
invariant(!this._subscribeCb, "Internal Framer bug. Concurrent writes detected.");
|
|
36
|
+
this._bytesReceived += chunk.length;
|
|
16
37
|
if (this._buffer && this._buffer.length > 0) {
|
|
17
38
|
this._buffer = Buffer.concat([
|
|
18
39
|
this._buffer,
|
|
@@ -36,11 +57,13 @@ var Framer = class {
|
|
|
36
57
|
this.port = {
|
|
37
58
|
send: (message) => {
|
|
38
59
|
return new Promise((resolve) => {
|
|
39
|
-
const
|
|
60
|
+
const frame = encodeFrame(message);
|
|
61
|
+
this._bytesSent += frame.length;
|
|
62
|
+
const canContinue = this._stream.push(frame);
|
|
40
63
|
if (!canContinue) {
|
|
41
|
-
this.
|
|
64
|
+
this._sendCallbacks.push(resolve);
|
|
42
65
|
} else {
|
|
43
|
-
|
|
66
|
+
resolve();
|
|
44
67
|
}
|
|
45
68
|
});
|
|
46
69
|
},
|
|
@@ -54,14 +77,19 @@ var Framer = class {
|
|
|
54
77
|
};
|
|
55
78
|
}
|
|
56
79
|
};
|
|
57
|
-
this.stream.on("drain", this._processResponseQueue.bind(this));
|
|
58
80
|
}
|
|
59
81
|
get stream() {
|
|
60
82
|
return this._stream;
|
|
61
83
|
}
|
|
84
|
+
get bytesSent() {
|
|
85
|
+
return this._bytesSent;
|
|
86
|
+
}
|
|
87
|
+
get bytesReceived() {
|
|
88
|
+
return this._bytesReceived;
|
|
89
|
+
}
|
|
62
90
|
_processResponseQueue() {
|
|
63
|
-
const responseQueue = this.
|
|
64
|
-
this.
|
|
91
|
+
const responseQueue = this._sendCallbacks;
|
|
92
|
+
this._sendCallbacks = [];
|
|
65
93
|
responseQueue.forEach((cb) => cb());
|
|
66
94
|
}
|
|
67
95
|
/**
|
|
@@ -84,139 +112,214 @@ var Framer = class {
|
|
|
84
112
|
}
|
|
85
113
|
}
|
|
86
114
|
destroy() {
|
|
87
|
-
this._stream.removeAllListeners("drain");
|
|
88
115
|
this._stream.destroy();
|
|
89
116
|
}
|
|
90
117
|
};
|
|
91
118
|
var decodeFrame = (buffer, offset) => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const tagLength = varint.decode.bytes;
|
|
95
|
-
if (buffer.length < offset + tagLength + frameLength) {
|
|
96
|
-
return void 0;
|
|
97
|
-
}
|
|
98
|
-
const payload = buffer.subarray(offset + tagLength, offset + tagLength + frameLength);
|
|
99
|
-
return {
|
|
100
|
-
payload,
|
|
101
|
-
bytesConsumed: tagLength + frameLength
|
|
102
|
-
};
|
|
103
|
-
} catch (err) {
|
|
104
|
-
if (err instanceof RangeError) {
|
|
105
|
-
return void 0;
|
|
106
|
-
} else {
|
|
107
|
-
throw err;
|
|
108
|
-
}
|
|
119
|
+
if (buffer.length < offset + FRAME_LENGTH_SIZE) {
|
|
120
|
+
return void 0;
|
|
109
121
|
}
|
|
122
|
+
const frameLength = buffer.readUInt16BE(offset);
|
|
123
|
+
const bytesConsumed = FRAME_LENGTH_SIZE + frameLength;
|
|
124
|
+
if (buffer.length < offset + bytesConsumed) {
|
|
125
|
+
return void 0;
|
|
126
|
+
}
|
|
127
|
+
const payload = buffer.subarray(offset + FRAME_LENGTH_SIZE, offset + bytesConsumed);
|
|
128
|
+
return {
|
|
129
|
+
payload,
|
|
130
|
+
bytesConsumed
|
|
131
|
+
};
|
|
110
132
|
};
|
|
111
133
|
var encodeFrame = (payload) => {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
frame.set(payload, tagLength);
|
|
134
|
+
const frame = Buffer.allocUnsafe(FRAME_LENGTH_SIZE + payload.length);
|
|
135
|
+
frame.writeUInt16BE(payload.length, 0);
|
|
136
|
+
frame.set(payload, FRAME_LENGTH_SIZE);
|
|
116
137
|
return frame;
|
|
117
138
|
};
|
|
118
139
|
|
|
119
140
|
// packages/core/mesh/teleport/src/muxing/muxer.ts
|
|
120
141
|
import { Duplex as Duplex2 } from "@dxos/node-std/stream";
|
|
121
142
|
import invariant2 from "tiny-invariant";
|
|
122
|
-
import { scheduleTaskInterval, Event, Trigger } from "@dxos/async";
|
|
143
|
+
import { scheduleTaskInterval, Event as Event2, Trigger } from "@dxos/async";
|
|
123
144
|
import { Context } from "@dxos/context";
|
|
124
145
|
import { failUndefined } from "@dxos/debug";
|
|
125
|
-
import { log } from "@dxos/log";
|
|
146
|
+
import { log as log2 } from "@dxos/log";
|
|
126
147
|
import { schema } from "@dxos/protocols";
|
|
127
148
|
|
|
128
149
|
// packages/core/mesh/teleport/src/muxing/balancer.ts
|
|
150
|
+
import * as varint from "varint";
|
|
151
|
+
import { Event } from "@dxos/async";
|
|
152
|
+
import { log } from "@dxos/log";
|
|
153
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/balancer.ts";
|
|
154
|
+
var MAX_CHUNK_SIZE = 8192;
|
|
129
155
|
var Balancer = class {
|
|
130
|
-
constructor(
|
|
131
|
-
this._port = _port;
|
|
156
|
+
constructor(_sysChannelId) {
|
|
132
157
|
this._sysChannelId = _sysChannelId;
|
|
133
158
|
this._lastCallerIndex = 0;
|
|
134
159
|
this._channels = [];
|
|
135
|
-
this.
|
|
160
|
+
this._framer = new Framer();
|
|
161
|
+
this._sendBuffers = /* @__PURE__ */ new Map();
|
|
162
|
+
this._receiveBuffers = /* @__PURE__ */ new Map();
|
|
163
|
+
this.incomingData = new Event();
|
|
164
|
+
this.stream = this._framer.stream;
|
|
136
165
|
this._channels.push(_sysChannelId);
|
|
166
|
+
this._framer.port.subscribe(this._processIncomingMessage.bind(this));
|
|
167
|
+
}
|
|
168
|
+
get bytesSent() {
|
|
169
|
+
return this._framer.bytesSent;
|
|
170
|
+
}
|
|
171
|
+
get bytesReceived() {
|
|
172
|
+
return this._framer.bytesReceived;
|
|
137
173
|
}
|
|
138
174
|
addChannel(channel) {
|
|
139
175
|
this._channels.push(channel);
|
|
140
176
|
}
|
|
141
|
-
|
|
142
|
-
const noCalls = this.
|
|
177
|
+
pushData(data, trigger, channelId) {
|
|
178
|
+
const noCalls = this._sendBuffers.size === 0;
|
|
143
179
|
if (!this._channels.includes(channelId)) {
|
|
144
180
|
throw new Error(`Unknown channel ${channelId}`);
|
|
145
181
|
}
|
|
146
|
-
if (!this.
|
|
147
|
-
this.
|
|
182
|
+
if (!this._sendBuffers.has(channelId)) {
|
|
183
|
+
this._sendBuffers.set(channelId, []);
|
|
148
184
|
}
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
185
|
+
const sendBuffer = this._sendBuffers.get(channelId);
|
|
186
|
+
const chunks = [];
|
|
187
|
+
for (let idx = 0; idx < data.length; idx += MAX_CHUNK_SIZE) {
|
|
188
|
+
chunks.push(data.subarray(idx, idx + MAX_CHUNK_SIZE));
|
|
189
|
+
}
|
|
190
|
+
chunks.forEach((chunk, index) => {
|
|
191
|
+
const msg = encodeChunk({
|
|
192
|
+
chunk,
|
|
193
|
+
channelId,
|
|
194
|
+
dataLength: index === 0 ? data.length : void 0
|
|
195
|
+
});
|
|
196
|
+
sendBuffer.push({
|
|
197
|
+
msg,
|
|
198
|
+
trigger: index === chunks.length - 1 ? trigger : void 0
|
|
199
|
+
});
|
|
153
200
|
});
|
|
154
201
|
if (noCalls) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
202
|
+
this._sendChunks().catch((err) => log.catch(err, void 0, {
|
|
203
|
+
F: __dxlog_file,
|
|
204
|
+
L: 96,
|
|
205
|
+
S: this,
|
|
206
|
+
C: (f, a) => f(...a)
|
|
207
|
+
}));
|
|
158
208
|
}
|
|
159
209
|
}
|
|
160
210
|
destroy() {
|
|
161
|
-
this.
|
|
211
|
+
this._sendBuffers.clear();
|
|
212
|
+
this._framer.destroy();
|
|
213
|
+
}
|
|
214
|
+
_processIncomingMessage(msg) {
|
|
215
|
+
const { channelId, dataLength, chunk } = decodeChunk(msg, (channelId2) => !this._receiveBuffers.has(channelId2));
|
|
216
|
+
if (!this._receiveBuffers.has(channelId)) {
|
|
217
|
+
if (chunk.length < dataLength) {
|
|
218
|
+
this._receiveBuffers.set(channelId, {
|
|
219
|
+
buffer: Buffer.from(chunk),
|
|
220
|
+
msgLength: dataLength
|
|
221
|
+
});
|
|
222
|
+
} else {
|
|
223
|
+
this.incomingData.emit(chunk);
|
|
224
|
+
}
|
|
225
|
+
} else {
|
|
226
|
+
const channelBuffer = this._receiveBuffers.get(channelId);
|
|
227
|
+
channelBuffer.buffer = Buffer.concat([
|
|
228
|
+
channelBuffer.buffer,
|
|
229
|
+
chunk
|
|
230
|
+
]);
|
|
231
|
+
if (channelBuffer.buffer.length < channelBuffer.msgLength) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const msg2 = channelBuffer.buffer;
|
|
235
|
+
this._receiveBuffers.delete(channelId);
|
|
236
|
+
this.incomingData.emit(msg2);
|
|
237
|
+
}
|
|
162
238
|
}
|
|
163
239
|
_getNextCallerId() {
|
|
164
|
-
if (this.
|
|
240
|
+
if (this._sendBuffers.has(this._sysChannelId)) {
|
|
165
241
|
return this._sysChannelId;
|
|
166
242
|
}
|
|
167
243
|
const index = this._lastCallerIndex;
|
|
168
244
|
this._lastCallerIndex = (this._lastCallerIndex + 1) % this._channels.length;
|
|
169
245
|
return this._channels[index];
|
|
170
246
|
}
|
|
171
|
-
|
|
172
|
-
let
|
|
173
|
-
while (!
|
|
247
|
+
_getNextChunk() {
|
|
248
|
+
let chunk;
|
|
249
|
+
while (!chunk) {
|
|
174
250
|
const channelId = this._getNextCallerId();
|
|
175
|
-
const
|
|
176
|
-
if (!
|
|
251
|
+
const sendBuffer = this._sendBuffers.get(channelId);
|
|
252
|
+
if (!sendBuffer) {
|
|
177
253
|
continue;
|
|
178
254
|
}
|
|
179
|
-
|
|
180
|
-
if (
|
|
181
|
-
this.
|
|
255
|
+
chunk = sendBuffer.shift();
|
|
256
|
+
if (sendBuffer.length === 0) {
|
|
257
|
+
this._sendBuffers.delete(channelId);
|
|
182
258
|
}
|
|
183
259
|
}
|
|
184
|
-
return
|
|
260
|
+
return chunk;
|
|
185
261
|
}
|
|
186
|
-
async
|
|
187
|
-
|
|
262
|
+
async _sendChunks() {
|
|
263
|
+
var _a, _b;
|
|
264
|
+
if (this._sendBuffers.size === 0) {
|
|
188
265
|
return;
|
|
189
266
|
}
|
|
190
|
-
const
|
|
267
|
+
const chunk = this._getNextChunk();
|
|
191
268
|
try {
|
|
192
|
-
await this.
|
|
193
|
-
|
|
269
|
+
await this._framer.port.send(chunk.msg);
|
|
270
|
+
(_a = chunk.trigger) == null ? void 0 : _a.wake();
|
|
194
271
|
} catch (err) {
|
|
195
|
-
|
|
272
|
+
(_b = chunk.trigger) == null ? void 0 : _b.throw(err);
|
|
196
273
|
}
|
|
197
|
-
await this.
|
|
274
|
+
await this._sendChunks();
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
var encodeChunk = ({ channelId, dataLength, chunk }) => {
|
|
278
|
+
const channelTagLength = varint.encodingLength(channelId);
|
|
279
|
+
const dataLengthLength = dataLength ? varint.encodingLength(dataLength) : 0;
|
|
280
|
+
const message = Buffer.allocUnsafe(channelTagLength + dataLengthLength + chunk.length);
|
|
281
|
+
varint.encode(channelId, message);
|
|
282
|
+
if (dataLength) {
|
|
283
|
+
varint.encode(dataLength, message, channelTagLength);
|
|
284
|
+
}
|
|
285
|
+
message.set(chunk, channelTagLength + dataLengthLength);
|
|
286
|
+
return message;
|
|
287
|
+
};
|
|
288
|
+
var decodeChunk = (data, withLength) => {
|
|
289
|
+
const channelId = varint.decode(data);
|
|
290
|
+
let dataLength;
|
|
291
|
+
let offset = varint.decode.bytes;
|
|
292
|
+
if (withLength(channelId)) {
|
|
293
|
+
dataLength = varint.decode(data, offset);
|
|
294
|
+
offset += varint.decode.bytes;
|
|
198
295
|
}
|
|
296
|
+
const chunk = data.subarray(offset);
|
|
297
|
+
return {
|
|
298
|
+
channelId,
|
|
299
|
+
dataLength,
|
|
300
|
+
chunk
|
|
301
|
+
};
|
|
199
302
|
};
|
|
200
303
|
|
|
201
304
|
// packages/core/mesh/teleport/src/muxing/muxer.ts
|
|
202
|
-
var
|
|
305
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/muxer.ts";
|
|
203
306
|
var Command = schema.getCodecForType("dxos.mesh.muxer.Command");
|
|
204
307
|
var STATS_INTERVAL = 1e3;
|
|
205
|
-
var
|
|
308
|
+
var MAX_SAFE_FRAME_SIZE = 1e6;
|
|
309
|
+
var SYSTEM_CHANNEL_ID = 0;
|
|
206
310
|
var Muxer = class {
|
|
207
311
|
constructor() {
|
|
208
|
-
this.
|
|
209
|
-
this._balancer = new Balancer(this._framer.port, SYSTEM_CHANNEL_ID);
|
|
210
|
-
this.stream = this._framer.stream;
|
|
312
|
+
this._balancer = new Balancer(SYSTEM_CHANNEL_ID);
|
|
211
313
|
this._channelsByLocalId = /* @__PURE__ */ new Map();
|
|
212
314
|
this._channelsByTag = /* @__PURE__ */ new Map();
|
|
213
|
-
this.
|
|
315
|
+
this._ctx = new Context();
|
|
316
|
+
this._nextId = 1;
|
|
214
317
|
this._destroyed = false;
|
|
215
318
|
this._destroying = false;
|
|
216
|
-
this.close = new
|
|
217
|
-
this.statsUpdated = new
|
|
218
|
-
this.
|
|
219
|
-
this.
|
|
319
|
+
this.close = new Event2();
|
|
320
|
+
this.statsUpdated = new Event2();
|
|
321
|
+
this.stream = this._balancer.stream;
|
|
322
|
+
this._balancer.incomingData.on(async (msg) => {
|
|
220
323
|
await this._handleCommand(Command.decode(msg));
|
|
221
324
|
});
|
|
222
325
|
scheduleTaskInterval(this._ctx, async () => this._emitStats(), STATS_INTERVAL);
|
|
@@ -318,11 +421,11 @@ var Muxer = class {
|
|
|
318
421
|
return;
|
|
319
422
|
}
|
|
320
423
|
this._destroying = true;
|
|
321
|
-
|
|
424
|
+
this._sendCommand({
|
|
322
425
|
destroy: {
|
|
323
426
|
error: err == null ? void 0 : err.message
|
|
324
427
|
}
|
|
325
|
-
}, SYSTEM_CHANNEL_ID)
|
|
428
|
+
}, SYSTEM_CHANNEL_ID).then(() => {
|
|
326
429
|
this._dispose();
|
|
327
430
|
}).catch((err2) => {
|
|
328
431
|
this._dispose(err2);
|
|
@@ -336,7 +439,6 @@ var Muxer = class {
|
|
|
336
439
|
}
|
|
337
440
|
this._destroyed = true;
|
|
338
441
|
this._balancer.destroy();
|
|
339
|
-
this._framer.destroy();
|
|
340
442
|
for (const channel of this._channelsByTag.values()) {
|
|
341
443
|
(_a = channel.destroy) == null ? void 0 : _a.call(channel, err);
|
|
342
444
|
}
|
|
@@ -346,20 +448,20 @@ var Muxer = class {
|
|
|
346
448
|
}
|
|
347
449
|
async _handleCommand(cmd) {
|
|
348
450
|
var _a;
|
|
349
|
-
|
|
451
|
+
log2("Received command", {
|
|
350
452
|
cmd
|
|
351
453
|
}, {
|
|
352
|
-
F:
|
|
353
|
-
L:
|
|
454
|
+
F: __dxlog_file2,
|
|
455
|
+
L: 240,
|
|
354
456
|
S: this,
|
|
355
457
|
C: (f, a) => f(...a)
|
|
356
458
|
});
|
|
357
459
|
if (this._destroyed || this._destroying) {
|
|
358
|
-
|
|
460
|
+
log2.warn("Received command after destroy", {
|
|
359
461
|
cmd
|
|
360
462
|
}, {
|
|
361
|
-
F:
|
|
362
|
-
L:
|
|
463
|
+
F: __dxlog_file2,
|
|
464
|
+
L: 243,
|
|
363
465
|
S: this,
|
|
364
466
|
C: (f, a) => f(...a)
|
|
365
467
|
});
|
|
@@ -383,11 +485,11 @@ var Muxer = class {
|
|
|
383
485
|
} else if (cmd.data) {
|
|
384
486
|
const stream = (_a = this._channelsByLocalId.get(cmd.data.channelId)) != null ? _a : failUndefined();
|
|
385
487
|
if (!stream.push) {
|
|
386
|
-
|
|
488
|
+
log2.warn("Received data for channel before it was opened", {
|
|
387
489
|
tag: stream.tag
|
|
388
490
|
}, {
|
|
389
|
-
F:
|
|
390
|
-
L:
|
|
491
|
+
F: __dxlog_file2,
|
|
492
|
+
L: 270,
|
|
391
493
|
S: this,
|
|
392
494
|
C: (f, a) => f(...a)
|
|
393
495
|
});
|
|
@@ -401,7 +503,7 @@ var Muxer = class {
|
|
|
401
503
|
async _sendCommand(cmd, channelId = -1) {
|
|
402
504
|
try {
|
|
403
505
|
const trigger = new Trigger();
|
|
404
|
-
this._balancer.
|
|
506
|
+
this._balancer.pushData(Command.encode(cmd), trigger, channelId);
|
|
405
507
|
await trigger.wait();
|
|
406
508
|
} catch (err) {
|
|
407
509
|
this.destroy(err);
|
|
@@ -430,6 +532,17 @@ var Muxer = class {
|
|
|
430
532
|
return channel;
|
|
431
533
|
}
|
|
432
534
|
async _sendData(channel, data) {
|
|
535
|
+
if (data.length > MAX_SAFE_FRAME_SIZE) {
|
|
536
|
+
log2.warn("frame size exceeds maximum safe value", {
|
|
537
|
+
size: data.length,
|
|
538
|
+
threshold: MAX_SAFE_FRAME_SIZE
|
|
539
|
+
}, {
|
|
540
|
+
F: __dxlog_file2,
|
|
541
|
+
L: 314,
|
|
542
|
+
S: this,
|
|
543
|
+
C: (f, a) => f(...a)
|
|
544
|
+
});
|
|
545
|
+
}
|
|
433
546
|
channel.stats.bytesSent += data.length;
|
|
434
547
|
if (channel.remoteId === null) {
|
|
435
548
|
channel.buffer.push(data);
|
|
@@ -453,25 +566,23 @@ var Muxer = class {
|
|
|
453
566
|
if (this._destroyed || this._destroying) {
|
|
454
567
|
return;
|
|
455
568
|
}
|
|
456
|
-
this.
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
569
|
+
const bytesSent = this._balancer.bytesSent;
|
|
570
|
+
const bytesReceived = this._balancer.bytesReceived;
|
|
571
|
+
this.statsUpdated.emit({
|
|
572
|
+
channels: Array.from(this._channelsByTag.values()).map((channel) => ({
|
|
573
|
+
id: channel.id,
|
|
574
|
+
tag: channel.tag,
|
|
575
|
+
contentType: channel.contentType,
|
|
576
|
+
bytesSent: channel.stats.bytesSent,
|
|
577
|
+
bytesReceived: channel.stats.bytesReceived
|
|
578
|
+
})),
|
|
579
|
+
bytesSent,
|
|
580
|
+
bytesReceived
|
|
581
|
+
});
|
|
462
582
|
}
|
|
463
583
|
};
|
|
464
584
|
|
|
465
585
|
// packages/core/mesh/teleport/src/teleport.ts
|
|
466
|
-
import invariant3 from "tiny-invariant";
|
|
467
|
-
import { asyncTimeout, scheduleTaskInterval as scheduleTaskInterval2, runInContextAsync, synchronized, scheduleTask } from "@dxos/async";
|
|
468
|
-
import { Context as Context2 } from "@dxos/context";
|
|
469
|
-
import { failUndefined as failUndefined2 } from "@dxos/debug";
|
|
470
|
-
import { PublicKey } from "@dxos/keys";
|
|
471
|
-
import { log as log2 } from "@dxos/log";
|
|
472
|
-
import { schema as schema2, RpcClosedError } from "@dxos/protocols";
|
|
473
|
-
import { createProtoRpcPeer } from "@dxos/rpc";
|
|
474
|
-
import { Callback } from "@dxos/util";
|
|
475
586
|
function _ts_decorate(decorators, target, key, desc) {
|
|
476
587
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
477
588
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
@@ -482,15 +593,15 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
482
593
|
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
483
594
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
484
595
|
}
|
|
485
|
-
var
|
|
596
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts";
|
|
486
597
|
var Teleport = class {
|
|
487
598
|
constructor({ initiator, localPeerId, remotePeerId }) {
|
|
488
599
|
this._ctx = new Context2({
|
|
489
600
|
onError: (err) => {
|
|
490
601
|
void this.destroy(err).catch(() => {
|
|
491
|
-
|
|
492
|
-
F:
|
|
493
|
-
L:
|
|
602
|
+
log3.error("Error during destroy", err, {
|
|
603
|
+
F: __dxlog_file3,
|
|
604
|
+
L: 34,
|
|
494
605
|
S: this,
|
|
495
606
|
C: (f, a) => f(...a)
|
|
496
607
|
});
|
|
@@ -502,9 +613,9 @@ var Teleport = class {
|
|
|
502
613
|
heartbeatInterval: 1e4,
|
|
503
614
|
heartbeatTimeout: 1e4,
|
|
504
615
|
onTimeout: () => {
|
|
505
|
-
this.destroy(new Error("Connection timed out")).catch((err) =>
|
|
506
|
-
F:
|
|
507
|
-
L:
|
|
616
|
+
this.destroy(new Error("Connection timed out")).catch((err) => log3.catch(err, void 0, {
|
|
617
|
+
F: __dxlog_file3,
|
|
618
|
+
L: 45,
|
|
508
619
|
S: this,
|
|
509
620
|
C: (f, a) => f(...a)
|
|
510
621
|
}));
|
|
@@ -516,16 +627,15 @@ var Teleport = class {
|
|
|
516
627
|
invariant3(typeof initiator === "boolean");
|
|
517
628
|
invariant3(PublicKey.isPublicKey(localPeerId));
|
|
518
629
|
invariant3(PublicKey.isPublicKey(remotePeerId));
|
|
519
|
-
invariant3(typeof initiator === "boolean");
|
|
520
630
|
this.initiator = initiator;
|
|
521
631
|
this.localPeerId = localPeerId;
|
|
522
632
|
this.remotePeerId = remotePeerId;
|
|
523
633
|
this._control.onExtensionRegistered.set(async (name) => {
|
|
524
|
-
|
|
634
|
+
log3("remote extension", {
|
|
525
635
|
name
|
|
526
636
|
}, {
|
|
527
|
-
F:
|
|
528
|
-
L:
|
|
637
|
+
F: __dxlog_file3,
|
|
638
|
+
L: 63,
|
|
529
639
|
S: this,
|
|
530
640
|
C: (f, a) => f(...a)
|
|
531
641
|
});
|
|
@@ -547,6 +657,20 @@ var Teleport = class {
|
|
|
547
657
|
await this.destroy(err);
|
|
548
658
|
});
|
|
549
659
|
}
|
|
660
|
+
this._muxer.statsUpdated.on((stats) => {
|
|
661
|
+
log3.trace("dxos.mesh.teleport.stats", {
|
|
662
|
+
localPeerId,
|
|
663
|
+
remotePeerId,
|
|
664
|
+
bytesSent: stats.bytesSent,
|
|
665
|
+
bytesReceived: stats.bytesReceived,
|
|
666
|
+
channels: stats.channels
|
|
667
|
+
}, {
|
|
668
|
+
F: __dxlog_file3,
|
|
669
|
+
L: 88,
|
|
670
|
+
S: this,
|
|
671
|
+
C: (f, a) => f(...a)
|
|
672
|
+
});
|
|
673
|
+
});
|
|
550
674
|
}
|
|
551
675
|
get stream() {
|
|
552
676
|
return this._muxer.stream;
|
|
@@ -574,9 +698,9 @@ var Teleport = class {
|
|
|
574
698
|
try {
|
|
575
699
|
await extension.onClose(err);
|
|
576
700
|
} catch (err2) {
|
|
577
|
-
|
|
578
|
-
F:
|
|
579
|
-
L:
|
|
701
|
+
log3.catch(err2, void 0, {
|
|
702
|
+
F: __dxlog_file3,
|
|
703
|
+
L: 132,
|
|
580
704
|
S: this,
|
|
581
705
|
C: (f, a) => f(...a)
|
|
582
706
|
});
|
|
@@ -588,11 +712,11 @@ var Teleport = class {
|
|
|
588
712
|
if (!this._open) {
|
|
589
713
|
throw new Error("Not open");
|
|
590
714
|
}
|
|
591
|
-
|
|
715
|
+
log3("addExtension", {
|
|
592
716
|
name
|
|
593
717
|
}, {
|
|
594
|
-
F:
|
|
595
|
-
L:
|
|
718
|
+
F: __dxlog_file3,
|
|
719
|
+
L: 144,
|
|
596
720
|
S: this,
|
|
597
721
|
C: (f, a) => f(...a)
|
|
598
722
|
});
|
|
@@ -620,11 +744,11 @@ var Teleport = class {
|
|
|
620
744
|
}
|
|
621
745
|
async _openExtension(extensionName) {
|
|
622
746
|
var _a;
|
|
623
|
-
|
|
747
|
+
log3("open extension", {
|
|
624
748
|
extensionName
|
|
625
749
|
}, {
|
|
626
|
-
F:
|
|
627
|
-
L:
|
|
750
|
+
F: __dxlog_file3,
|
|
751
|
+
L: 174,
|
|
628
752
|
S: this,
|
|
629
753
|
C: (f, a) => f(...a)
|
|
630
754
|
});
|
|
@@ -648,11 +772,11 @@ var Teleport = class {
|
|
|
648
772
|
}
|
|
649
773
|
};
|
|
650
774
|
await extension.onOpen(context);
|
|
651
|
-
|
|
775
|
+
log3("extension opened", {
|
|
652
776
|
extensionName
|
|
653
777
|
}, {
|
|
654
|
-
F:
|
|
655
|
-
L:
|
|
778
|
+
F: __dxlog_file3,
|
|
779
|
+
L: 197,
|
|
656
780
|
S: this,
|
|
657
781
|
C: (f, a) => f(...a)
|
|
658
782
|
});
|
|
@@ -671,6 +795,11 @@ var ControlExtension = class {
|
|
|
671
795
|
});
|
|
672
796
|
this.onExtensionRegistered = new Callback();
|
|
673
797
|
}
|
|
798
|
+
async registerExtension(name) {
|
|
799
|
+
await this._rpc.rpc.Control.registerExtension({
|
|
800
|
+
name
|
|
801
|
+
});
|
|
802
|
+
}
|
|
674
803
|
async onOpen(extensionContext) {
|
|
675
804
|
this._extensionContext = extensionContext;
|
|
676
805
|
this._rpc = createProtoRpcPeer({
|
|
@@ -706,20 +835,136 @@ var ControlExtension = class {
|
|
|
706
835
|
await this._ctx.dispose();
|
|
707
836
|
await this._rpc.close();
|
|
708
837
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
838
|
+
};
|
|
839
|
+
|
|
840
|
+
// packages/core/mesh/teleport/src/testing/test-builder.ts
|
|
841
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/testing/test-builder.ts";
|
|
842
|
+
var TestBuilder = class {
|
|
843
|
+
constructor() {
|
|
844
|
+
this._peers = /* @__PURE__ */ new Set();
|
|
845
|
+
}
|
|
846
|
+
createPeer(opts) {
|
|
847
|
+
const peer = opts.factory();
|
|
848
|
+
this._peers.add(peer);
|
|
849
|
+
return peer;
|
|
850
|
+
}
|
|
851
|
+
*createPeers(opts) {
|
|
852
|
+
while (true) {
|
|
853
|
+
yield this.createPeer(opts);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
async destroy() {
|
|
857
|
+
await Promise.all(Array.from(this._peers).map((agent) => agent.destroy()));
|
|
858
|
+
}
|
|
859
|
+
async connect(peer1, peer2) {
|
|
860
|
+
invariant4(peer1 !== peer2);
|
|
861
|
+
invariant4(this._peers.has(peer1));
|
|
862
|
+
invariant4(this._peers.has(peer1));
|
|
863
|
+
const connection1 = peer1.createConnection({
|
|
864
|
+
initiator: true,
|
|
865
|
+
remotePeerId: peer2.peerId
|
|
866
|
+
});
|
|
867
|
+
const connection2 = peer2.createConnection({
|
|
868
|
+
initiator: false,
|
|
869
|
+
remotePeerId: peer1.peerId
|
|
870
|
+
});
|
|
871
|
+
pipeStreams(connection1.teleport.stream, connection2.teleport.stream);
|
|
872
|
+
await Promise.all([
|
|
873
|
+
peer1.openConnection(connection1),
|
|
874
|
+
peer2.openConnection(connection2)
|
|
875
|
+
]);
|
|
876
|
+
return [
|
|
877
|
+
connection1,
|
|
878
|
+
connection2
|
|
879
|
+
];
|
|
880
|
+
}
|
|
881
|
+
async disconnect(peer1, peer2) {
|
|
882
|
+
invariant4(peer1 !== peer2);
|
|
883
|
+
invariant4(this._peers.has(peer1));
|
|
884
|
+
invariant4(this._peers.has(peer1));
|
|
885
|
+
const connection1 = Array.from(peer1.connections).find((connection) => connection.remotePeerId.equals(peer2.peerId));
|
|
886
|
+
const connection2 = Array.from(peer2.connections).find((connection) => connection.remotePeerId.equals(peer1.peerId));
|
|
887
|
+
invariant4(connection1);
|
|
888
|
+
invariant4(connection2);
|
|
889
|
+
await Promise.all([
|
|
890
|
+
peer1.closeConnection(connection1),
|
|
891
|
+
peer2.closeConnection(connection2)
|
|
892
|
+
]);
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
var TestPeer = class {
|
|
896
|
+
constructor(peerId = PublicKey2.random()) {
|
|
897
|
+
this.peerId = peerId;
|
|
898
|
+
this.connections = /* @__PURE__ */ new Set();
|
|
899
|
+
}
|
|
900
|
+
async onOpen(connection) {
|
|
901
|
+
}
|
|
902
|
+
async onClose(connection) {
|
|
903
|
+
}
|
|
904
|
+
createConnection({ initiator, remotePeerId }) {
|
|
905
|
+
const connection = new TestConnection(this.peerId, remotePeerId, initiator);
|
|
906
|
+
this.connections.add(connection);
|
|
907
|
+
return connection;
|
|
908
|
+
}
|
|
909
|
+
async openConnection(connection) {
|
|
910
|
+
invariant4(this.connections.has(connection));
|
|
911
|
+
await connection.teleport.open();
|
|
912
|
+
await this.onOpen(connection);
|
|
913
|
+
}
|
|
914
|
+
async closeConnection(connection) {
|
|
915
|
+
invariant4(this.connections.has(connection));
|
|
916
|
+
await this.onClose(connection);
|
|
917
|
+
await connection.teleport.close();
|
|
918
|
+
this.connections.delete(connection);
|
|
919
|
+
}
|
|
920
|
+
async destroy() {
|
|
921
|
+
for (const teleport of this.connections) {
|
|
922
|
+
await this.closeConnection(teleport);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
var pipeStreams = (stream1, stream2) => {
|
|
927
|
+
pipeline(stream1, stream2, (err) => {
|
|
928
|
+
if (err && err.code !== "ERR_STREAM_PREMATURE_CLOSE") {
|
|
929
|
+
log4.catch(err, void 0, {
|
|
930
|
+
F: __dxlog_file4,
|
|
931
|
+
L: 106,
|
|
932
|
+
S: void 0,
|
|
933
|
+
C: (f, a) => f(...a)
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
pipeline(stream2, stream1, (err) => {
|
|
938
|
+
if (err && err.code !== "ERR_STREAM_PREMATURE_CLOSE") {
|
|
939
|
+
log4.catch(err, void 0, {
|
|
940
|
+
F: __dxlog_file4,
|
|
941
|
+
L: 111,
|
|
942
|
+
S: void 0,
|
|
943
|
+
C: (f, a) => f(...a)
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
});
|
|
947
|
+
};
|
|
948
|
+
var TestConnection = class {
|
|
949
|
+
constructor(localPeerId, remotePeerId, initiator) {
|
|
950
|
+
this.localPeerId = localPeerId;
|
|
951
|
+
this.remotePeerId = remotePeerId;
|
|
952
|
+
this.initiator = initiator;
|
|
953
|
+
this.teleport = new Teleport({
|
|
954
|
+
initiator,
|
|
955
|
+
localPeerId,
|
|
956
|
+
remotePeerId
|
|
712
957
|
});
|
|
713
958
|
}
|
|
714
959
|
};
|
|
715
960
|
|
|
716
961
|
// packages/core/mesh/teleport/src/testing/test-extension.ts
|
|
717
|
-
import
|
|
962
|
+
import invariant5 from "tiny-invariant";
|
|
718
963
|
import { asyncTimeout as asyncTimeout2, Trigger as Trigger2 } from "@dxos/async";
|
|
719
|
-
import { log as
|
|
964
|
+
import { log as log5 } from "@dxos/log";
|
|
720
965
|
import { schema as schema3 } from "@dxos/protocols";
|
|
721
966
|
import { createProtoRpcPeer as createProtoRpcPeer2 } from "@dxos/rpc";
|
|
722
|
-
var
|
|
967
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/testing/test-extension.ts";
|
|
723
968
|
var TestExtension = class {
|
|
724
969
|
constructor(callbacks = {}) {
|
|
725
970
|
this.callbacks = callbacks;
|
|
@@ -732,11 +977,11 @@ var TestExtension = class {
|
|
|
732
977
|
}
|
|
733
978
|
async onOpen(context) {
|
|
734
979
|
var _a, _b;
|
|
735
|
-
|
|
980
|
+
log5("onOpen", {
|
|
736
981
|
localPeerId: context.localPeerId,
|
|
737
982
|
remotePeerId: context.remotePeerId
|
|
738
983
|
}, {
|
|
739
|
-
F:
|
|
984
|
+
F: __dxlog_file5,
|
|
740
985
|
L: 33,
|
|
741
986
|
S: this,
|
|
742
987
|
C: (f, a) => f(...a)
|
|
@@ -771,10 +1016,10 @@ var TestExtension = class {
|
|
|
771
1016
|
}
|
|
772
1017
|
async onClose(err) {
|
|
773
1018
|
var _a, _b, _c;
|
|
774
|
-
|
|
1019
|
+
log5("onClose", {
|
|
775
1020
|
err
|
|
776
1021
|
}, {
|
|
777
|
-
F:
|
|
1022
|
+
F: __dxlog_file5,
|
|
778
1023
|
L: 67,
|
|
779
1024
|
S: this,
|
|
780
1025
|
C: (f, a) => f(...a)
|
|
@@ -790,7 +1035,226 @@ var TestExtension = class {
|
|
|
790
1035
|
const res = await asyncTimeout2(this._rpc.rpc.TestService.testCall({
|
|
791
1036
|
data: message
|
|
792
1037
|
}), 1500);
|
|
793
|
-
|
|
1038
|
+
invariant5(res.data === message);
|
|
1039
|
+
}
|
|
1040
|
+
/**
|
|
1041
|
+
* Force-close the connection.
|
|
1042
|
+
*/
|
|
1043
|
+
async closeConnection(err) {
|
|
1044
|
+
var _a;
|
|
1045
|
+
(_a = this.extensionContext) == null ? void 0 : _a.close(err);
|
|
1046
|
+
}
|
|
1047
|
+
};
|
|
1048
|
+
|
|
1049
|
+
// packages/core/mesh/teleport/src/testing/test-extension-with-streams.ts
|
|
1050
|
+
import assert from "@dxos/node-std/assert";
|
|
1051
|
+
import { randomBytes } from "@dxos/node-std/crypto";
|
|
1052
|
+
import { Trigger as Trigger3 } from "@dxos/async";
|
|
1053
|
+
import { log as log6 } from "@dxos/log";
|
|
1054
|
+
import { schema as schema4 } from "@dxos/protocols";
|
|
1055
|
+
import { createProtoRpcPeer as createProtoRpcPeer3 } from "@dxos/rpc";
|
|
1056
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/testing/test-extension-with-streams.ts";
|
|
1057
|
+
var TestExtensionWithStreams = class {
|
|
1058
|
+
constructor(callbacks = {}) {
|
|
1059
|
+
this.callbacks = callbacks;
|
|
1060
|
+
this.open = new Trigger3();
|
|
1061
|
+
this.closed = new Trigger3();
|
|
1062
|
+
this._streams = /* @__PURE__ */ new Map();
|
|
1063
|
+
}
|
|
1064
|
+
get remotePeerId() {
|
|
1065
|
+
var _a;
|
|
1066
|
+
return (_a = this.extensionContext) == null ? void 0 : _a.remotePeerId;
|
|
1067
|
+
}
|
|
1068
|
+
async _openStream(streamTag, interval = 5, chunkSize = 2048) {
|
|
1069
|
+
assert(!this._streams.has(streamTag), `Stream already exists: ${streamTag}`);
|
|
1070
|
+
const networkStream = await this.extensionContext.createStream(streamTag, {
|
|
1071
|
+
contentType: "application/x-test-stream"
|
|
1072
|
+
});
|
|
1073
|
+
const streamEntry = {
|
|
1074
|
+
networkStream,
|
|
1075
|
+
bytesSent: 0,
|
|
1076
|
+
bytesReceived: 0,
|
|
1077
|
+
sendErrors: 0,
|
|
1078
|
+
receiveErrors: 0,
|
|
1079
|
+
startTimestamp: Date.now()
|
|
1080
|
+
};
|
|
1081
|
+
const pushChunk = () => {
|
|
1082
|
+
streamEntry.timer = setTimeout(() => {
|
|
1083
|
+
const chunk = randomBytes(chunkSize);
|
|
1084
|
+
if (!networkStream.write(chunk, "binary", (err) => {
|
|
1085
|
+
if (!err) {
|
|
1086
|
+
streamEntry.bytesSent += chunk.length;
|
|
1087
|
+
} else {
|
|
1088
|
+
streamEntry.sendErrors += 1;
|
|
1089
|
+
}
|
|
1090
|
+
})) {
|
|
1091
|
+
networkStream.once("drain", pushChunk);
|
|
1092
|
+
} else {
|
|
1093
|
+
process.nextTick(pushChunk);
|
|
1094
|
+
}
|
|
1095
|
+
}, interval);
|
|
1096
|
+
};
|
|
1097
|
+
pushChunk();
|
|
1098
|
+
this._streams.set(streamTag, streamEntry);
|
|
1099
|
+
networkStream.on("data", (data) => {
|
|
1100
|
+
streamEntry.bytesReceived += data.length;
|
|
1101
|
+
});
|
|
1102
|
+
networkStream.on("error", (err) => {
|
|
1103
|
+
streamEntry.receiveErrors += 1;
|
|
1104
|
+
});
|
|
1105
|
+
networkStream.on("close", () => {
|
|
1106
|
+
networkStream.removeAllListeners();
|
|
1107
|
+
});
|
|
1108
|
+
streamEntry.reportingTimer = setInterval(() => {
|
|
1109
|
+
var _a, _b;
|
|
1110
|
+
const { bytesSent, bytesReceived, sendErrors, receiveErrors } = streamEntry;
|
|
1111
|
+
log6.trace("dxos.test.stream-stats", {
|
|
1112
|
+
streamTag,
|
|
1113
|
+
bytesSent,
|
|
1114
|
+
bytesReceived,
|
|
1115
|
+
sendErrors,
|
|
1116
|
+
receiveErrors,
|
|
1117
|
+
from: (_a = this.extensionContext) == null ? void 0 : _a.localPeerId,
|
|
1118
|
+
to: (_b = this.extensionContext) == null ? void 0 : _b.remotePeerId
|
|
1119
|
+
}, {
|
|
1120
|
+
F: __dxlog_file6,
|
|
1121
|
+
L: 91,
|
|
1122
|
+
S: this,
|
|
1123
|
+
C: (f, a) => f(...a)
|
|
1124
|
+
});
|
|
1125
|
+
}, 100);
|
|
1126
|
+
}
|
|
1127
|
+
_closeStream(streamTag) {
|
|
1128
|
+
assert(this._streams.has(streamTag), `Stream does not exist: ${streamTag}`);
|
|
1129
|
+
const stream = this._streams.get(streamTag);
|
|
1130
|
+
clearTimeout(stream.timer);
|
|
1131
|
+
clearTimeout(stream.reportingTimer);
|
|
1132
|
+
const { bytesSent, bytesReceived, sendErrors, receiveErrors, startTimestamp } = stream;
|
|
1133
|
+
stream.networkStream.destroy();
|
|
1134
|
+
this._streams.delete(streamTag);
|
|
1135
|
+
return {
|
|
1136
|
+
bytesSent,
|
|
1137
|
+
bytesReceived,
|
|
1138
|
+
sendErrors,
|
|
1139
|
+
receiveErrors,
|
|
1140
|
+
runningTime: Date.now() - (startTimestamp != null ? startTimestamp : 0)
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1143
|
+
async onOpen(context) {
|
|
1144
|
+
var _a, _b;
|
|
1145
|
+
log6("onOpen", {
|
|
1146
|
+
localPeerId: context.localPeerId,
|
|
1147
|
+
remotePeerId: context.remotePeerId
|
|
1148
|
+
}, {
|
|
1149
|
+
F: __dxlog_file6,
|
|
1150
|
+
L: 126,
|
|
1151
|
+
S: this,
|
|
1152
|
+
C: (f, a) => f(...a)
|
|
1153
|
+
});
|
|
1154
|
+
this.extensionContext = context;
|
|
1155
|
+
this._rpc = createProtoRpcPeer3({
|
|
1156
|
+
port: await context.createPort("rpc", {
|
|
1157
|
+
contentType: 'application/x-protobuf; messageType="dxos.rpc.Message"'
|
|
1158
|
+
}),
|
|
1159
|
+
requested: {
|
|
1160
|
+
TestServiceWithStreams: schema4.getService("example.testing.rpc.TestServiceWithStreams")
|
|
1161
|
+
},
|
|
1162
|
+
exposed: {
|
|
1163
|
+
TestServiceWithStreams: schema4.getService("example.testing.rpc.TestServiceWithStreams")
|
|
1164
|
+
},
|
|
1165
|
+
handlers: {
|
|
1166
|
+
TestServiceWithStreams: {
|
|
1167
|
+
requestTestStream: async (request) => {
|
|
1168
|
+
const { data: streamTag, streamLoadInterval, streamLoadChunkSize } = request;
|
|
1169
|
+
await this._openStream(streamTag, streamLoadInterval, streamLoadChunkSize);
|
|
1170
|
+
return {
|
|
1171
|
+
data: streamTag
|
|
1172
|
+
};
|
|
1173
|
+
},
|
|
1174
|
+
closeTestStream: async (request) => {
|
|
1175
|
+
const streamTag = request.data;
|
|
1176
|
+
const { bytesSent, bytesReceived, sendErrors, receiveErrors, runningTime } = this._closeStream(streamTag);
|
|
1177
|
+
return {
|
|
1178
|
+
data: streamTag,
|
|
1179
|
+
bytesSent,
|
|
1180
|
+
bytesReceived,
|
|
1181
|
+
sendErrors,
|
|
1182
|
+
receiveErrors,
|
|
1183
|
+
runningTime
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
},
|
|
1188
|
+
timeout: 2e3
|
|
1189
|
+
});
|
|
1190
|
+
await this._rpc.open();
|
|
1191
|
+
await ((_b = (_a = this.callbacks).onOpen) == null ? void 0 : _b.call(_a));
|
|
1192
|
+
this.open.wake();
|
|
1193
|
+
}
|
|
1194
|
+
async onClose(err) {
|
|
1195
|
+
var _a, _b, _c;
|
|
1196
|
+
log6("onClose", {
|
|
1197
|
+
err
|
|
1198
|
+
}, {
|
|
1199
|
+
F: __dxlog_file6,
|
|
1200
|
+
L: 177,
|
|
1201
|
+
S: this,
|
|
1202
|
+
C: (f, a) => f(...a)
|
|
1203
|
+
});
|
|
1204
|
+
await ((_b = (_a = this.callbacks).onClose) == null ? void 0 : _b.call(_a));
|
|
1205
|
+
this.closed.wake();
|
|
1206
|
+
for (const [streamTag, stream] of Object.entries(this._streams)) {
|
|
1207
|
+
log6("closing stream", {
|
|
1208
|
+
streamTag
|
|
1209
|
+
}, {
|
|
1210
|
+
F: __dxlog_file6,
|
|
1211
|
+
L: 181,
|
|
1212
|
+
S: this,
|
|
1213
|
+
C: (f, a) => f(...a)
|
|
1214
|
+
});
|
|
1215
|
+
clearTimeout(stream.interval);
|
|
1216
|
+
stream.networkStream.destroy();
|
|
1217
|
+
}
|
|
1218
|
+
await ((_c = this._rpc) == null ? void 0 : _c.close());
|
|
1219
|
+
}
|
|
1220
|
+
async addNewStream(streamLoadInterval, streamLoadChunkSize, streamTag) {
|
|
1221
|
+
await this.open.wait({
|
|
1222
|
+
timeout: 1500
|
|
1223
|
+
});
|
|
1224
|
+
if (!streamTag) {
|
|
1225
|
+
streamTag = `stream-${randomBytes(4).toString("hex")}`;
|
|
1226
|
+
}
|
|
1227
|
+
const { data } = await this._rpc.rpc.TestServiceWithStreams.requestTestStream({
|
|
1228
|
+
data: streamTag,
|
|
1229
|
+
streamLoadInterval,
|
|
1230
|
+
streamLoadChunkSize
|
|
1231
|
+
});
|
|
1232
|
+
assert(data === streamTag);
|
|
1233
|
+
await this._openStream(streamTag, streamLoadInterval, streamLoadChunkSize);
|
|
1234
|
+
return streamTag;
|
|
1235
|
+
}
|
|
1236
|
+
async closeStream(streamTag) {
|
|
1237
|
+
await this.open.wait({
|
|
1238
|
+
timeout: 1500
|
|
1239
|
+
});
|
|
1240
|
+
const { data, bytesSent, bytesReceived, sendErrors, receiveErrors, runningTime } = await this._rpc.rpc.TestServiceWithStreams.closeTestStream({
|
|
1241
|
+
data: streamTag
|
|
1242
|
+
});
|
|
1243
|
+
assert(data === streamTag);
|
|
1244
|
+
const local = this._closeStream(streamTag);
|
|
1245
|
+
return {
|
|
1246
|
+
streamTag,
|
|
1247
|
+
stats: {
|
|
1248
|
+
local,
|
|
1249
|
+
remote: {
|
|
1250
|
+
bytesSent,
|
|
1251
|
+
bytesReceived,
|
|
1252
|
+
sendErrors,
|
|
1253
|
+
receiveErrors,
|
|
1254
|
+
runningTime
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
};
|
|
794
1258
|
}
|
|
795
1259
|
/**
|
|
796
1260
|
* Force-close the connection.
|
|
@@ -807,6 +1271,10 @@ export {
|
|
|
807
1271
|
encodeFrame,
|
|
808
1272
|
Muxer,
|
|
809
1273
|
Teleport,
|
|
810
|
-
|
|
1274
|
+
TestBuilder,
|
|
1275
|
+
TestPeer,
|
|
1276
|
+
TestConnection,
|
|
1277
|
+
TestExtension,
|
|
1278
|
+
TestExtensionWithStreams
|
|
811
1279
|
};
|
|
812
|
-
//# sourceMappingURL=chunk-
|
|
1280
|
+
//# sourceMappingURL=chunk-GGVQ27WJ.mjs.map
|