@dxos/network-manager 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.
Files changed (53) hide show
  1. package/dist/lib/browser/{chunk-UKYZHA5S.mjs → chunk-S2JHWVGQ.mjs} +310 -83
  2. package/dist/lib/browser/chunk-S2JHWVGQ.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +1 -1
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/browser/testing/index.mjs +1 -1
  6. package/dist/lib/node/chunk-3SCPMSHV.cjs +3998 -0
  7. package/dist/lib/node/chunk-3SCPMSHV.cjs.map +7 -0
  8. package/dist/lib/node/chunk-DMWORJG3.cjs +471 -0
  9. package/dist/lib/node/chunk-DMWORJG3.cjs.map +7 -0
  10. package/dist/lib/node/datachannel-ABYQKZRC.cjs +35 -0
  11. package/dist/lib/node/datachannel-ABYQKZRC.cjs.map +7 -0
  12. package/dist/lib/node/index.cjs +35 -4250
  13. package/dist/lib/node/index.cjs.map +4 -4
  14. package/dist/lib/node/meta.json +1 -1
  15. package/dist/lib/node/testing/index.cjs +111 -4139
  16. package/dist/lib/node/testing/index.cjs.map +4 -4
  17. package/dist/types/src/connection-log.d.ts.map +1 -1
  18. package/dist/types/src/swarm/connection.d.ts +4 -1
  19. package/dist/types/src/swarm/connection.d.ts.map +1 -1
  20. package/dist/types/src/transport/datachannel/rtc-peer-connection.d.ts +7 -0
  21. package/dist/types/src/transport/datachannel/rtc-peer-connection.d.ts.map +1 -1
  22. package/dist/types/src/transport/libdatachannel-transport.d.ts +3 -1
  23. package/dist/types/src/transport/libdatachannel-transport.d.ts.map +1 -1
  24. package/dist/types/src/transport/memory-transport.d.ts +3 -1
  25. package/dist/types/src/transport/memory-transport.d.ts.map +1 -1
  26. package/dist/types/src/transport/simplepeer-transport-proxy.d.ts +3 -1
  27. package/dist/types/src/transport/simplepeer-transport-proxy.d.ts.map +1 -1
  28. package/dist/types/src/transport/simplepeer-transport-service.d.ts +3 -1
  29. package/dist/types/src/transport/simplepeer-transport-service.d.ts.map +1 -1
  30. package/dist/types/src/transport/simplepeer-transport.d.ts +4 -1
  31. package/dist/types/src/transport/simplepeer-transport.d.ts.map +1 -1
  32. package/dist/types/src/transport/tcp-transport.browser.d.ts +3 -1
  33. package/dist/types/src/transport/tcp-transport.browser.d.ts.map +1 -1
  34. package/dist/types/src/transport/tcp-transport.d.ts +3 -1
  35. package/dist/types/src/transport/tcp-transport.d.ts.map +1 -1
  36. package/dist/types/src/transport/transport.d.ts +17 -0
  37. package/dist/types/src/transport/transport.d.ts.map +1 -1
  38. package/dist/types/src/wire-protocol.d.ts +1 -1
  39. package/dist/types/src/wire-protocol.d.ts.map +1 -1
  40. package/package.json +18 -18
  41. package/src/connection-log.ts +27 -1
  42. package/src/swarm/connection.ts +40 -6
  43. package/src/transport/datachannel/rtc-peer-connection.ts +13 -1
  44. package/src/transport/libdatachannel-transport.ts +44 -4
  45. package/src/transport/memory-transport.ts +14 -1
  46. package/src/transport/simplepeer-transport-proxy.ts +9 -1
  47. package/src/transport/simplepeer-transport-service.ts +14 -0
  48. package/src/transport/simplepeer-transport.ts +67 -3
  49. package/src/transport/tcp-transport.browser.ts +9 -1
  50. package/src/transport/tcp-transport.ts +19 -1
  51. package/src/transport/transport.ts +19 -0
  52. package/src/wire-protocol.ts +3 -3
  53. package/dist/lib/browser/chunk-UKYZHA5S.mjs.map +0 -7
@@ -0,0 +1,3998 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
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
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var chunk_3SCPMSHV_exports = {};
30
+ __export(chunk_3SCPMSHV_exports, {
31
+ Connection: () => Connection,
32
+ ConnectionLimiter: () => ConnectionLimiter,
33
+ ConnectionLog: () => ConnectionLog,
34
+ ConnectionState: () => ConnectionState,
35
+ EventType: () => EventType,
36
+ FullyConnectedTopology: () => FullyConnectedTopology,
37
+ LibDataChannelTransport: () => LibDataChannelTransport,
38
+ MAX_CONCURRENT_INITIATING_CONNECTIONS: () => MAX_CONCURRENT_INITIATING_CONNECTIONS,
39
+ MMSTTopology: () => MMSTTopology,
40
+ MemoryTransport: () => MemoryTransport,
41
+ MemoryTransportFactory: () => MemoryTransportFactory,
42
+ NetworkManager: () => NetworkManager,
43
+ SimplePeerTransport: () => SimplePeerTransport,
44
+ SimplePeerTransportProxy: () => SimplePeerTransportProxy,
45
+ SimplePeerTransportProxyFactory: () => SimplePeerTransportProxyFactory,
46
+ SimplePeerTransportService: () => SimplePeerTransportService,
47
+ StarTopology: () => StarTopology,
48
+ Swarm: () => Swarm,
49
+ SwarmMapper: () => SwarmMapper,
50
+ SwarmMessenger: () => SwarmMessenger,
51
+ TcpTransport: () => TcpTransport,
52
+ TcpTransportFactory: () => TcpTransportFactory,
53
+ TransportKind: () => TransportKind,
54
+ createLibDataChannelTransportFactory: () => createLibDataChannelTransportFactory,
55
+ createSimplePeerTransportFactory: () => createSimplePeerTransportFactory,
56
+ createTeleportProtocolFactory: () => createTeleportProtocolFactory
57
+ });
58
+ module.exports = __toCommonJS(chunk_3SCPMSHV_exports);
59
+ var import_chunk_DMWORJG3 = require("./chunk-DMWORJG3.cjs");
60
+ var import_async = require("@dxos/async");
61
+ var import_context = require("@dxos/context");
62
+ var import_debug = require("@dxos/debug");
63
+ var import_invariant = require("@dxos/invariant");
64
+ var import_keys = require("@dxos/keys");
65
+ var import_log = require("@dxos/log");
66
+ var import_protocols = require("@dxos/protocols");
67
+ var import_context2 = require("@dxos/context");
68
+ var import_invariant2 = require("@dxos/invariant");
69
+ var import_keys2 = require("@dxos/keys");
70
+ var import_log2 = require("@dxos/log");
71
+ var import_protocols2 = require("@dxos/protocols");
72
+ var import_util = require("@dxos/util");
73
+ var import_async2 = require("@dxos/async");
74
+ var import_context3 = require("@dxos/context");
75
+ var import_debug2 = require("@dxos/debug");
76
+ var import_invariant3 = require("@dxos/invariant");
77
+ var import_keys3 = require("@dxos/keys");
78
+ var import_log3 = require("@dxos/log");
79
+ var import_protocols3 = require("@dxos/protocols");
80
+ var import_util2 = require("@dxos/util");
81
+ var import_async3 = require("@dxos/async");
82
+ var import_context4 = require("@dxos/context");
83
+ var import_invariant4 = require("@dxos/invariant");
84
+ var import_keys4 = require("@dxos/keys");
85
+ var import_log4 = require("@dxos/log");
86
+ var import_protocols4 = require("@dxos/protocols");
87
+ var import_async4 = require("@dxos/async");
88
+ var import_keys5 = require("@dxos/keys");
89
+ var import_log5 = require("@dxos/log");
90
+ var import_util3 = require("@dxos/util");
91
+ var import_async5 = require("@dxos/async");
92
+ var import_context5 = require("@dxos/context");
93
+ var import_invariant5 = require("@dxos/invariant");
94
+ var import_keys6 = require("@dxos/keys");
95
+ var import_log6 = require("@dxos/log");
96
+ var import_protocols5 = require("@dxos/protocols");
97
+ var import_util4 = require("@dxos/util");
98
+ var import_async6 = require("@dxos/async");
99
+ var import_debug3 = require("@dxos/debug");
100
+ var import_keys7 = require("@dxos/keys");
101
+ var import_util5 = require("@dxos/util");
102
+ var import_async7 = require("@dxos/async");
103
+ var import_invariant6 = require("@dxos/invariant");
104
+ var import_keys8 = require("@dxos/keys");
105
+ var import_log7 = require("@dxos/log");
106
+ var import_messaging = require("@dxos/messaging");
107
+ var import_protocols6 = require("@dxos/protocols");
108
+ var import_services = require("@dxos/protocols/proto/dxos/client/services");
109
+ var import_util6 = require("@dxos/util");
110
+ var import_invariant7 = require("@dxos/invariant");
111
+ var import_xor_distance = __toESM(require("xor-distance"));
112
+ var import_invariant8 = require("@dxos/invariant");
113
+ var import_log8 = require("@dxos/log");
114
+ var import_invariant9 = require("@dxos/invariant");
115
+ var import_log9 = require("@dxos/log");
116
+ var import_node_stream = require("node:stream");
117
+ var import_async8 = require("@dxos/async");
118
+ var import_debug4 = require("@dxos/debug");
119
+ var import_invariant10 = require("@dxos/invariant");
120
+ var import_keys9 = require("@dxos/keys");
121
+ var import_log10 = require("@dxos/log");
122
+ var import_util7 = require("@dxos/util");
123
+ var import_simple_peer = __toESM(require("simple-peer"));
124
+ var import_tiny_invariant = __toESM(require("tiny-invariant"));
125
+ var import_async9 = require("@dxos/async");
126
+ var import_debug5 = require("@dxos/debug");
127
+ var import_keys10 = require("@dxos/keys");
128
+ var import_log11 = require("@dxos/log");
129
+ var import_protocols7 = require("@dxos/protocols");
130
+ var import_node_stream2 = require("node:stream");
131
+ var import_codec_protobuf = require("@dxos/codec-protobuf");
132
+ var import_invariant11 = require("@dxos/invariant");
133
+ var import_keys11 = require("@dxos/keys");
134
+ var import_log12 = require("@dxos/log");
135
+ var import_bridge = require("@dxos/protocols/proto/dxos/mesh/bridge");
136
+ var import_util8 = require("@dxos/util");
137
+ var import_node_stream3 = require("node:stream");
138
+ var import_async10 = require("@dxos/async");
139
+ var import_context6 = require("@dxos/context");
140
+ var import_debug6 = require("@dxos/debug");
141
+ var import_invariant12 = require("@dxos/invariant");
142
+ var import_keys12 = require("@dxos/keys");
143
+ var import_log13 = require("@dxos/log");
144
+ var import_protocols8 = require("@dxos/protocols");
145
+ var import_bridge2 = require("@dxos/protocols/proto/dxos/mesh/bridge");
146
+ var import_util9 = require("@dxos/util");
147
+ var import_stream = require("stream");
148
+ var import_async11 = require("@dxos/async");
149
+ var import_debug7 = require("@dxos/debug");
150
+ var import_log14 = require("@dxos/log");
151
+ var import_node_net = require("node:net");
152
+ var import_async12 = require("@dxos/async");
153
+ var import_debug8 = require("@dxos/debug");
154
+ var import_log15 = require("@dxos/log");
155
+ var import_teleport = require("@dxos/teleport");
156
+ function _ts_decorate(decorators, target, key, desc) {
157
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
158
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
159
+ r = Reflect.decorate(decorators, target, key, desc);
160
+ else
161
+ for (var i = decorators.length - 1; i >= 0; i--)
162
+ if (d = decorators[i])
163
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
164
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
165
+ }
166
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/swarm/connection.ts";
167
+ var STARTING_SIGNALLING_DELAY = 10;
168
+ var TRANSPORT_CONNECTION_TIMEOUT = 1e4;
169
+ var TRANSPORT_STATS_INTERVAL = 5e3;
170
+ var MAX_SIGNALLING_DELAY = 300;
171
+ var ConnectionState;
172
+ (function(ConnectionState5) {
173
+ ConnectionState5[
174
+ /**
175
+ * Connection is created, but not yet passed through the connection limiter.
176
+ */
177
+ "CREATED"
178
+ ] = "CREATED";
179
+ ConnectionState5[
180
+ /**
181
+ * Initial state. Connection is registered but no attempt to connect to the remote peer has been performed.
182
+ * Might mean that we are waiting for the answer signal from the remote peer.
183
+ */
184
+ "INITIAL"
185
+ ] = "INITIAL";
186
+ ConnectionState5[
187
+ /**
188
+ * Trying to establish connection.
189
+ */
190
+ "CONNECTING"
191
+ ] = "CONNECTING";
192
+ ConnectionState5[
193
+ /**
194
+ * Connection is established.
195
+ */
196
+ "CONNECTED"
197
+ ] = "CONNECTED";
198
+ ConnectionState5[
199
+ /**
200
+ * Connection is being closed.
201
+ */
202
+ "CLOSING"
203
+ ] = "CLOSING";
204
+ ConnectionState5[
205
+ /**
206
+ * Connection closed.
207
+ */
208
+ "CLOSED"
209
+ ] = "CLOSED";
210
+ ConnectionState5["ABORTING"] = "ABORTING";
211
+ ConnectionState5["ABORTED"] = "ABORTED";
212
+ })(ConnectionState || (ConnectionState = {}));
213
+ var Connection = class {
214
+ constructor(topic, ownId, remoteId, sessionId, initiator, _signalMessaging, _protocol, _transportFactory, _callbacks) {
215
+ this.topic = topic;
216
+ this.ownId = ownId;
217
+ this.remoteId = remoteId;
218
+ this.sessionId = sessionId;
219
+ this.initiator = initiator;
220
+ this._signalMessaging = _signalMessaging;
221
+ this._protocol = _protocol;
222
+ this._transportFactory = _transportFactory;
223
+ this._callbacks = _callbacks;
224
+ this._ctx = new import_context.Context();
225
+ this.connectedTimeoutContext = new import_context.Context();
226
+ this._state = ConnectionState.CREATED;
227
+ this._incomingSignalBuffer = [];
228
+ this._outgoingSignalBuffer = [];
229
+ this.stateChanged = new import_async.Event();
230
+ this.errors = new import_debug.ErrorStream();
231
+ this._instanceId = import_keys.PublicKey.random().toHex();
232
+ this.transportStats = new import_async.Event();
233
+ this._signalSendTask = new import_async.DeferredTask(this._ctx, async () => {
234
+ await this._flushSignalBuffer();
235
+ });
236
+ this._signallingDelay = STARTING_SIGNALLING_DELAY;
237
+ import_log.log.trace("dxos.mesh.connection.construct", {
238
+ sessionId: this.sessionId,
239
+ topic: this.topic,
240
+ localPeerId: this.ownId,
241
+ remotePeerId: this.remoteId,
242
+ initiator: this.initiator
243
+ }, {
244
+ F: __dxlog_file,
245
+ L: 134,
246
+ S: this,
247
+ C: (f, a) => f(...a)
248
+ });
249
+ }
250
+ get sessionIdString() {
251
+ return this.sessionId.truncate();
252
+ }
253
+ get state() {
254
+ return this._state;
255
+ }
256
+ get transport() {
257
+ return this._transport;
258
+ }
259
+ get protocol() {
260
+ return this._protocol;
261
+ }
262
+ /**
263
+ * Create an underlying transport and prepares it for the connection.
264
+ */
265
+ async openConnection() {
266
+ (0, import_invariant.invariant)(this._state === ConnectionState.INITIAL, "Invalid state.", {
267
+ F: __dxlog_file,
268
+ L: 164,
269
+ S: this,
270
+ A: [
271
+ "this._state === ConnectionState.INITIAL",
272
+ "'Invalid state.'"
273
+ ]
274
+ });
275
+ import_log.log.trace("dxos.mesh.connection.open-connection", import_protocols.trace.begin({
276
+ id: this._instanceId
277
+ }), {
278
+ F: __dxlog_file,
279
+ L: 165,
280
+ S: this,
281
+ C: (f, a) => f(...a)
282
+ });
283
+ import_log.log.trace("dxos.mesh.connection.open", {
284
+ sessionId: this.sessionId,
285
+ topic: this.topic,
286
+ localPeerId: this.ownId,
287
+ remotePeerId: this.remoteId,
288
+ initiator: this.initiator
289
+ }, {
290
+ F: __dxlog_file,
291
+ L: 166,
292
+ S: this,
293
+ C: (f, a) => f(...a)
294
+ });
295
+ this._changeState(ConnectionState.CONNECTING);
296
+ this._protocol.open(this.sessionId).catch((err) => {
297
+ this.errors.raise(err);
298
+ });
299
+ this._protocol.stream.on("close", () => {
300
+ (0, import_log.log)("protocol stream closed", void 0, {
301
+ F: __dxlog_file,
302
+ L: 183,
303
+ S: this,
304
+ C: (f, a) => f(...a)
305
+ });
306
+ this.close(new import_protocols.ProtocolError("protocol stream closed")).catch((err) => this.errors.raise(err));
307
+ });
308
+ (0, import_async.scheduleTask)(this.connectedTimeoutContext, async () => {
309
+ import_log.log.info(`timeout waiting ${TRANSPORT_CONNECTION_TIMEOUT / 1e3}s for transport to connect, aborting`, void 0, {
310
+ F: __dxlog_file,
311
+ L: 190,
312
+ S: this,
313
+ C: (f, a) => f(...a)
314
+ });
315
+ await this.abort(new import_protocols.TimeoutError(`${TRANSPORT_CONNECTION_TIMEOUT / 1e3}s for transport to connect`)).catch((err) => this.errors.raise(err));
316
+ }, TRANSPORT_CONNECTION_TIMEOUT);
317
+ (0, import_invariant.invariant)(!this._transport, void 0, {
318
+ F: __dxlog_file,
319
+ L: 198,
320
+ S: this,
321
+ A: [
322
+ "!this._transport",
323
+ ""
324
+ ]
325
+ });
326
+ this._transport = this._transportFactory.createTransport({
327
+ initiator: this.initiator,
328
+ stream: this._protocol.stream,
329
+ sendSignal: async (signal) => this._sendSignal(signal),
330
+ sessionId: this.sessionId
331
+ });
332
+ this._transport.connected.once(async () => {
333
+ this._changeState(ConnectionState.CONNECTED);
334
+ await this.connectedTimeoutContext.dispose();
335
+ this._callbacks?.onConnected?.();
336
+ (0, import_async.scheduleTaskInterval)(this._ctx, async () => this._emitTransportStats(), TRANSPORT_STATS_INTERVAL);
337
+ });
338
+ this._transport.closed.once(() => {
339
+ this._transport = void 0;
340
+ (0, import_log.log)("abort triggered by transport close", void 0, {
341
+ F: __dxlog_file,
342
+ L: 216,
343
+ S: this,
344
+ C: (f, a) => f(...a)
345
+ });
346
+ this.abort().catch((err) => this.errors.raise(err));
347
+ });
348
+ this._transport.errors.handle(async (err) => {
349
+ (0, import_log.log)("transport error:", {
350
+ err
351
+ }, {
352
+ F: __dxlog_file,
353
+ L: 221,
354
+ S: this,
355
+ C: (f, a) => f(...a)
356
+ });
357
+ if (!this.closeReason) {
358
+ this.closeReason = err?.message;
359
+ }
360
+ if (err instanceof import_protocols.ConnectionResetError) {
361
+ import_log.log.info("aborting due to transport ConnectionResetError", void 0, {
362
+ F: __dxlog_file,
363
+ L: 228,
364
+ S: this,
365
+ C: (f, a) => f(...a)
366
+ });
367
+ this.abort().catch((err2) => this.errors.raise(err2));
368
+ } else if (err instanceof import_protocols.ConnectivityError) {
369
+ import_log.log.info("aborting due to transport ConnectivityError", void 0, {
370
+ F: __dxlog_file,
371
+ L: 231,
372
+ S: this,
373
+ C: (f, a) => f(...a)
374
+ });
375
+ this.abort().catch((err2) => this.errors.raise(err2));
376
+ } else if (err instanceof import_protocols.UnknownProtocolError) {
377
+ import_log.log.warn("unsure what to do with UnknownProtocolError, will keep on truckin", {
378
+ err
379
+ }, {
380
+ F: __dxlog_file,
381
+ L: 234,
382
+ S: this,
383
+ C: (f, a) => f(...a)
384
+ });
385
+ }
386
+ if (this._state !== ConnectionState.CLOSED && this._state !== ConnectionState.CLOSING) {
387
+ await this.connectedTimeoutContext.dispose();
388
+ this.errors.raise(err);
389
+ }
390
+ });
391
+ for (const signal of this._incomingSignalBuffer) {
392
+ void this._transport.signal(signal);
393
+ }
394
+ this._incomingSignalBuffer = [];
395
+ import_log.log.trace("dxos.mesh.connection.open-connection", import_protocols.trace.end({
396
+ id: this._instanceId
397
+ }), {
398
+ F: __dxlog_file,
399
+ L: 250,
400
+ S: this,
401
+ C: (f, a) => f(...a)
402
+ });
403
+ }
404
+ async abort(err) {
405
+ (0, import_log.log)("aborting...", {
406
+ err
407
+ }, {
408
+ F: __dxlog_file,
409
+ L: 257,
410
+ S: this,
411
+ C: (f, a) => f(...a)
412
+ });
413
+ if (this._state === ConnectionState.CLOSED || this._state === ConnectionState.ABORTED) {
414
+ (0, import_log.log)(`abort ignored: already ${this._state}`, this.closeReason, {
415
+ F: __dxlog_file,
416
+ L: 259,
417
+ S: this,
418
+ C: (f, a) => f(...a)
419
+ });
420
+ return;
421
+ }
422
+ await this.connectedTimeoutContext.dispose();
423
+ this._changeState(ConnectionState.ABORTING);
424
+ if (!this.closeReason) {
425
+ this.closeReason = err?.message;
426
+ }
427
+ await this._ctx.dispose();
428
+ try {
429
+ (0, import_log.log)("aborting protocol... ", void 0, {
430
+ F: __dxlog_file,
431
+ L: 273,
432
+ S: this,
433
+ C: (f, a) => f(...a)
434
+ });
435
+ await this._protocol.abort();
436
+ } catch (err2) {
437
+ import_log.log.catch(err2, void 0, {
438
+ F: __dxlog_file,
439
+ L: 276,
440
+ S: this,
441
+ C: (f, a) => f(...a)
442
+ });
443
+ }
444
+ try {
445
+ await this._transport?.destroy();
446
+ } catch (err2) {
447
+ import_log.log.catch(err2, void 0, {
448
+ F: __dxlog_file,
449
+ L: 283,
450
+ S: this,
451
+ C: (f, a) => f(...a)
452
+ });
453
+ }
454
+ try {
455
+ this._callbacks?.onClosed?.(err);
456
+ } catch (err2) {
457
+ import_log.log.catch(err2, void 0, {
458
+ F: __dxlog_file,
459
+ L: 289,
460
+ S: this,
461
+ C: (f, a) => f(...a)
462
+ });
463
+ }
464
+ this._changeState(ConnectionState.ABORTED);
465
+ }
466
+ async close(err) {
467
+ if (!this.closeReason) {
468
+ this.closeReason = err?.message;
469
+ } else {
470
+ this.closeReason += `; ${err?.message}`;
471
+ }
472
+ if (this._state === ConnectionState.CLOSED || this._state === ConnectionState.ABORTING || this._state === ConnectionState.ABORTED) {
473
+ return;
474
+ }
475
+ const lastState = this._state;
476
+ this._changeState(ConnectionState.CLOSING);
477
+ await this.connectedTimeoutContext.dispose();
478
+ await this._ctx.dispose();
479
+ (0, import_log.log)("closing...", {
480
+ peerId: this.ownId
481
+ }, {
482
+ F: __dxlog_file,
483
+ L: 314,
484
+ S: this,
485
+ C: (f, a) => f(...a)
486
+ });
487
+ if (lastState === ConnectionState.CONNECTED) {
488
+ try {
489
+ await this._protocol.close();
490
+ } catch (err2) {
491
+ import_log.log.catch(err2, void 0, {
492
+ F: __dxlog_file,
493
+ L: 321,
494
+ S: this,
495
+ C: (f, a) => f(...a)
496
+ });
497
+ }
498
+ try {
499
+ await this._transport?.destroy();
500
+ } catch (err2) {
501
+ import_log.log.catch(err2, void 0, {
502
+ F: __dxlog_file,
503
+ L: 328,
504
+ S: this,
505
+ C: (f, a) => f(...a)
506
+ });
507
+ }
508
+ } else {
509
+ import_log.log.info(`graceful close requested when we were in ${lastState} state? aborting`, void 0, {
510
+ F: __dxlog_file,
511
+ L: 331,
512
+ S: this,
513
+ C: (f, a) => f(...a)
514
+ });
515
+ try {
516
+ await this._protocol.abort();
517
+ } catch (err2) {
518
+ import_log.log.catch(err2, void 0, {
519
+ F: __dxlog_file,
520
+ L: 335,
521
+ S: this,
522
+ C: (f, a) => f(...a)
523
+ });
524
+ }
525
+ try {
526
+ await this._transport?.destroy();
527
+ } catch (err2) {
528
+ import_log.log.catch(err2, void 0, {
529
+ F: __dxlog_file,
530
+ L: 340,
531
+ S: this,
532
+ C: (f, a) => f(...a)
533
+ });
534
+ }
535
+ }
536
+ (0, import_log.log)("closed", {
537
+ peerId: this.ownId
538
+ }, {
539
+ F: __dxlog_file,
540
+ L: 344,
541
+ S: this,
542
+ C: (f, a) => f(...a)
543
+ });
544
+ this._changeState(ConnectionState.CLOSED);
545
+ this._callbacks?.onClosed?.(err);
546
+ }
547
+ _sendSignal(signal) {
548
+ this._outgoingSignalBuffer.push(signal);
549
+ this._signalSendTask.schedule();
550
+ }
551
+ async _flushSignalBuffer() {
552
+ if (this._outgoingSignalBuffer.length === 0) {
553
+ return;
554
+ }
555
+ try {
556
+ if (process.env.NODE_ENV !== "test") {
557
+ await (0, import_context.cancelWithContext)(this._ctx, (0, import_async.sleep)(this._signallingDelay));
558
+ this._signallingDelay = Math.min(this._signallingDelay * 2, MAX_SIGNALLING_DELAY);
559
+ }
560
+ const signals = [
561
+ ...this._outgoingSignalBuffer
562
+ ];
563
+ this._outgoingSignalBuffer.length = 0;
564
+ await this._signalMessaging.signal({
565
+ author: this.ownId,
566
+ recipient: this.remoteId,
567
+ sessionId: this.sessionId,
568
+ topic: this.topic,
569
+ data: {
570
+ signalBatch: {
571
+ signals
572
+ }
573
+ }
574
+ });
575
+ } catch (err) {
576
+ if (err instanceof import_protocols.CancelledError || err instanceof Error && err.message?.includes("CANCELLED")) {
577
+ return;
578
+ }
579
+ import_log.log.info("signal message failed to deliver", {
580
+ err
581
+ }, {
582
+ F: __dxlog_file,
583
+ L: 382,
584
+ S: this,
585
+ C: (f, a) => f(...a)
586
+ });
587
+ await this.close(new import_protocols.ConnectivityError("signal message failed to deliver", err));
588
+ }
589
+ }
590
+ /**
591
+ * Receive a signal from the remote peer.
592
+ */
593
+ async signal(msg) {
594
+ (0, import_invariant.invariant)(msg.sessionId, void 0, {
595
+ F: __dxlog_file,
596
+ L: 391,
597
+ S: this,
598
+ A: [
599
+ "msg.sessionId",
600
+ ""
601
+ ]
602
+ });
603
+ if (!msg.sessionId.equals(this.sessionId)) {
604
+ (0, import_log.log)("dropping signal for incorrect session id", void 0, {
605
+ F: __dxlog_file,
606
+ L: 393,
607
+ S: this,
608
+ C: (f, a) => f(...a)
609
+ });
610
+ return;
611
+ }
612
+ (0, import_invariant.invariant)(msg.data.signal || msg.data.signalBatch, void 0, {
613
+ F: __dxlog_file,
614
+ L: 396,
615
+ S: this,
616
+ A: [
617
+ "msg.data.signal || msg.data.signalBatch",
618
+ ""
619
+ ]
620
+ });
621
+ (0, import_invariant.invariant)(msg.author?.equals(this.remoteId), void 0, {
622
+ F: __dxlog_file,
623
+ L: 397,
624
+ S: this,
625
+ A: [
626
+ "msg.author?.equals(this.remoteId)",
627
+ ""
628
+ ]
629
+ });
630
+ (0, import_invariant.invariant)(msg.recipient?.equals(this.ownId), void 0, {
631
+ F: __dxlog_file,
632
+ L: 398,
633
+ S: this,
634
+ A: [
635
+ "msg.recipient?.equals(this.ownId)",
636
+ ""
637
+ ]
638
+ });
639
+ const signals = msg.data.signalBatch ? msg.data.signalBatch.signals ?? [] : [
640
+ msg.data.signal
641
+ ];
642
+ for (const signal of signals) {
643
+ if (!signal) {
644
+ continue;
645
+ }
646
+ if ([
647
+ ConnectionState.CREATED,
648
+ ConnectionState.INITIAL
649
+ ].includes(this.state)) {
650
+ (0, import_log.log)("buffered signal", {
651
+ peerId: this.ownId,
652
+ remoteId: this.remoteId,
653
+ msg: msg.data
654
+ }, {
655
+ F: __dxlog_file,
656
+ L: 407,
657
+ S: this,
658
+ C: (f, a) => f(...a)
659
+ });
660
+ this._incomingSignalBuffer.push(signal);
661
+ } else {
662
+ (0, import_invariant.invariant)(this._transport, "Connection not ready to accept signals.", {
663
+ F: __dxlog_file,
664
+ L: 410,
665
+ S: this,
666
+ A: [
667
+ "this._transport",
668
+ "'Connection not ready to accept signals.'"
669
+ ]
670
+ });
671
+ (0, import_log.log)("received signal", {
672
+ peerId: this.ownId,
673
+ remoteId: this.remoteId,
674
+ msg: msg.data
675
+ }, {
676
+ F: __dxlog_file,
677
+ L: 411,
678
+ S: this,
679
+ C: (f, a) => f(...a)
680
+ });
681
+ await this._transport.signal(signal);
682
+ }
683
+ }
684
+ }
685
+ initiate() {
686
+ this._changeState(ConnectionState.INITIAL);
687
+ }
688
+ _changeState(state) {
689
+ (0, import_log.log)("stateChanged", {
690
+ from: this._state,
691
+ to: state,
692
+ peerId: this.ownId
693
+ }, {
694
+ F: __dxlog_file,
695
+ L: 422,
696
+ S: this,
697
+ C: (f, a) => f(...a)
698
+ });
699
+ (0, import_invariant.invariant)(state !== this._state, "Already in this state.", {
700
+ F: __dxlog_file,
701
+ L: 423,
702
+ S: this,
703
+ A: [
704
+ "state !== this._state",
705
+ "'Already in this state.'"
706
+ ]
707
+ });
708
+ this._state = state;
709
+ this.stateChanged.emit(state);
710
+ }
711
+ async _emitTransportStats() {
712
+ const stats = await this.transport?.getStats();
713
+ if (stats) {
714
+ this.transportStats.emit(stats);
715
+ }
716
+ }
717
+ };
718
+ _ts_decorate([
719
+ import_log.logInfo
720
+ ], Connection.prototype, "sessionIdString", null);
721
+ _ts_decorate([
722
+ import_async.synchronized
723
+ ], Connection.prototype, "abort", null);
724
+ _ts_decorate([
725
+ import_async.synchronized
726
+ ], Connection.prototype, "close", null);
727
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/signal/swarm-messenger.ts";
728
+ var SwarmMessage = import_protocols2.schema.getCodecForType("dxos.mesh.swarm.SwarmMessage");
729
+ var SwarmMessenger = class {
730
+ constructor({ sendMessage, onSignal, onOffer, topic }) {
731
+ this._ctx = new import_context2.Context();
732
+ this._offerRecords = new import_util.ComplexMap((key) => key.toHex());
733
+ this._sendMessage = sendMessage;
734
+ this._onSignal = onSignal;
735
+ this._onOffer = onOffer;
736
+ this._topic = topic;
737
+ }
738
+ async receiveMessage({ author, recipient, payload }) {
739
+ if (payload.type_url !== "dxos.mesh.swarm.SwarmMessage") {
740
+ return;
741
+ }
742
+ const message = SwarmMessage.decode(payload.value);
743
+ if (!this._topic.equals(message.topic)) {
744
+ return;
745
+ }
746
+ (0, import_log2.log)("received", {
747
+ from: author,
748
+ to: recipient,
749
+ msg: message
750
+ }, {
751
+ F: __dxlog_file2,
752
+ L: 69,
753
+ S: this,
754
+ C: (f, a) => f(...a)
755
+ });
756
+ if (message.data?.offer) {
757
+ await this._handleOffer({
758
+ author,
759
+ recipient,
760
+ message
761
+ });
762
+ } else if (message.data?.answer) {
763
+ await this._resolveAnswers(message);
764
+ } else if (message.data?.signal) {
765
+ await this._handleSignal({
766
+ author,
767
+ recipient,
768
+ message
769
+ });
770
+ } else if (message.data?.signalBatch) {
771
+ await this._handleSignal({
772
+ author,
773
+ recipient,
774
+ message
775
+ });
776
+ } else {
777
+ import_log2.log.warn("unknown message", {
778
+ message
779
+ }, {
780
+ F: __dxlog_file2,
781
+ L: 80,
782
+ S: this,
783
+ C: (f, a) => f(...a)
784
+ });
785
+ }
786
+ }
787
+ async signal(message) {
788
+ (0, import_invariant2.invariant)(message.data?.signal || message.data?.signalBatch, "Invalid message", {
789
+ F: __dxlog_file2,
790
+ L: 85,
791
+ S: this,
792
+ A: [
793
+ "message.data?.signal || message.data?.signalBatch",
794
+ "'Invalid message'"
795
+ ]
796
+ });
797
+ await this._sendReliableMessage({
798
+ author: message.author,
799
+ recipient: message.recipient,
800
+ message
801
+ });
802
+ }
803
+ async offer(message) {
804
+ const networkMessage = {
805
+ ...message,
806
+ messageId: import_keys2.PublicKey.random()
807
+ };
808
+ return new Promise((resolve, reject) => {
809
+ this._offerRecords.set(networkMessage.messageId, {
810
+ resolve
811
+ });
812
+ this._sendReliableMessage({
813
+ author: message.author,
814
+ recipient: message.recipient,
815
+ message: networkMessage
816
+ }).catch((err) => reject(err));
817
+ });
818
+ }
819
+ async _sendReliableMessage({ author, recipient, message }) {
820
+ const networkMessage = {
821
+ ...message,
822
+ // Setting unique message_id if it not specified yet.
823
+ messageId: message.messageId ?? import_keys2.PublicKey.random()
824
+ };
825
+ (0, import_log2.log)("sending", {
826
+ from: author,
827
+ to: recipient,
828
+ msg: networkMessage
829
+ }, {
830
+ F: __dxlog_file2,
831
+ L: 123,
832
+ S: this,
833
+ C: (f, a) => f(...a)
834
+ });
835
+ await this._sendMessage({
836
+ author,
837
+ recipient,
838
+ payload: {
839
+ type_url: "dxos.mesh.swarm.SwarmMessage",
840
+ value: SwarmMessage.encode(networkMessage)
841
+ }
842
+ });
843
+ }
844
+ async _resolveAnswers(message) {
845
+ (0, import_invariant2.invariant)(message.data?.answer?.offerMessageId, "No offerMessageId", {
846
+ F: __dxlog_file2,
847
+ L: 135,
848
+ S: this,
849
+ A: [
850
+ "message.data?.answer?.offerMessageId",
851
+ "'No offerMessageId'"
852
+ ]
853
+ });
854
+ const offerRecord = this._offerRecords.get(message.data.answer.offerMessageId);
855
+ if (offerRecord) {
856
+ this._offerRecords.delete(message.data.answer.offerMessageId);
857
+ (0, import_invariant2.invariant)(message.data?.answer, "No answer", {
858
+ F: __dxlog_file2,
859
+ L: 139,
860
+ S: this,
861
+ A: [
862
+ "message.data?.answer",
863
+ "'No answer'"
864
+ ]
865
+ });
866
+ (0, import_log2.log)("resolving", {
867
+ answer: message.data.answer
868
+ }, {
869
+ F: __dxlog_file2,
870
+ L: 140,
871
+ S: this,
872
+ C: (f, a) => f(...a)
873
+ });
874
+ offerRecord.resolve(message.data.answer);
875
+ }
876
+ }
877
+ async _handleOffer({ author, recipient, message }) {
878
+ (0, import_invariant2.invariant)(message.data.offer, "No offer", {
879
+ F: __dxlog_file2,
880
+ L: 154,
881
+ S: this,
882
+ A: [
883
+ "message.data.offer",
884
+ "'No offer'"
885
+ ]
886
+ });
887
+ const offerMessage = {
888
+ author,
889
+ recipient,
890
+ ...message,
891
+ data: {
892
+ offer: message.data.offer
893
+ }
894
+ };
895
+ const answer = await this._onOffer(offerMessage);
896
+ answer.offerMessageId = message.messageId;
897
+ try {
898
+ await this._sendReliableMessage({
899
+ author: recipient,
900
+ recipient: author,
901
+ message: {
902
+ topic: message.topic,
903
+ sessionId: message.sessionId,
904
+ data: {
905
+ answer
906
+ }
907
+ }
908
+ });
909
+ } catch (err) {
910
+ if (err instanceof import_protocols2.TimeoutError) {
911
+ import_log2.log.info("timeout sending answer to offer", {
912
+ err
913
+ }, {
914
+ F: __dxlog_file2,
915
+ L: 175,
916
+ S: this,
917
+ C: (f, a) => f(...a)
918
+ });
919
+ } else {
920
+ import_log2.log.info("error sending answer to offer", {
921
+ err
922
+ }, {
923
+ F: __dxlog_file2,
924
+ L: 177,
925
+ S: this,
926
+ C: (f, a) => f(...a)
927
+ });
928
+ }
929
+ }
930
+ }
931
+ async _handleSignal({ author, recipient, message }) {
932
+ (0, import_invariant2.invariant)(message.messageId, void 0, {
933
+ F: __dxlog_file2,
934
+ L: 191,
935
+ S: this,
936
+ A: [
937
+ "message.messageId",
938
+ ""
939
+ ]
940
+ });
941
+ (0, import_invariant2.invariant)(message.data.signal || message.data.signalBatch, "Invalid message", {
942
+ F: __dxlog_file2,
943
+ L: 192,
944
+ S: this,
945
+ A: [
946
+ "message.data.signal || message.data.signalBatch",
947
+ "'Invalid message'"
948
+ ]
949
+ });
950
+ const signalMessage = {
951
+ author,
952
+ recipient,
953
+ ...message,
954
+ data: {
955
+ signal: message.data.signal,
956
+ signalBatch: message.data.signalBatch
957
+ }
958
+ };
959
+ await this._onSignal(signalMessage);
960
+ }
961
+ };
962
+ function _ts_decorate2(decorators, target, key, desc) {
963
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
964
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
965
+ r = Reflect.decorate(decorators, target, key, desc);
966
+ else
967
+ for (var i = decorators.length - 1; i >= 0; i--)
968
+ if (d = decorators[i])
969
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
970
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
971
+ }
972
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/swarm/peer.ts";
973
+ var ConnectionDisplacedError = class extends import_protocols4.SystemError {
974
+ constructor() {
975
+ super("Connection displaced by remote initiator.");
976
+ }
977
+ };
978
+ var CONNECTION_COUNTS_STABLE_AFTER = 5e3;
979
+ var Peer = class {
980
+ // TODO(burdon): Convert to map?
981
+ constructor(id, topic, localPeerId, _signalMessaging, _protocolProvider, _transportFactory, _connectionLimiter, _callbacks) {
982
+ this.id = id;
983
+ this.topic = topic;
984
+ this.localPeerId = localPeerId;
985
+ this._signalMessaging = _signalMessaging;
986
+ this._protocolProvider = _protocolProvider;
987
+ this._transportFactory = _transportFactory;
988
+ this._connectionLimiter = _connectionLimiter;
989
+ this._callbacks = _callbacks;
990
+ this._availableAfter = 0;
991
+ this.availableToConnect = true;
992
+ this._ctx = new import_context4.Context();
993
+ this.advertizing = false;
994
+ this.initiating = false;
995
+ this.connectionDisplaced = new import_async3.Event();
996
+ }
997
+ /**
998
+ * Respond to remote offer.
999
+ */
1000
+ async onOffer(message) {
1001
+ const remoteId = message.author;
1002
+ if (this.connection && ![
1003
+ ConnectionState.CREATED,
1004
+ ConnectionState.INITIAL,
1005
+ ConnectionState.CONNECTING
1006
+ ].includes(this.connection.state)) {
1007
+ import_log4.log.info(`received offer when connection already in ${this.connection.state} state`, void 0, {
1008
+ F: __dxlog_file3,
1009
+ L: 115,
1010
+ S: this,
1011
+ C: (f, a) => f(...a)
1012
+ });
1013
+ return {
1014
+ accept: false
1015
+ };
1016
+ }
1017
+ if (this.connection || this.initiating) {
1018
+ if (remoteId.toHex() < this.localPeerId.toHex()) {
1019
+ (0, import_log4.log)("close local connection", {
1020
+ localPeerId: this.id,
1021
+ topic: this.topic,
1022
+ remotePeerId: this.localPeerId,
1023
+ sessionId: this.connection?.sessionId
1024
+ }, {
1025
+ F: __dxlog_file3,
1026
+ L: 124,
1027
+ S: this,
1028
+ C: (f, a) => f(...a)
1029
+ });
1030
+ if (this.connection) {
1031
+ await this.closeConnection(new ConnectionDisplacedError());
1032
+ }
1033
+ } else {
1034
+ return {
1035
+ accept: false
1036
+ };
1037
+ }
1038
+ }
1039
+ if (await this._callbacks.onOffer(remoteId)) {
1040
+ if (!this.connection) {
1041
+ (0, import_invariant4.invariant)(message.sessionId, void 0, {
1042
+ F: __dxlog_file3,
1043
+ L: 144,
1044
+ S: this,
1045
+ A: [
1046
+ "message.sessionId",
1047
+ ""
1048
+ ]
1049
+ });
1050
+ const connection = this._createConnection(false, message.sessionId);
1051
+ try {
1052
+ await this._connectionLimiter.connecting(message.sessionId);
1053
+ connection.initiate();
1054
+ await connection.openConnection();
1055
+ } catch (err) {
1056
+ if (!(err instanceof import_protocols4.CancelledError)) {
1057
+ import_log4.log.info("connection error", {
1058
+ topic: this.topic,
1059
+ peerId: this.localPeerId,
1060
+ remoteId: this.id,
1061
+ err
1062
+ }, {
1063
+ F: __dxlog_file3,
1064
+ L: 154,
1065
+ S: this,
1066
+ C: (f, a) => f(...a)
1067
+ });
1068
+ }
1069
+ await this.closeConnection(err);
1070
+ }
1071
+ return {
1072
+ accept: true
1073
+ };
1074
+ }
1075
+ }
1076
+ return {
1077
+ accept: false
1078
+ };
1079
+ }
1080
+ /**
1081
+ * Initiate a connection to the remote peer.
1082
+ */
1083
+ async initiateConnection() {
1084
+ (0, import_invariant4.invariant)(!this.initiating, "Initiation in progress.", {
1085
+ F: __dxlog_file3,
1086
+ L: 171,
1087
+ S: this,
1088
+ A: [
1089
+ "!this.initiating",
1090
+ "'Initiation in progress.'"
1091
+ ]
1092
+ });
1093
+ (0, import_invariant4.invariant)(!this.connection, "Already connected.", {
1094
+ F: __dxlog_file3,
1095
+ L: 172,
1096
+ S: this,
1097
+ A: [
1098
+ "!this.connection",
1099
+ "'Already connected.'"
1100
+ ]
1101
+ });
1102
+ const sessionId = import_keys4.PublicKey.random();
1103
+ (0, import_log4.log)("initiating...", {
1104
+ id: this.id,
1105
+ topic: this.topic,
1106
+ peerId: this.id,
1107
+ sessionId
1108
+ }, {
1109
+ F: __dxlog_file3,
1110
+ L: 174,
1111
+ S: this,
1112
+ C: (f, a) => f(...a)
1113
+ });
1114
+ const connection = this._createConnection(true, sessionId);
1115
+ this.initiating = true;
1116
+ let answer;
1117
+ try {
1118
+ await this._connectionLimiter.connecting(sessionId);
1119
+ connection.initiate();
1120
+ answer = await this._signalMessaging.offer({
1121
+ author: this.localPeerId,
1122
+ recipient: this.id,
1123
+ sessionId,
1124
+ topic: this.topic,
1125
+ data: {
1126
+ offer: {}
1127
+ }
1128
+ });
1129
+ (0, import_log4.log)("received", {
1130
+ answer,
1131
+ topic: this.topic,
1132
+ ownId: this.localPeerId,
1133
+ remoteId: this.id
1134
+ }, {
1135
+ F: __dxlog_file3,
1136
+ L: 191,
1137
+ S: this,
1138
+ C: (f, a) => f(...a)
1139
+ });
1140
+ if (connection.state !== ConnectionState.INITIAL) {
1141
+ (0, import_log4.log)("ignoring response", void 0, {
1142
+ F: __dxlog_file3,
1143
+ L: 193,
1144
+ S: this,
1145
+ C: (f, a) => f(...a)
1146
+ });
1147
+ return;
1148
+ }
1149
+ } catch (err) {
1150
+ (0, import_log4.log)("initiation error: send offer", {
1151
+ err,
1152
+ topic: this.topic,
1153
+ peerId: this.localPeerId,
1154
+ remoteId: this.id
1155
+ }, {
1156
+ F: __dxlog_file3,
1157
+ L: 197,
1158
+ S: this,
1159
+ C: (f, a) => f(...a)
1160
+ });
1161
+ await connection.abort(err);
1162
+ throw err;
1163
+ } finally {
1164
+ this.initiating = false;
1165
+ }
1166
+ try {
1167
+ if (!answer.accept) {
1168
+ this._callbacks.onRejected();
1169
+ return;
1170
+ }
1171
+ } catch (err) {
1172
+ (0, import_log4.log)("initiation error: accept answer", {
1173
+ err,
1174
+ topic: this.topic,
1175
+ peerId: this.localPeerId,
1176
+ remoteId: this.id
1177
+ }, {
1178
+ F: __dxlog_file3,
1179
+ L: 210,
1180
+ S: this,
1181
+ C: (f, a) => f(...a)
1182
+ });
1183
+ await connection.abort(err);
1184
+ throw err;
1185
+ } finally {
1186
+ this.initiating = false;
1187
+ }
1188
+ try {
1189
+ (0, import_log4.log)("opening connection as initiator", void 0, {
1190
+ F: __dxlog_file3,
1191
+ L: 223,
1192
+ S: this,
1193
+ C: (f, a) => f(...a)
1194
+ });
1195
+ await connection.openConnection();
1196
+ this._callbacks.onAccepted();
1197
+ } catch (err) {
1198
+ (0, import_log4.log)("initiation error: open connection", {
1199
+ err,
1200
+ topic: this.topic,
1201
+ peerId: this.localPeerId,
1202
+ remoteId: this.id
1203
+ }, {
1204
+ F: __dxlog_file3,
1205
+ L: 227,
1206
+ S: this,
1207
+ C: (f, a) => f(...a)
1208
+ });
1209
+ import_log4.log.warn("closing connection due to unhandled error on openConnection", {
1210
+ err
1211
+ }, {
1212
+ F: __dxlog_file3,
1213
+ L: 234,
1214
+ S: this,
1215
+ C: (f, a) => f(...a)
1216
+ });
1217
+ await this.closeConnection(err);
1218
+ throw err;
1219
+ } finally {
1220
+ this.initiating = false;
1221
+ }
1222
+ }
1223
+ /**
1224
+ * Create new connection.
1225
+ * Either we're initiating a connection or creating one in response to an offer from the other peer.
1226
+ */
1227
+ _createConnection(initiator, sessionId) {
1228
+ (0, import_log4.log)("creating connection", {
1229
+ topic: this.topic,
1230
+ peerId: this.localPeerId,
1231
+ remoteId: this.id,
1232
+ initiator,
1233
+ sessionId
1234
+ }, {
1235
+ F: __dxlog_file3,
1236
+ L: 248,
1237
+ S: this,
1238
+ C: (f, a) => f(...a)
1239
+ });
1240
+ (0, import_invariant4.invariant)(!this.connection, "Already connected.", {
1241
+ F: __dxlog_file3,
1242
+ L: 255,
1243
+ S: this,
1244
+ A: [
1245
+ "!this.connection",
1246
+ "'Already connected.'"
1247
+ ]
1248
+ });
1249
+ const connection = new Connection(
1250
+ this.topic,
1251
+ this.localPeerId,
1252
+ this.id,
1253
+ sessionId,
1254
+ initiator,
1255
+ this._signalMessaging,
1256
+ // TODO(dmaretskyi): Init only when connection is established.
1257
+ this._protocolProvider({
1258
+ initiator,
1259
+ localPeerId: this.localPeerId,
1260
+ remotePeerId: this.id,
1261
+ topic: this.topic
1262
+ }),
1263
+ this._transportFactory,
1264
+ {
1265
+ onConnected: () => {
1266
+ this.availableToConnect = true;
1267
+ this._lastConnectionTime = Date.now();
1268
+ this._callbacks.onConnected();
1269
+ this._connectionLimiter.doneConnecting(sessionId);
1270
+ import_log4.log.trace("dxos.mesh.connection.connected", {
1271
+ topic: this.topic,
1272
+ localPeerId: this.localPeerId,
1273
+ remotePeerId: this.id,
1274
+ sessionId,
1275
+ initiator
1276
+ }, {
1277
+ F: __dxlog_file3,
1278
+ L: 274,
1279
+ S: this,
1280
+ C: (f, a) => f(...a)
1281
+ });
1282
+ },
1283
+ onClosed: (err) => {
1284
+ (0, import_log4.log)("connection closed", {
1285
+ topic: this.topic,
1286
+ peerId: this.localPeerId,
1287
+ remoteId: this.id,
1288
+ initiator
1289
+ }, {
1290
+ F: __dxlog_file3,
1291
+ L: 283,
1292
+ S: this,
1293
+ C: (f, a) => f(...a)
1294
+ });
1295
+ this._connectionLimiter.doneConnecting(sessionId);
1296
+ (0, import_invariant4.invariant)(this.connection === connection, "Connection mismatch (race condition).", {
1297
+ F: __dxlog_file3,
1298
+ L: 288,
1299
+ S: this,
1300
+ A: [
1301
+ "this.connection === connection",
1302
+ "'Connection mismatch (race condition).'"
1303
+ ]
1304
+ });
1305
+ import_log4.log.trace("dxos.mesh.connection.closed", {
1306
+ topic: this.topic,
1307
+ localPeerId: this.localPeerId,
1308
+ remotePeerId: this.id,
1309
+ sessionId,
1310
+ initiator
1311
+ }, {
1312
+ F: __dxlog_file3,
1313
+ L: 290,
1314
+ S: this,
1315
+ C: (f, a) => f(...a)
1316
+ });
1317
+ if (err instanceof ConnectionDisplacedError) {
1318
+ this.connectionDisplaced.emit(this.connection);
1319
+ } else {
1320
+ if (this._lastConnectionTime && this._lastConnectionTime + CONNECTION_COUNTS_STABLE_AFTER < Date.now()) {
1321
+ this._availableAfter = 0;
1322
+ } else {
1323
+ this.availableToConnect = false;
1324
+ this._availableAfter = increaseInterval(this._availableAfter);
1325
+ }
1326
+ this._callbacks.onDisconnected();
1327
+ (0, import_async3.scheduleTask)(this._connectionCtx, () => {
1328
+ this.availableToConnect = true;
1329
+ this._callbacks.onPeerAvailable();
1330
+ }, this._availableAfter);
1331
+ }
1332
+ this.connection = void 0;
1333
+ }
1334
+ }
1335
+ );
1336
+ this._callbacks.onInitiated(connection);
1337
+ void this._connectionCtx?.dispose();
1338
+ this._connectionCtx = this._ctx.derive();
1339
+ connection.errors.handle((err) => {
1340
+ import_log4.log.info("connection error, closing", {
1341
+ topic: this.topic,
1342
+ peerId: this.localPeerId,
1343
+ remoteId: this.id,
1344
+ initiator,
1345
+ err
1346
+ }, {
1347
+ F: __dxlog_file3,
1348
+ L: 330,
1349
+ S: this,
1350
+ C: (f, a) => f(...a)
1351
+ });
1352
+ import_log4.log.trace("dxos.mesh.connection.error", {
1353
+ topic: this.topic,
1354
+ localPeerId: this.localPeerId,
1355
+ remotePeerId: this.id,
1356
+ sessionId,
1357
+ initiator,
1358
+ err
1359
+ }, {
1360
+ F: __dxlog_file3,
1361
+ L: 337,
1362
+ S: this,
1363
+ C: (f, a) => f(...a)
1364
+ });
1365
+ void this.closeConnection(err);
1366
+ });
1367
+ this.connection = connection;
1368
+ return connection;
1369
+ }
1370
+ async closeConnection(err) {
1371
+ if (!this.connection) {
1372
+ return;
1373
+ }
1374
+ const connection = this.connection;
1375
+ (0, import_log4.log)("closing...", {
1376
+ peerId: this.id,
1377
+ sessionId: connection.sessionId
1378
+ }, {
1379
+ F: __dxlog_file3,
1380
+ L: 362,
1381
+ S: this,
1382
+ C: (f, a) => f(...a)
1383
+ });
1384
+ await connection.close(err);
1385
+ (0, import_log4.log)("closed", {
1386
+ peerId: this.id,
1387
+ sessionId: connection.sessionId
1388
+ }, {
1389
+ F: __dxlog_file3,
1390
+ L: 368,
1391
+ S: this,
1392
+ C: (f, a) => f(...a)
1393
+ });
1394
+ }
1395
+ async onSignal(message) {
1396
+ if (!this.connection) {
1397
+ (0, import_log4.log)("dropping signal message for non-existent connection", {
1398
+ message
1399
+ }, {
1400
+ F: __dxlog_file3,
1401
+ L: 373,
1402
+ S: this,
1403
+ C: (f, a) => f(...a)
1404
+ });
1405
+ return;
1406
+ }
1407
+ await this.connection.signal(message);
1408
+ }
1409
+ async destroy(reason) {
1410
+ await this._ctx.dispose();
1411
+ (0, import_log4.log)("Destroying peer", {
1412
+ peerId: this.id,
1413
+ topic: this.topic
1414
+ }, {
1415
+ F: __dxlog_file3,
1416
+ L: 383,
1417
+ S: this,
1418
+ C: (f, a) => f(...a)
1419
+ });
1420
+ await this?.connection?.close(reason);
1421
+ }
1422
+ };
1423
+ _ts_decorate2([
1424
+ import_async3.synchronized
1425
+ ], Peer.prototype, "destroy", null);
1426
+ var increaseInterval = (interval) => {
1427
+ if (interval === 0) {
1428
+ return 50;
1429
+ } else if (interval < 500) {
1430
+ return 500;
1431
+ } else if (interval < 1e3) {
1432
+ return 1e3;
1433
+ } else if (interval < 5e3) {
1434
+ return 5e3;
1435
+ }
1436
+ return 1e4;
1437
+ };
1438
+ function _ts_decorate3(decorators, target, key, desc) {
1439
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1440
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
1441
+ r = Reflect.decorate(decorators, target, key, desc);
1442
+ else
1443
+ for (var i = decorators.length - 1; i >= 0; i--)
1444
+ if (d = decorators[i])
1445
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1446
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1447
+ }
1448
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/swarm/swarm.ts";
1449
+ var INITIATION_DELAY = 100;
1450
+ var getClassName = (obj) => Object.getPrototypeOf(obj).constructor.name;
1451
+ var Swarm = class {
1452
+ // TODO(burdon): Swarm => Peer.create/destroy =< Connection.open/close
1453
+ // TODO(burdon): Split up properties.
1454
+ constructor(_topic, _ownPeerId, _topology, _protocolProvider, _messenger, _transportFactory, _label, _connectionLimiter, _initiationDelay = INITIATION_DELAY) {
1455
+ this._topic = _topic;
1456
+ this._ownPeerId = _ownPeerId;
1457
+ this._topology = _topology;
1458
+ this._protocolProvider = _protocolProvider;
1459
+ this._messenger = _messenger;
1460
+ this._transportFactory = _transportFactory;
1461
+ this._label = _label;
1462
+ this._connectionLimiter = _connectionLimiter;
1463
+ this._initiationDelay = _initiationDelay;
1464
+ this._ctx = new import_context3.Context();
1465
+ this._listeningHandle = void 0;
1466
+ this._peers = new import_util2.ComplexMap(import_keys3.PublicKey.hash);
1467
+ this._instanceId = import_keys3.PublicKey.random().toHex();
1468
+ this.connectionAdded = new import_async2.Event();
1469
+ this.disconnected = new import_async2.Event();
1470
+ this.connected = new import_async2.Event();
1471
+ this.errors = new import_debug2.ErrorStream();
1472
+ import_log3.log.trace("dxos.mesh.swarm.constructor", import_protocols3.trace.begin({
1473
+ id: this._instanceId,
1474
+ data: {
1475
+ topic: this._topic.toHex(),
1476
+ peerId: this._ownPeerId.toHex()
1477
+ }
1478
+ }), {
1479
+ F: __dxlog_file4,
1480
+ L: 88,
1481
+ S: this,
1482
+ C: (f, a) => f(...a)
1483
+ });
1484
+ (0, import_log3.log)("creating swarm", {
1485
+ peerId: _ownPeerId
1486
+ }, {
1487
+ F: __dxlog_file4,
1488
+ L: 92,
1489
+ S: this,
1490
+ C: (f, a) => f(...a)
1491
+ });
1492
+ _topology.init(this._getSwarmController());
1493
+ this._swarmMessenger = new SwarmMessenger({
1494
+ sendMessage: async (msg) => await this._messenger.sendMessage(msg),
1495
+ onSignal: async (msg) => await this.onSignal(msg),
1496
+ onOffer: async (msg) => await this.onOffer(msg),
1497
+ topic: this._topic
1498
+ });
1499
+ import_log3.log.trace("dxos.mesh.swarm.constructor", import_protocols3.trace.end({
1500
+ id: this._instanceId
1501
+ }), {
1502
+ F: __dxlog_file4,
1503
+ L: 101,
1504
+ S: this,
1505
+ C: (f, a) => f(...a)
1506
+ });
1507
+ }
1508
+ get connections() {
1509
+ return Array.from(this._peers.values()).map((peer) => peer.connection).filter(import_util2.isNotNullOrUndefined);
1510
+ }
1511
+ get ownPeerId() {
1512
+ return this._ownPeerId;
1513
+ }
1514
+ /**
1515
+ * Custom label assigned to this swarm. Used in devtools to display human-readable names for swarms.
1516
+ */
1517
+ get label() {
1518
+ return this._label;
1519
+ }
1520
+ get topic() {
1521
+ return this._topic;
1522
+ }
1523
+ async open() {
1524
+ (0, import_invariant3.invariant)(!this._listeningHandle, void 0, {
1525
+ F: __dxlog_file4,
1526
+ L: 128,
1527
+ S: this,
1528
+ A: [
1529
+ "!this._listeningHandle",
1530
+ ""
1531
+ ]
1532
+ });
1533
+ this._listeningHandle = await this._messenger.listen({
1534
+ peerId: this._ownPeerId,
1535
+ payloadType: "dxos.mesh.swarm.SwarmMessage",
1536
+ onMessage: async (message) => {
1537
+ await this._swarmMessenger.receiveMessage(message).catch((err) => import_log3.log.info("Error while receiving message", {
1538
+ err
1539
+ }, {
1540
+ F: __dxlog_file4,
1541
+ L: 136,
1542
+ S: this,
1543
+ C: (f, a) => f(...a)
1544
+ }));
1545
+ }
1546
+ });
1547
+ }
1548
+ async destroy() {
1549
+ (0, import_log3.log)("destroying...", void 0, {
1550
+ F: __dxlog_file4,
1551
+ L: 142,
1552
+ S: this,
1553
+ C: (f, a) => f(...a)
1554
+ });
1555
+ await this._listeningHandle?.unsubscribe();
1556
+ this._listeningHandle = void 0;
1557
+ await this._ctx.dispose();
1558
+ await this._topology.destroy();
1559
+ await Promise.all(Array.from(this._peers.keys()).map((key) => this._destroyPeer(key, "swarm destroyed")));
1560
+ (0, import_log3.log)("destroyed", void 0, {
1561
+ F: __dxlog_file4,
1562
+ L: 149,
1563
+ S: this,
1564
+ C: (f, a) => f(...a)
1565
+ });
1566
+ }
1567
+ async setTopology(topology) {
1568
+ (0, import_invariant3.invariant)(!this._ctx.disposed, "Swarm is offline", {
1569
+ F: __dxlog_file4,
1570
+ L: 153,
1571
+ S: this,
1572
+ A: [
1573
+ "!this._ctx.disposed",
1574
+ "'Swarm is offline'"
1575
+ ]
1576
+ });
1577
+ if (topology === this._topology) {
1578
+ return;
1579
+ }
1580
+ (0, import_log3.log)("setting topology", {
1581
+ previous: getClassName(this._topology),
1582
+ topology: getClassName(topology)
1583
+ }, {
1584
+ F: __dxlog_file4,
1585
+ L: 157,
1586
+ S: this,
1587
+ C: (f, a) => f(...a)
1588
+ });
1589
+ await this._topology.destroy();
1590
+ this._topology = topology;
1591
+ this._topology.init(this._getSwarmController());
1592
+ this._topology.update();
1593
+ }
1594
+ onSwarmEvent(swarmEvent) {
1595
+ (0, import_log3.log)("swarm event", {
1596
+ swarmEvent
1597
+ }, {
1598
+ F: __dxlog_file4,
1599
+ L: 170,
1600
+ S: this,
1601
+ C: (f, a) => f(...a)
1602
+ });
1603
+ if (this._ctx.disposed) {
1604
+ (0, import_log3.log)("swarm event ignored for disposed swarm", void 0, {
1605
+ F: __dxlog_file4,
1606
+ L: 173,
1607
+ S: this,
1608
+ C: (f, a) => f(...a)
1609
+ });
1610
+ return;
1611
+ }
1612
+ if (swarmEvent.peerAvailable) {
1613
+ const peerId = import_keys3.PublicKey.from(swarmEvent.peerAvailable.peer);
1614
+ (0, import_log3.log)("new peer", {
1615
+ peerId
1616
+ }, {
1617
+ F: __dxlog_file4,
1618
+ L: 179,
1619
+ S: this,
1620
+ C: (f, a) => f(...a)
1621
+ });
1622
+ if (!peerId.equals(this._ownPeerId)) {
1623
+ const peer = this._getOrCreatePeer(peerId);
1624
+ peer.advertizing = true;
1625
+ }
1626
+ } else if (swarmEvent.peerLeft) {
1627
+ const peer = this._peers.get(import_keys3.PublicKey.from(swarmEvent.peerLeft.peer));
1628
+ if (peer) {
1629
+ peer.advertizing = false;
1630
+ if (peer.connection?.state !== ConnectionState.CONNECTED) {
1631
+ void this._destroyPeer(peer.id, "peer left").catch((err) => import_log3.log.catch(err, void 0, {
1632
+ F: __dxlog_file4,
1633
+ L: 190,
1634
+ S: this,
1635
+ C: (f, a) => f(...a)
1636
+ }));
1637
+ }
1638
+ } else {
1639
+ (0, import_log3.log)("received peerLeft but no peer found", {
1640
+ peer: swarmEvent.peerLeft.peer
1641
+ }, {
1642
+ F: __dxlog_file4,
1643
+ L: 193,
1644
+ S: this,
1645
+ C: (f, a) => f(...a)
1646
+ });
1647
+ }
1648
+ }
1649
+ this._topology.update();
1650
+ }
1651
+ async onOffer(message) {
1652
+ (0, import_log3.log)("offer", {
1653
+ message
1654
+ }, {
1655
+ F: __dxlog_file4,
1656
+ L: 202,
1657
+ S: this,
1658
+ C: (f, a) => f(...a)
1659
+ });
1660
+ if (this._ctx.disposed) {
1661
+ (0, import_log3.log)("ignored for disposed swarm", void 0, {
1662
+ F: __dxlog_file4,
1663
+ L: 204,
1664
+ S: this,
1665
+ C: (f, a) => f(...a)
1666
+ });
1667
+ return {
1668
+ accept: false
1669
+ };
1670
+ }
1671
+ (0, import_invariant3.invariant)(message.author, void 0, {
1672
+ F: __dxlog_file4,
1673
+ L: 209,
1674
+ S: this,
1675
+ A: [
1676
+ "message.author",
1677
+ ""
1678
+ ]
1679
+ });
1680
+ if (!message.recipient?.equals(this._ownPeerId)) {
1681
+ (0, import_log3.log)("rejecting offer with incorrect peerId", {
1682
+ message
1683
+ }, {
1684
+ F: __dxlog_file4,
1685
+ L: 211,
1686
+ S: this,
1687
+ C: (f, a) => f(...a)
1688
+ });
1689
+ return {
1690
+ accept: false
1691
+ };
1692
+ }
1693
+ if (!message.topic?.equals(this._topic)) {
1694
+ (0, import_log3.log)("rejecting offer with incorrect topic", {
1695
+ message
1696
+ }, {
1697
+ F: __dxlog_file4,
1698
+ L: 215,
1699
+ S: this,
1700
+ C: (f, a) => f(...a)
1701
+ });
1702
+ return {
1703
+ accept: false
1704
+ };
1705
+ }
1706
+ const peer = this._getOrCreatePeer(message.author);
1707
+ const answer = await peer.onOffer(message);
1708
+ this._topology.update();
1709
+ return answer;
1710
+ }
1711
+ async onSignal(message) {
1712
+ (0, import_log3.log)("signal", {
1713
+ message
1714
+ }, {
1715
+ F: __dxlog_file4,
1716
+ L: 226,
1717
+ S: this,
1718
+ C: (f, a) => f(...a)
1719
+ });
1720
+ if (this._ctx.disposed) {
1721
+ import_log3.log.info("ignored for offline swarm", void 0, {
1722
+ F: __dxlog_file4,
1723
+ L: 228,
1724
+ S: this,
1725
+ C: (f, a) => f(...a)
1726
+ });
1727
+ return;
1728
+ }
1729
+ (0, import_invariant3.invariant)(message.recipient?.equals(this._ownPeerId), `Invalid signal peer id expected=${this.ownPeerId}, actual=${message.recipient}`, {
1730
+ F: __dxlog_file4,
1731
+ L: 231,
1732
+ S: this,
1733
+ A: [
1734
+ "message.recipient?.equals(this._ownPeerId)",
1735
+ "`Invalid signal peer id expected=${this.ownPeerId}, actual=${message.recipient}`"
1736
+ ]
1737
+ });
1738
+ (0, import_invariant3.invariant)(message.topic?.equals(this._topic), void 0, {
1739
+ F: __dxlog_file4,
1740
+ L: 235,
1741
+ S: this,
1742
+ A: [
1743
+ "message.topic?.equals(this._topic)",
1744
+ ""
1745
+ ]
1746
+ });
1747
+ (0, import_invariant3.invariant)(message.author, void 0, {
1748
+ F: __dxlog_file4,
1749
+ L: 236,
1750
+ S: this,
1751
+ A: [
1752
+ "message.author",
1753
+ ""
1754
+ ]
1755
+ });
1756
+ const peer = this._getOrCreatePeer(message.author);
1757
+ await peer.onSignal(message);
1758
+ }
1759
+ // For debug purposes
1760
+ async goOffline() {
1761
+ await this._ctx.dispose();
1762
+ await Promise.all([
1763
+ ...this._peers.keys()
1764
+ ].map((peerId) => this._destroyPeer(peerId, "goOffline")));
1765
+ }
1766
+ // For debug purposes
1767
+ async goOnline() {
1768
+ this._ctx = new import_context3.Context();
1769
+ }
1770
+ _getOrCreatePeer(peerId) {
1771
+ let peer = this._peers.get(peerId);
1772
+ if (!peer) {
1773
+ peer = new Peer(peerId, this._topic, this._ownPeerId, this._swarmMessenger, this._protocolProvider, this._transportFactory, this._connectionLimiter, {
1774
+ onInitiated: (connection) => {
1775
+ this.connectionAdded.emit(connection);
1776
+ },
1777
+ onConnected: () => {
1778
+ this.connected.emit(peerId);
1779
+ },
1780
+ onDisconnected: async () => {
1781
+ if (!peer.advertizing) {
1782
+ await this._destroyPeer(peer.id, "peer disconnected");
1783
+ }
1784
+ this.disconnected.emit(peerId);
1785
+ this._topology.update();
1786
+ },
1787
+ onRejected: () => {
1788
+ if (this._peers.has(peerId)) {
1789
+ (0, import_log3.log)("peer rejected connection", {
1790
+ peerId
1791
+ }, {
1792
+ F: __dxlog_file4,
1793
+ L: 285,
1794
+ S: this,
1795
+ C: (f, a) => f(...a)
1796
+ });
1797
+ void this._destroyPeer(peerId, "peer rejected connection");
1798
+ }
1799
+ },
1800
+ onAccepted: () => {
1801
+ this._topology.update();
1802
+ },
1803
+ onOffer: (remoteId) => {
1804
+ return this._topology.onOffer(remoteId);
1805
+ },
1806
+ onPeerAvailable: () => {
1807
+ this._topology.update();
1808
+ }
1809
+ });
1810
+ this._peers.set(peerId, peer);
1811
+ }
1812
+ return peer;
1813
+ }
1814
+ async _destroyPeer(peerId, reason) {
1815
+ (0, import_invariant3.invariant)(this._peers.has(peerId), void 0, {
1816
+ F: __dxlog_file4,
1817
+ L: 307,
1818
+ S: this,
1819
+ A: [
1820
+ "this._peers.has(peerId)",
1821
+ ""
1822
+ ]
1823
+ });
1824
+ await this._peers.get(peerId).destroy(new Error(reason));
1825
+ this._peers.delete(peerId);
1826
+ }
1827
+ _getSwarmController() {
1828
+ return {
1829
+ getState: () => ({
1830
+ ownPeerId: this._ownPeerId,
1831
+ connected: Array.from(this._peers.values()).filter((peer) => peer.connection).map((peer) => peer.id),
1832
+ candidates: Array.from(this._peers.values()).filter((peer) => !peer.connection && peer.advertizing && peer.availableToConnect).map((peer) => peer.id)
1833
+ }),
1834
+ connect: (peer) => {
1835
+ if (this._ctx.disposed) {
1836
+ return;
1837
+ }
1838
+ (0, import_async2.scheduleTask)(this._ctx, async () => {
1839
+ try {
1840
+ await this._initiateConnection(peer);
1841
+ } catch (err) {
1842
+ (0, import_log3.log)("initiation error", err, {
1843
+ F: __dxlog_file4,
1844
+ L: 333,
1845
+ S: this,
1846
+ C: (f, a) => f(...a)
1847
+ });
1848
+ }
1849
+ });
1850
+ },
1851
+ disconnect: async (peer) => {
1852
+ if (this._ctx.disposed) {
1853
+ return;
1854
+ }
1855
+ (0, import_async2.scheduleTask)(this._ctx, async () => {
1856
+ await this._closeConnection(peer);
1857
+ this._topology.update();
1858
+ });
1859
+ }
1860
+ };
1861
+ }
1862
+ /**
1863
+ * Creates a connection then sends message over signal network.
1864
+ */
1865
+ async _initiateConnection(remoteId) {
1866
+ const ctx = this._ctx;
1867
+ if (remoteId.toHex() < this._ownPeerId.toHex()) {
1868
+ (0, import_log3.log)("initiation delay", {
1869
+ remoteId
1870
+ }, {
1871
+ F: __dxlog_file4,
1872
+ L: 360,
1873
+ S: this,
1874
+ C: (f, a) => f(...a)
1875
+ });
1876
+ await (0, import_async2.sleep)(this._initiationDelay);
1877
+ }
1878
+ if (ctx.disposed) {
1879
+ return;
1880
+ }
1881
+ const peer = this._getOrCreatePeer(remoteId);
1882
+ if (peer.connection) {
1883
+ return;
1884
+ }
1885
+ (0, import_log3.log)("initiating connection...", {
1886
+ remoteId
1887
+ }, {
1888
+ F: __dxlog_file4,
1889
+ L: 374,
1890
+ S: this,
1891
+ C: (f, a) => f(...a)
1892
+ });
1893
+ await peer.initiateConnection();
1894
+ this._topology.update();
1895
+ (0, import_log3.log)("initiated", {
1896
+ remoteId
1897
+ }, {
1898
+ F: __dxlog_file4,
1899
+ L: 377,
1900
+ S: this,
1901
+ C: (f, a) => f(...a)
1902
+ });
1903
+ }
1904
+ async _closeConnection(peerId) {
1905
+ const peer = this._peers.get(peerId);
1906
+ if (!peer) {
1907
+ return;
1908
+ }
1909
+ await peer.closeConnection();
1910
+ }
1911
+ };
1912
+ _ts_decorate3([
1913
+ import_log3.logInfo
1914
+ ], Swarm.prototype, "_instanceId", void 0);
1915
+ _ts_decorate3([
1916
+ import_log3.logInfo
1917
+ ], Swarm.prototype, "ownPeerId", null);
1918
+ _ts_decorate3([
1919
+ import_log3.logInfo
1920
+ ], Swarm.prototype, "topic", null);
1921
+ _ts_decorate3([
1922
+ import_async2.synchronized
1923
+ ], Swarm.prototype, "onSwarmEvent", null);
1924
+ _ts_decorate3([
1925
+ import_async2.synchronized
1926
+ ], Swarm.prototype, "onOffer", null);
1927
+ _ts_decorate3([
1928
+ import_async2.synchronized
1929
+ ], Swarm.prototype, "goOffline", null);
1930
+ _ts_decorate3([
1931
+ import_async2.synchronized
1932
+ ], Swarm.prototype, "goOnline", null);
1933
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/swarm/swarm-mapper.ts";
1934
+ var SwarmMapper = class {
1935
+ get peers() {
1936
+ return Array.from(this._peers.values());
1937
+ }
1938
+ constructor(_swarm) {
1939
+ this._swarm = _swarm;
1940
+ this._subscriptions = new import_async4.EventSubscriptions();
1941
+ this._connectionSubscriptions = new import_util3.ComplexMap(import_keys5.PublicKey.hash);
1942
+ this._peers = new import_util3.ComplexMap(import_keys5.PublicKey.hash);
1943
+ this.mapUpdated = new import_async4.Event();
1944
+ this._subscriptions.add(_swarm.connectionAdded.on((connection) => {
1945
+ this._update();
1946
+ this._connectionSubscriptions.set(connection.remoteId, connection.stateChanged.on(() => {
1947
+ this._update();
1948
+ }));
1949
+ }));
1950
+ this._subscriptions.add(_swarm.disconnected.on((peerId) => {
1951
+ this._connectionSubscriptions.get(peerId)?.();
1952
+ this._connectionSubscriptions.delete(peerId);
1953
+ this._update();
1954
+ }));
1955
+ this._update();
1956
+ }
1957
+ _update() {
1958
+ (0, import_log5.log)("updating swarm", void 0, {
1959
+ F: __dxlog_file5,
1960
+ L: 72,
1961
+ S: this,
1962
+ C: (f, a) => f(...a)
1963
+ });
1964
+ this._peers.clear();
1965
+ this._peers.set(this._swarm.ownPeerId, {
1966
+ id: this._swarm.ownPeerId,
1967
+ state: "ME",
1968
+ connections: []
1969
+ });
1970
+ for (const connection of this._swarm.connections) {
1971
+ this._peers.set(connection.remoteId, {
1972
+ id: connection.remoteId,
1973
+ state: connection.state,
1974
+ connections: [
1975
+ this._swarm.ownPeerId
1976
+ ]
1977
+ });
1978
+ }
1979
+ (0, import_log5.log)("graph changed", {
1980
+ directConnections: this._swarm.connections.length,
1981
+ totalPeersInSwarm: this._peers.size
1982
+ }, {
1983
+ F: __dxlog_file5,
1984
+ L: 113,
1985
+ S: this,
1986
+ C: (f, a) => f(...a)
1987
+ });
1988
+ this.mapUpdated.emit(Array.from(this._peers.values()));
1989
+ }
1990
+ // TODO(burdon): Async open/close.
1991
+ destroy() {
1992
+ Array.from(this._connectionSubscriptions.values()).forEach((cb) => cb());
1993
+ this._subscriptions.clear();
1994
+ }
1995
+ };
1996
+ var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/swarm/connection-limiter.ts";
1997
+ var MAX_CONCURRENT_INITIATING_CONNECTIONS = 50;
1998
+ var ConnectionLimiter = class {
1999
+ constructor({ maxConcurrentInitConnections = MAX_CONCURRENT_INITIATING_CONNECTIONS } = {}) {
2000
+ this._ctx = new import_context5.Context();
2001
+ this._waitingPromises = new import_util4.ComplexMap(import_keys6.PublicKey.hash);
2002
+ this.resolveWaitingPromises = new import_async5.DeferredTask(this._ctx, async () => {
2003
+ Array.from(this._waitingPromises.values()).slice(0, this._maxConcurrentInitConnections).forEach(({ resolve }) => {
2004
+ resolve();
2005
+ });
2006
+ });
2007
+ this._maxConcurrentInitConnections = maxConcurrentInitConnections;
2008
+ }
2009
+ /**
2010
+ * @returns Promise that resolves in queue when connections amount with 'CONNECTING' state is below the limit.
2011
+ */
2012
+ async connecting(sessionId) {
2013
+ (0, import_invariant5.invariant)(!this._waitingPromises.has(sessionId), "Peer is already waiting for connection", {
2014
+ F: __dxlog_file6,
2015
+ L: 48,
2016
+ S: this,
2017
+ A: [
2018
+ "!this._waitingPromises.has(sessionId)",
2019
+ "'Peer is already waiting for connection'"
2020
+ ]
2021
+ });
2022
+ (0, import_log6.log)("waiting", {
2023
+ sessionId
2024
+ }, {
2025
+ F: __dxlog_file6,
2026
+ L: 49,
2027
+ S: this,
2028
+ C: (f, a) => f(...a)
2029
+ });
2030
+ await new Promise((resolve, reject) => {
2031
+ this._waitingPromises.set(sessionId, {
2032
+ resolve,
2033
+ reject
2034
+ });
2035
+ this.resolveWaitingPromises.schedule();
2036
+ });
2037
+ (0, import_log6.log)("allow", {
2038
+ sessionId
2039
+ }, {
2040
+ F: __dxlog_file6,
2041
+ L: 57,
2042
+ S: this,
2043
+ C: (f, a) => f(...a)
2044
+ });
2045
+ }
2046
+ /**
2047
+ * Rejects promise returned by `connecting` method.
2048
+ */
2049
+ doneConnecting(sessionId) {
2050
+ (0, import_log6.log)("done", {
2051
+ sessionId
2052
+ }, {
2053
+ F: __dxlog_file6,
2054
+ L: 64,
2055
+ S: this,
2056
+ C: (f, a) => f(...a)
2057
+ });
2058
+ if (!this._waitingPromises.has(sessionId)) {
2059
+ return;
2060
+ }
2061
+ this._waitingPromises.get(sessionId).reject(new import_protocols5.CancelledError());
2062
+ this._waitingPromises.delete(sessionId);
2063
+ this.resolveWaitingPromises.schedule();
2064
+ }
2065
+ };
2066
+ var CONNECTION_GC_THRESHOLD = 1e3 * 60 * 15;
2067
+ var EventType;
2068
+ (function(EventType2) {
2069
+ EventType2["CONNECTION_STATE_CHANGED"] = "CONNECTION_STATE_CHANGED";
2070
+ EventType2["PROTOCOL_ERROR"] = "PROTOCOL_ERROR";
2071
+ EventType2["PROTOCOL_EXTENSIONS_INITIALIZED"] = "PROTOCOL_EXTENSIONS_INITIALIZED";
2072
+ EventType2["PROTOCOL_EXTENSIONS_HANDSHAKE"] = "PROTOCOL_EXTENSIONS_HANDSHAKE";
2073
+ EventType2["PROTOCOL_HANDSHAKE"] = "PROTOCOL_HANDSHAKE";
2074
+ })(EventType || (EventType = {}));
2075
+ var ConnectionLog = class {
2076
+ constructor() {
2077
+ this._swarms = new import_util5.ComplexMap(import_keys7.PublicKey.hash);
2078
+ this.update = new import_async6.Event();
2079
+ }
2080
+ getSwarmInfo(swarmId) {
2081
+ return this._swarms.get(swarmId) ?? (0, import_debug3.raise)(new Error(`Swarm not found: ${swarmId}`));
2082
+ }
2083
+ get swarms() {
2084
+ return Array.from(this._swarms.values());
2085
+ }
2086
+ joinedSwarm(swarm) {
2087
+ const info = {
2088
+ id: import_keys7.PublicKey.from(swarm._instanceId),
2089
+ topic: swarm.topic,
2090
+ isActive: true,
2091
+ label: swarm.label,
2092
+ connections: []
2093
+ };
2094
+ this._swarms.set(import_keys7.PublicKey.from(swarm._instanceId), info);
2095
+ this.update.emit();
2096
+ swarm.connectionAdded.on((connection) => {
2097
+ const connectionInfo = {
2098
+ state: ConnectionState.CREATED,
2099
+ closeReason: connection.closeReason,
2100
+ remotePeerId: connection.remoteId,
2101
+ sessionId: connection.sessionId,
2102
+ transport: connection.transport && Object.getPrototypeOf(connection.transport).constructor.name,
2103
+ protocolExtensions: [],
2104
+ events: [],
2105
+ lastUpdate: /* @__PURE__ */ new Date()
2106
+ };
2107
+ info.connections.push(connectionInfo);
2108
+ this.update.emit();
2109
+ connection.stateChanged.on(async (state) => {
2110
+ connectionInfo.state = state;
2111
+ connectionInfo.closeReason = connection.closeReason;
2112
+ connectionInfo.lastUpdate = /* @__PURE__ */ new Date();
2113
+ connectionInfo.events.push({
2114
+ type: EventType.CONNECTION_STATE_CHANGED,
2115
+ newState: state
2116
+ });
2117
+ if (state === ConnectionState.CONNECTED) {
2118
+ const details = await connection.transport?.getDetails();
2119
+ connectionInfo.transportDetails = details;
2120
+ }
2121
+ this.update.emit();
2122
+ });
2123
+ connection.protocol?.stats?.on((stats) => {
2124
+ connectionInfo.readBufferSize = stats.readBufferSize;
2125
+ connectionInfo.writeBufferSize = stats.writeBufferSize;
2126
+ connectionInfo.streams = stats.channels;
2127
+ connectionInfo.lastUpdate = /* @__PURE__ */ new Date();
2128
+ this.update.emit();
2129
+ });
2130
+ connection.transportStats?.on((stats) => {
2131
+ connectionInfo.transportBytesSent = stats.bytesSent;
2132
+ connectionInfo.transportBytesReceived = stats.bytesReceived;
2133
+ connectionInfo.transportPacketsSent = stats.packetsSent;
2134
+ connectionInfo.transportPacketsReceived = stats.packetsReceived;
2135
+ });
2136
+ gcSwarm(info);
2137
+ });
2138
+ }
2139
+ leftSwarm(swarm) {
2140
+ this.getSwarmInfo(import_keys7.PublicKey.from(swarm._instanceId)).isActive = false;
2141
+ this.update.emit();
2142
+ }
2143
+ };
2144
+ var gcSwarm = (swarm) => {
2145
+ swarm.connections = swarm.connections?.filter((connection) => {
2146
+ return connection.lastUpdate ? Date.now() - connection.lastUpdate.getTime() < CONNECTION_GC_THRESHOLD : true;
2147
+ });
2148
+ };
2149
+ var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/network-manager.ts";
2150
+ var NetworkManager = class {
2151
+ constructor({ transportFactory, signalManager, log: log1 }) {
2152
+ this._swarms = new import_util6.ComplexMap(import_keys8.PublicKey.hash);
2153
+ this._mappers = new import_util6.ComplexMap(import_keys8.PublicKey.hash);
2154
+ this._connectionState = import_services.ConnectionState.ONLINE;
2155
+ this.connectionStateChanged = new import_async7.Event();
2156
+ this.topicsUpdated = new import_async7.Event();
2157
+ this._instanceId = import_keys8.PublicKey.random().toHex();
2158
+ this._transportFactory = transportFactory;
2159
+ this._signalManager = signalManager;
2160
+ this._signalManager.swarmEvent.on(({ topic, swarmEvent: event }) => this._swarms.get(topic)?.onSwarmEvent(event));
2161
+ this._messenger = new import_messaging.Messenger({
2162
+ signalManager: this._signalManager
2163
+ });
2164
+ this._signalConnection = {
2165
+ join: (opts) => this._signalManager.join(opts),
2166
+ leave: (opts) => this._signalManager.leave(opts)
2167
+ };
2168
+ this._connectionLimiter = new ConnectionLimiter();
2169
+ if (log1) {
2170
+ this._connectionLog = new ConnectionLog();
2171
+ }
2172
+ }
2173
+ // TODO(burdon): Remove access (Devtools only).
2174
+ get connectionLog() {
2175
+ return this._connectionLog;
2176
+ }
2177
+ get connectionState() {
2178
+ return this._connectionState;
2179
+ }
2180
+ // TODO(burdon): Reconcile with "discovery_key".
2181
+ get topics() {
2182
+ return Array.from(this._swarms.keys());
2183
+ }
2184
+ getSwarmMap(topic) {
2185
+ return this._mappers.get(topic);
2186
+ }
2187
+ getSwarm(topic) {
2188
+ return this._swarms.get(topic);
2189
+ }
2190
+ async open() {
2191
+ import_log7.log.trace("dxos.mesh.network-manager.open", import_protocols6.trace.begin({
2192
+ id: this._instanceId
2193
+ }), {
2194
+ F: __dxlog_file7,
2195
+ L: 130,
2196
+ S: this,
2197
+ C: (f, a) => f(...a)
2198
+ });
2199
+ await this._messenger.open();
2200
+ await this._signalManager.open();
2201
+ import_log7.log.trace("dxos.mesh.network-manager.open", import_protocols6.trace.end({
2202
+ id: this._instanceId
2203
+ }), {
2204
+ F: __dxlog_file7,
2205
+ L: 133,
2206
+ S: this,
2207
+ C: (f, a) => f(...a)
2208
+ });
2209
+ }
2210
+ async close() {
2211
+ for (const topic of this._swarms.keys()) {
2212
+ await this.leaveSwarm(topic).catch((err) => {
2213
+ (0, import_log7.log)(err, void 0, {
2214
+ F: __dxlog_file7,
2215
+ L: 139,
2216
+ S: this,
2217
+ C: (f, a) => f(...a)
2218
+ });
2219
+ });
2220
+ }
2221
+ await this._messenger.close();
2222
+ await this._signalManager.close();
2223
+ }
2224
+ /**
2225
+ * Join the swarm.
2226
+ */
2227
+ async joinSwarm({ topic, peerId, topology, protocolProvider: protocol, label }) {
2228
+ (0, import_invariant6.invariant)(import_keys8.PublicKey.isPublicKey(topic), void 0, {
2229
+ F: __dxlog_file7,
2230
+ L: 157,
2231
+ S: this,
2232
+ A: [
2233
+ "PublicKey.isPublicKey(topic)",
2234
+ ""
2235
+ ]
2236
+ });
2237
+ (0, import_invariant6.invariant)(import_keys8.PublicKey.isPublicKey(peerId), void 0, {
2238
+ F: __dxlog_file7,
2239
+ L: 158,
2240
+ S: this,
2241
+ A: [
2242
+ "PublicKey.isPublicKey(peerId)",
2243
+ ""
2244
+ ]
2245
+ });
2246
+ (0, import_invariant6.invariant)(topology, void 0, {
2247
+ F: __dxlog_file7,
2248
+ L: 159,
2249
+ S: this,
2250
+ A: [
2251
+ "topology",
2252
+ ""
2253
+ ]
2254
+ });
2255
+ (0, import_invariant6.invariant)(typeof protocol === "function", void 0, {
2256
+ F: __dxlog_file7,
2257
+ L: 160,
2258
+ S: this,
2259
+ A: [
2260
+ "typeof protocol === 'function'",
2261
+ ""
2262
+ ]
2263
+ });
2264
+ if (this._swarms.has(topic)) {
2265
+ throw new Error(`Already connected to swarm: ${import_keys8.PublicKey.from(topic)}`);
2266
+ }
2267
+ (0, import_log7.log)("joining", {
2268
+ topic: import_keys8.PublicKey.from(topic),
2269
+ peerId,
2270
+ topology: topology.toString()
2271
+ }, {
2272
+ F: __dxlog_file7,
2273
+ L: 165,
2274
+ S: this,
2275
+ C: (f, a) => f(...a)
2276
+ });
2277
+ const swarm = new Swarm(topic, peerId, topology, protocol, this._messenger, this._transportFactory, label, this._connectionLimiter);
2278
+ swarm.errors.handle((error) => {
2279
+ (0, import_log7.log)("swarm error", {
2280
+ error
2281
+ }, {
2282
+ F: __dxlog_file7,
2283
+ L: 178,
2284
+ S: this,
2285
+ C: (f, a) => f(...a)
2286
+ });
2287
+ });
2288
+ this._swarms.set(topic, swarm);
2289
+ this._mappers.set(topic, new SwarmMapper(swarm));
2290
+ await swarm.open();
2291
+ this._signalConnection.join({
2292
+ topic,
2293
+ peerId
2294
+ }).catch((error) => import_log7.log.catch(error, void 0, {
2295
+ F: __dxlog_file7,
2296
+ L: 187,
2297
+ S: this,
2298
+ C: (f, a) => f(...a)
2299
+ }));
2300
+ this.topicsUpdated.emit();
2301
+ this._connectionLog?.joinedSwarm(swarm);
2302
+ (0, import_log7.log)("joined", {
2303
+ topic: import_keys8.PublicKey.from(topic),
2304
+ count: this._swarms.size
2305
+ }, {
2306
+ F: __dxlog_file7,
2307
+ L: 191,
2308
+ S: this,
2309
+ C: (f, a) => f(...a)
2310
+ });
2311
+ return {
2312
+ close: () => this.leaveSwarm(topic)
2313
+ };
2314
+ }
2315
+ /**
2316
+ * Close the connection.
2317
+ */
2318
+ async leaveSwarm(topic) {
2319
+ if (!this._swarms.has(topic)) {
2320
+ return;
2321
+ }
2322
+ (0, import_log7.log)("leaving", {
2323
+ topic: import_keys8.PublicKey.from(topic)
2324
+ }, {
2325
+ F: __dxlog_file7,
2326
+ L: 207,
2327
+ S: this,
2328
+ C: (f, a) => f(...a)
2329
+ });
2330
+ const swarm = this._swarms.get(topic);
2331
+ await this._signalConnection.leave({
2332
+ topic,
2333
+ peerId: swarm.ownPeerId
2334
+ });
2335
+ const map = this._mappers.get(topic);
2336
+ map.destroy();
2337
+ this._mappers.delete(topic);
2338
+ this._connectionLog?.leftSwarm(swarm);
2339
+ await swarm.destroy();
2340
+ this._swarms.delete(topic);
2341
+ await this.topicsUpdated.emit();
2342
+ (0, import_log7.log)("left", {
2343
+ topic: import_keys8.PublicKey.from(topic),
2344
+ count: this._swarms.size
2345
+ }, {
2346
+ F: __dxlog_file7,
2347
+ L: 221,
2348
+ S: this,
2349
+ C: (f, a) => f(...a)
2350
+ });
2351
+ }
2352
+ async setConnectionState(state) {
2353
+ if (state === this._connectionState) {
2354
+ return;
2355
+ }
2356
+ switch (state) {
2357
+ case import_services.ConnectionState.OFFLINE: {
2358
+ this._connectionState = state;
2359
+ await Promise.all([
2360
+ ...this._swarms.values()
2361
+ ].map((swarm) => swarm.goOffline()));
2362
+ await this._messenger.close();
2363
+ await this._signalManager.close();
2364
+ break;
2365
+ }
2366
+ case import_services.ConnectionState.ONLINE: {
2367
+ this._connectionState = state;
2368
+ this._messenger.open();
2369
+ await Promise.all([
2370
+ ...this._swarms.values()
2371
+ ].map((swarm) => swarm.goOnline()));
2372
+ await this._signalManager.open();
2373
+ break;
2374
+ }
2375
+ }
2376
+ this.connectionStateChanged.emit(this._connectionState);
2377
+ }
2378
+ };
2379
+ var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/topology/fully-connected-topology.ts";
2380
+ var FullyConnectedTopology = class {
2381
+ toString() {
2382
+ return "FullyConnectedTopology";
2383
+ }
2384
+ init(controller) {
2385
+ (0, import_invariant7.invariant)(!this._controller, "Already initialized", {
2386
+ F: __dxlog_file8,
2387
+ L: 18,
2388
+ S: this,
2389
+ A: [
2390
+ "!this._controller",
2391
+ "'Already initialized'"
2392
+ ]
2393
+ });
2394
+ this._controller = controller;
2395
+ }
2396
+ update() {
2397
+ (0, import_invariant7.invariant)(this._controller, "Not initialized", {
2398
+ F: __dxlog_file8,
2399
+ L: 23,
2400
+ S: this,
2401
+ A: [
2402
+ "this._controller",
2403
+ "'Not initialized'"
2404
+ ]
2405
+ });
2406
+ const { candidates: discovered } = this._controller.getState();
2407
+ for (const peer of discovered) {
2408
+ this._controller.connect(peer);
2409
+ }
2410
+ }
2411
+ async onOffer(peer) {
2412
+ return true;
2413
+ }
2414
+ async destroy() {
2415
+ }
2416
+ };
2417
+ var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/topology/mmst-topology.ts";
2418
+ var MMSTTopology = class {
2419
+ constructor({ originateConnections = 2, maxPeers = 4, sampleSize = 10 } = {}) {
2420
+ this._sampleCollected = false;
2421
+ this._originateConnections = originateConnections;
2422
+ this._maxPeers = maxPeers;
2423
+ this._sampleSize = sampleSize;
2424
+ }
2425
+ init(controller) {
2426
+ (0, import_invariant8.invariant)(!this._controller, "Already initialized", {
2427
+ F: __dxlog_file9,
2428
+ L: 46,
2429
+ S: this,
2430
+ A: [
2431
+ "!this._controller",
2432
+ "'Already initialized'"
2433
+ ]
2434
+ });
2435
+ this._controller = controller;
2436
+ }
2437
+ update() {
2438
+ (0, import_invariant8.invariant)(this._controller, "Not initialized", {
2439
+ F: __dxlog_file9,
2440
+ L: 51,
2441
+ S: this,
2442
+ A: [
2443
+ "this._controller",
2444
+ "'Not initialized'"
2445
+ ]
2446
+ });
2447
+ const { connected, candidates } = this._controller.getState();
2448
+ if (this._sampleCollected || connected.length > this._maxPeers || candidates.length > 0) {
2449
+ (0, import_log8.log)("Running the algorithm.", void 0, {
2450
+ F: __dxlog_file9,
2451
+ L: 55,
2452
+ S: this,
2453
+ C: (f, a) => f(...a)
2454
+ });
2455
+ this._sampleCollected = true;
2456
+ this._runAlgorithm();
2457
+ }
2458
+ }
2459
+ async onOffer(peer) {
2460
+ (0, import_invariant8.invariant)(this._controller, "Not initialized", {
2461
+ F: __dxlog_file9,
2462
+ L: 62,
2463
+ S: this,
2464
+ A: [
2465
+ "this._controller",
2466
+ "'Not initialized'"
2467
+ ]
2468
+ });
2469
+ const { connected } = this._controller.getState();
2470
+ const accept = connected.length < this._maxPeers;
2471
+ (0, import_log8.log)(`Offer ${peer} accept=${accept}`, void 0, {
2472
+ F: __dxlog_file9,
2473
+ L: 65,
2474
+ S: this,
2475
+ C: (f, a) => f(...a)
2476
+ });
2477
+ return accept;
2478
+ }
2479
+ async destroy() {
2480
+ }
2481
+ _runAlgorithm() {
2482
+ (0, import_invariant8.invariant)(this._controller, "Not initialized", {
2483
+ F: __dxlog_file9,
2484
+ L: 74,
2485
+ S: this,
2486
+ A: [
2487
+ "this._controller",
2488
+ "'Not initialized'"
2489
+ ]
2490
+ });
2491
+ const { connected, candidates, ownPeerId } = this._controller.getState();
2492
+ if (connected.length > this._maxPeers) {
2493
+ const sorted = sortByXorDistance(connected, ownPeerId).reverse().slice(0, this._maxPeers - connected.length);
2494
+ for (const peer of sorted) {
2495
+ (0, import_log8.log)(`Disconnect ${peer}.`, void 0, {
2496
+ F: __dxlog_file9,
2497
+ L: 83,
2498
+ S: this,
2499
+ C: (f, a) => f(...a)
2500
+ });
2501
+ this._controller.disconnect(peer);
2502
+ }
2503
+ } else if (connected.length < this._originateConnections) {
2504
+ const sample = candidates.sort(() => Math.random() - 0.5).slice(0, this._sampleSize);
2505
+ const sorted = sortByXorDistance(sample, ownPeerId).slice(0, this._originateConnections - connected.length);
2506
+ for (const peer of sorted) {
2507
+ (0, import_log8.log)(`Connect ${peer}.`, void 0, {
2508
+ F: __dxlog_file9,
2509
+ L: 91,
2510
+ S: this,
2511
+ C: (f, a) => f(...a)
2512
+ });
2513
+ this._controller.connect(peer);
2514
+ }
2515
+ }
2516
+ }
2517
+ toString() {
2518
+ return "MMSTTopology";
2519
+ }
2520
+ };
2521
+ var sortByXorDistance = (keys, reference) => keys.sort((a, b) => import_xor_distance.default.gt((0, import_xor_distance.default)(a.asBuffer(), reference.asBuffer()), (0, import_xor_distance.default)(b.asBuffer(), reference.asBuffer())));
2522
+ var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/topology/star-topology.ts";
2523
+ var StarTopology = class {
2524
+ constructor(_centralPeer) {
2525
+ this._centralPeer = _centralPeer;
2526
+ }
2527
+ toString() {
2528
+ return `StarTopology(${this._centralPeer.truncate()})`;
2529
+ }
2530
+ init(controller) {
2531
+ (0, import_invariant9.invariant)(!this._controller, "Already initialized.", {
2532
+ F: __dxlog_file10,
2533
+ L: 21,
2534
+ S: this,
2535
+ A: [
2536
+ "!this._controller",
2537
+ "'Already initialized.'"
2538
+ ]
2539
+ });
2540
+ this._controller = controller;
2541
+ }
2542
+ update() {
2543
+ (0, import_invariant9.invariant)(this._controller, "Not initialized.", {
2544
+ F: __dxlog_file10,
2545
+ L: 26,
2546
+ S: this,
2547
+ A: [
2548
+ "this._controller",
2549
+ "'Not initialized.'"
2550
+ ]
2551
+ });
2552
+ const { candidates, connected, ownPeerId } = this._controller.getState();
2553
+ if (!ownPeerId.equals(this._centralPeer)) {
2554
+ (0, import_log9.log)("leaf peer dropping all connections apart from central peer.", void 0, {
2555
+ F: __dxlog_file10,
2556
+ L: 29,
2557
+ S: this,
2558
+ C: (f, a) => f(...a)
2559
+ });
2560
+ for (const peer of connected) {
2561
+ if (!peer.equals(this._centralPeer)) {
2562
+ (0, import_log9.log)("dropping connection", {
2563
+ peer
2564
+ }, {
2565
+ F: __dxlog_file10,
2566
+ L: 34,
2567
+ S: this,
2568
+ C: (f, a) => f(...a)
2569
+ });
2570
+ this._controller.disconnect(peer);
2571
+ }
2572
+ }
2573
+ }
2574
+ for (const peer of candidates) {
2575
+ if (peer.equals(this._centralPeer) || ownPeerId.equals(this._centralPeer)) {
2576
+ (0, import_log9.log)("connecting to peer", {
2577
+ peer
2578
+ }, {
2579
+ F: __dxlog_file10,
2580
+ L: 43,
2581
+ S: this,
2582
+ C: (f, a) => f(...a)
2583
+ });
2584
+ this._controller.connect(peer);
2585
+ }
2586
+ }
2587
+ }
2588
+ async onOffer(peer) {
2589
+ (0, import_invariant9.invariant)(this._controller, "Not initialized.", {
2590
+ F: __dxlog_file10,
2591
+ L: 50,
2592
+ S: this,
2593
+ A: [
2594
+ "this._controller",
2595
+ "'Not initialized.'"
2596
+ ]
2597
+ });
2598
+ const { ownPeerId } = this._controller.getState();
2599
+ (0, import_log9.log)("offer", {
2600
+ peer,
2601
+ isCentral: peer.equals(this._centralPeer),
2602
+ isSelfCentral: ownPeerId.equals(this._centralPeer)
2603
+ }, {
2604
+ F: __dxlog_file10,
2605
+ L: 52,
2606
+ S: this,
2607
+ C: (f, a) => f(...a)
2608
+ });
2609
+ return ownPeerId.equals(this._centralPeer) || peer.equals(this._centralPeer);
2610
+ }
2611
+ async destroy() {
2612
+ }
2613
+ };
2614
+ function _ts_decorate4(decorators, target, key, desc) {
2615
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
2616
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
2617
+ r = Reflect.decorate(decorators, target, key, desc);
2618
+ else
2619
+ for (var i = decorators.length - 1; i >= 0; i--)
2620
+ if (d = decorators[i])
2621
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2622
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
2623
+ }
2624
+ var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/memory-transport.ts";
2625
+ var MEMORY_TRANSPORT_DELAY = 1;
2626
+ var createStreamDelay = (delay) => {
2627
+ return new import_node_stream.Transform({
2628
+ objectMode: true,
2629
+ transform: (chunk, _, cb) => {
2630
+ setTimeout(() => cb(null, chunk), delay);
2631
+ }
2632
+ });
2633
+ };
2634
+ var MemoryTransportFactory = {
2635
+ createTransport: (params) => new MemoryTransport(params)
2636
+ };
2637
+ var MemoryTransport = class _MemoryTransport {
2638
+ static {
2639
+ this._connections = new import_util7.ComplexMap(import_keys9.PublicKey.hash);
2640
+ }
2641
+ constructor(options) {
2642
+ this.options = options;
2643
+ this.closed = new import_async8.Event();
2644
+ this.connected = new import_async8.Event();
2645
+ this.errors = new import_debug4.ErrorStream();
2646
+ this._instanceId = import_keys9.PublicKey.random();
2647
+ this._remote = new import_async8.Trigger();
2648
+ this._outgoingDelay = createStreamDelay(MEMORY_TRANSPORT_DELAY);
2649
+ this._incomingDelay = createStreamDelay(MEMORY_TRANSPORT_DELAY);
2650
+ this._destroyed = false;
2651
+ (0, import_log10.log)("creating", void 0, {
2652
+ F: __dxlog_file11,
2653
+ L: 64,
2654
+ S: this,
2655
+ C: (f, a) => f(...a)
2656
+ });
2657
+ (0, import_invariant10.invariant)(!_MemoryTransport._connections.has(this._instanceId), "Duplicate memory connection", {
2658
+ F: __dxlog_file11,
2659
+ L: 66,
2660
+ S: this,
2661
+ A: [
2662
+ "!MemoryTransport._connections.has(this._instanceId)",
2663
+ "'Duplicate memory connection'"
2664
+ ]
2665
+ });
2666
+ _MemoryTransport._connections.set(this._instanceId, this);
2667
+ if (this.options.initiator) {
2668
+ setTimeout(async () => {
2669
+ (0, import_log10.log)("sending signal", void 0, {
2670
+ F: __dxlog_file11,
2671
+ L: 73,
2672
+ S: this,
2673
+ C: (f, a) => f(...a)
2674
+ });
2675
+ void this.options.sendSignal({
2676
+ payload: {
2677
+ transportId: this._instanceId.toHex()
2678
+ }
2679
+ }).catch((err) => {
2680
+ if (!this._destroyed) {
2681
+ this.errors.raise(err);
2682
+ }
2683
+ });
2684
+ });
2685
+ } else {
2686
+ this._remote.wait({
2687
+ timeout: this.options.timeout ?? 1e3
2688
+ }).then((remoteId) => {
2689
+ if (this._destroyed) {
2690
+ return;
2691
+ }
2692
+ this._remoteInstanceId = remoteId;
2693
+ this._remoteConnection = _MemoryTransport._connections.get(this._remoteInstanceId);
2694
+ if (!this._remoteConnection) {
2695
+ this._destroyed = true;
2696
+ this.closed.emit();
2697
+ return;
2698
+ }
2699
+ (0, import_invariant10.invariant)(!this._remoteConnection._remoteConnection, `Remote already connected: ${this._remoteInstanceId}`, {
2700
+ F: __dxlog_file11,
2701
+ L: 99,
2702
+ S: this,
2703
+ A: [
2704
+ "!this._remoteConnection._remoteConnection",
2705
+ "`Remote already connected: ${this._remoteInstanceId}`"
2706
+ ]
2707
+ });
2708
+ this._remoteConnection._remoteConnection = this;
2709
+ this._remoteConnection._remoteInstanceId = this._instanceId;
2710
+ (0, import_log10.log)("connected", void 0, {
2711
+ F: __dxlog_file11,
2712
+ L: 103,
2713
+ S: this,
2714
+ C: (f, a) => f(...a)
2715
+ });
2716
+ this.options.stream.pipe(this._outgoingDelay).pipe(this._remoteConnection.options.stream).pipe(this._incomingDelay).pipe(this.options.stream);
2717
+ this.connected.emit();
2718
+ this._remoteConnection.connected.emit();
2719
+ }).catch((err) => {
2720
+ if (this._destroyed) {
2721
+ return;
2722
+ }
2723
+ this.errors.raise(err);
2724
+ });
2725
+ }
2726
+ }
2727
+ async destroy() {
2728
+ (0, import_log10.log)("closing", void 0, {
2729
+ F: __dxlog_file11,
2730
+ L: 124,
2731
+ S: this,
2732
+ C: (f, a) => f(...a)
2733
+ });
2734
+ this._destroyed = true;
2735
+ _MemoryTransport._connections.delete(this._instanceId);
2736
+ if (this._remoteConnection) {
2737
+ (0, import_log10.log)("closing", void 0, {
2738
+ F: __dxlog_file11,
2739
+ L: 129,
2740
+ S: this,
2741
+ C: (f, a) => f(...a)
2742
+ });
2743
+ this._remoteConnection._destroyed = true;
2744
+ _MemoryTransport._connections.delete(this._remoteInstanceId);
2745
+ this.options.stream.unpipe(this._incomingDelay);
2746
+ this._incomingDelay.unpipe(this._remoteConnection.options.stream);
2747
+ this._remoteConnection.options.stream.unpipe(this._outgoingDelay);
2748
+ this._outgoingDelay.unpipe(this.options.stream);
2749
+ this.options.stream.unpipe(this._outgoingDelay);
2750
+ this._remoteConnection.closed.emit();
2751
+ this._remoteConnection._remoteConnection = void 0;
2752
+ this._remoteConnection = void 0;
2753
+ (0, import_log10.log)("closed", void 0, {
2754
+ F: __dxlog_file11,
2755
+ L: 150,
2756
+ S: this,
2757
+ C: (f, a) => f(...a)
2758
+ });
2759
+ }
2760
+ this.closed.emit();
2761
+ (0, import_log10.log)("closed", void 0, {
2762
+ F: __dxlog_file11,
2763
+ L: 154,
2764
+ S: this,
2765
+ C: (f, a) => f(...a)
2766
+ });
2767
+ }
2768
+ signal({ payload }) {
2769
+ (0, import_log10.log)("received signal", {
2770
+ payload
2771
+ }, {
2772
+ F: __dxlog_file11,
2773
+ L: 158,
2774
+ S: this,
2775
+ C: (f, a) => f(...a)
2776
+ });
2777
+ if (!payload?.transportId) {
2778
+ return;
2779
+ }
2780
+ const transportId = payload.transportId;
2781
+ if (transportId) {
2782
+ const remoteId = import_keys9.PublicKey.fromHex(transportId);
2783
+ this._remote.wake(remoteId);
2784
+ }
2785
+ }
2786
+ async getDetails() {
2787
+ return this._instanceId.toHex();
2788
+ }
2789
+ async getStats() {
2790
+ return {
2791
+ bytesSent: 0,
2792
+ bytesReceived: 0,
2793
+ packetsSent: 0,
2794
+ packetsReceived: 0
2795
+ };
2796
+ }
2797
+ };
2798
+ _ts_decorate4([
2799
+ import_log10.logInfo
2800
+ ], MemoryTransport.prototype, "_instanceId", void 0);
2801
+ _ts_decorate4([
2802
+ import_log10.logInfo
2803
+ ], MemoryTransport.prototype, "_remoteInstanceId", void 0);
2804
+ var TransportKind;
2805
+ (function(TransportKind2) {
2806
+ TransportKind2["SIMPLE_PEER"] = "SIMPLE_PEER";
2807
+ TransportKind2["LIBDATACHANNEL"] = "LIBDATACHANNEL";
2808
+ TransportKind2["SIMPLE_PEER_PROXY"] = "SIMPLE_PEER_PROXY";
2809
+ TransportKind2["MEMORY"] = "MEMORY";
2810
+ TransportKind2["TCP"] = "TCP";
2811
+ })(TransportKind || (TransportKind = {}));
2812
+ var wrtc = null;
2813
+ try {
2814
+ wrtc = (0, import_chunk_DMWORJG3.__require)("@koush/wrtc");
2815
+ } catch {
2816
+ }
2817
+ var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/simplepeer-transport.ts";
2818
+ var SimplePeerTransport = class {
2819
+ constructor(params) {
2820
+ this.params = params;
2821
+ this._closed = false;
2822
+ this._piped = false;
2823
+ this.closed = new import_async9.Event();
2824
+ this.connected = new import_async9.Event();
2825
+ this.errors = new import_debug5.ErrorStream();
2826
+ this._instanceId = import_keys10.PublicKey.random().toHex();
2827
+ import_log11.log.trace("dxos.mesh.webrtc-transport.constructor", import_protocols7.trace.begin({
2828
+ id: this._instanceId
2829
+ }), {
2830
+ F: __dxlog_file12,
2831
+ L: 41,
2832
+ S: this,
2833
+ C: (f, a) => f(...a)
2834
+ });
2835
+ (0, import_log11.log)("created connection", params, {
2836
+ F: __dxlog_file12,
2837
+ L: 42,
2838
+ S: this,
2839
+ C: (f, a) => f(...a)
2840
+ });
2841
+ this._peer = new import_simple_peer.default({
2842
+ channelName: "dxos.mesh.transport",
2843
+ initiator: this.params.initiator,
2844
+ wrtc: import_simple_peer.default.WEBRTC_SUPPORT ? void 0 : wrtc ?? (0, import_debug5.raise)(new Error("wrtc not available")),
2845
+ config: this.params.webrtcConfig
2846
+ });
2847
+ this._peer.on("signal", async (data) => {
2848
+ (0, import_log11.log)("signal", data, {
2849
+ F: __dxlog_file12,
2850
+ L: 51,
2851
+ S: this,
2852
+ C: (f, a) => f(...a)
2853
+ });
2854
+ await this.params.sendSignal({
2855
+ payload: {
2856
+ data
2857
+ }
2858
+ });
2859
+ });
2860
+ this._peer.on("connect", () => {
2861
+ (0, import_log11.log)("connected", void 0, {
2862
+ F: __dxlog_file12,
2863
+ L: 56,
2864
+ S: this,
2865
+ C: (f, a) => f(...a)
2866
+ });
2867
+ this.params.stream.pipe(this._peer).pipe(this.params.stream);
2868
+ this._piped = true;
2869
+ this.connected.emit();
2870
+ });
2871
+ this._peer.on("close", async () => {
2872
+ (0, import_log11.log)("closed", void 0, {
2873
+ F: __dxlog_file12,
2874
+ L: 63,
2875
+ S: this,
2876
+ C: (f, a) => f(...a)
2877
+ });
2878
+ await this.destroy();
2879
+ });
2880
+ this._peer.on("error", async (err) => {
2881
+ if (typeof RTCError !== "undefined" && err instanceof RTCError) {
2882
+ if (err.errorDetail === "sctp-failure") {
2883
+ this.errors.raise(new import_protocols7.ConnectionResetError("sctp-failure from RTCError", err));
2884
+ } else {
2885
+ import_log11.log.info("unknown RTCError", {
2886
+ err
2887
+ }, {
2888
+ F: __dxlog_file12,
2889
+ L: 74,
2890
+ S: this,
2891
+ C: (f, a) => f(...a)
2892
+ });
2893
+ this.errors.raise(new import_protocols7.UnknownProtocolError("unknown RTCError", err));
2894
+ }
2895
+ } else if ("code" in err) {
2896
+ import_log11.log.info("simple-peer error", err, {
2897
+ F: __dxlog_file12,
2898
+ L: 79,
2899
+ S: this,
2900
+ C: (f, a) => f(...a)
2901
+ });
2902
+ switch (err.code) {
2903
+ case "ERR_WEBRTC_SUPPORT":
2904
+ this.errors.raise(new import_protocols7.ProtocolError("WebRTC not supported", err));
2905
+ break;
2906
+ case "ERR_SIGNALING":
2907
+ this.errors.raise(new import_protocols7.ConnectivityError("signaling failure", err));
2908
+ break;
2909
+ case "ERR_ICE_CONNECTION_FAILURE":
2910
+ case "ERR_DATA_CHANNEL":
2911
+ case "ERR_CONNECTION_FAILURE":
2912
+ this.errors.raise(new import_protocols7.ConnectivityError("unknown communication failure", err));
2913
+ break;
2914
+ case "ERR_CREATE_OFFER":
2915
+ case "ERR_CREATE_ANSWER":
2916
+ case "ERR_SET_LOCAL_DESCRIPTION":
2917
+ case "ERR_SET_REMOTE_DESCRIPTION":
2918
+ case "ERR_ADD_ICE_CANDIDATE":
2919
+ this.errors.raise(new import_protocols7.UnknownProtocolError("unknown simple-peer library failure", err));
2920
+ break;
2921
+ default:
2922
+ this.errors.raise(new Error("unknown simple-peer error"));
2923
+ break;
2924
+ }
2925
+ } else {
2926
+ import_log11.log.info("unknown peer connection error", err, {
2927
+ F: __dxlog_file12,
2928
+ L: 105,
2929
+ S: this,
2930
+ C: (f, a) => f(...a)
2931
+ });
2932
+ this.errors.raise(err);
2933
+ }
2934
+ try {
2935
+ if (typeof this._peer?._pc?.getStats === "function") {
2936
+ this._peer._pc.getStats().then((stats) => {
2937
+ import_log11.log.info("report after webrtc error", {
2938
+ config: this.params.webrtcConfig,
2939
+ stats: Object.fromEntries(stats.entries())
2940
+ }, {
2941
+ F: __dxlog_file12,
2942
+ L: 113,
2943
+ S: this,
2944
+ C: (f, a) => f(...a)
2945
+ });
2946
+ });
2947
+ }
2948
+ } catch (err2) {
2949
+ import_log11.log.catch(err2, void 0, {
2950
+ F: __dxlog_file12,
2951
+ L: 120,
2952
+ S: this,
2953
+ C: (f, a) => f(...a)
2954
+ });
2955
+ }
2956
+ await this.destroy();
2957
+ });
2958
+ import_log11.log.trace("dxos.mesh.webrtc-transport.constructor", import_protocols7.trace.end({
2959
+ id: this._instanceId
2960
+ }), {
2961
+ F: __dxlog_file12,
2962
+ L: 126,
2963
+ S: this,
2964
+ C: (f, a) => f(...a)
2965
+ });
2966
+ }
2967
+ async getStats() {
2968
+ const stats = await this._getStats();
2969
+ if (!stats) {
2970
+ return {
2971
+ bytesSent: 0,
2972
+ bytesReceived: 0,
2973
+ packetsSent: 0,
2974
+ packetsReceived: 0,
2975
+ rawStats: {}
2976
+ };
2977
+ }
2978
+ return {
2979
+ bytesSent: stats.transport.bytesSent,
2980
+ bytesReceived: stats.transport.bytesReceived,
2981
+ packetsSent: stats.transport.messagesSent,
2982
+ packetsReceived: stats.transport.messagesReceived,
2983
+ rawStats: stats.raw
2984
+ };
2985
+ }
2986
+ async _getStats() {
2987
+ if (typeof this._peer?._pc?.getStats !== "function") {
2988
+ return null;
2989
+ }
2990
+ return await this._peer._pc.getStats().then((stats) => {
2991
+ const statsEntries = Array.from(stats.entries());
2992
+ const transport = statsEntries.filter((s) => s[1].type === "transport")[0][1];
2993
+ const candidatePair = statsEntries.filter((s) => s[0] === transport.selectedCandidatePairId);
2994
+ let selectedCandidatePair;
2995
+ let remoteCandidate;
2996
+ if (candidatePair.length > 0) {
2997
+ selectedCandidatePair = candidatePair[0][1];
2998
+ remoteCandidate = statsEntries.filter((s) => s[0] === selectedCandidatePair.remoteCandidateId)[0][1];
2999
+ }
3000
+ return {
3001
+ datachannel: statsEntries.filter((s) => s[1].type === "data-channel")[0][1],
3002
+ transport,
3003
+ selectedCandidatePair,
3004
+ remoteCandidate,
3005
+ raw: Object.fromEntries(stats.entries())
3006
+ };
3007
+ });
3008
+ }
3009
+ async getDetails() {
3010
+ const stats = await this._getStats();
3011
+ const rc = stats?.remoteCandidate;
3012
+ if (!rc) {
3013
+ return "unavailable";
3014
+ }
3015
+ if (rc.relay) {
3016
+ return `${rc.ip}:${rc.port}/${rc.protocol} relay for XXX ${rc.candidateType}`;
3017
+ }
3018
+ return `${rc.ip}:${rc.port}/${rc.protocol} ${rc.candidateType}`;
3019
+ }
3020
+ async destroy() {
3021
+ (0, import_log11.log)("closing...", void 0, {
3022
+ F: __dxlog_file12,
3023
+ L: 189,
3024
+ S: this,
3025
+ C: (f, a) => f(...a)
3026
+ });
3027
+ if (this._closed) {
3028
+ return;
3029
+ }
3030
+ this._closed = true;
3031
+ this._disconnectStreams();
3032
+ this._peer.destroy();
3033
+ this._closed = true;
3034
+ this.closed.emit();
3035
+ (0, import_log11.log)("closed", void 0, {
3036
+ F: __dxlog_file12,
3037
+ L: 198,
3038
+ S: this,
3039
+ C: (f, a) => f(...a)
3040
+ });
3041
+ }
3042
+ signal(signal) {
3043
+ if (this._closed) {
3044
+ return;
3045
+ }
3046
+ (0, import_tiny_invariant.default)(signal.payload.data, "Signal message must contain signal data.");
3047
+ this._peer.signal(signal.payload.data);
3048
+ }
3049
+ _disconnectStreams() {
3050
+ if (this._piped) {
3051
+ this.params.stream.unpipe?.(this._peer)?.unpipe?.(this.params.stream);
3052
+ }
3053
+ }
3054
+ };
3055
+ var createSimplePeerTransportFactory = (webrtcConfig) => ({
3056
+ createTransport: (params) => new SimplePeerTransport({
3057
+ ...params,
3058
+ webrtcConfig
3059
+ })
3060
+ });
3061
+ var __dxlog_file13 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/simplepeer-transport-service.ts";
3062
+ var SimplePeerTransportService = class {
3063
+ constructor(_webrtcConfig) {
3064
+ this._webrtcConfig = _webrtcConfig;
3065
+ this.transports = new import_util8.ComplexMap(import_keys11.PublicKey.hash);
3066
+ }
3067
+ open(request) {
3068
+ const rpcStream = new import_codec_protobuf.Stream(({ ready, next, close }) => {
3069
+ const duplex = new import_node_stream2.Duplex({
3070
+ read: () => {
3071
+ const callbacks = [
3072
+ ...transportState.writeCallbacks
3073
+ ];
3074
+ transportState.writeCallbacks.length = 0;
3075
+ for (const cb of callbacks) {
3076
+ cb();
3077
+ }
3078
+ },
3079
+ write: function(chunk, _, callback) {
3080
+ next({
3081
+ data: {
3082
+ payload: chunk
3083
+ }
3084
+ });
3085
+ callback();
3086
+ }
3087
+ });
3088
+ const transport = new SimplePeerTransport({
3089
+ initiator: request.initiator,
3090
+ stream: duplex,
3091
+ webrtcConfig: this._webrtcConfig,
3092
+ sendSignal: async (signal) => {
3093
+ next({
3094
+ signal: {
3095
+ payload: signal
3096
+ }
3097
+ });
3098
+ }
3099
+ });
3100
+ next({
3101
+ connection: {
3102
+ state: import_bridge.ConnectionState.CONNECTING
3103
+ }
3104
+ });
3105
+ transport.connected.on(() => {
3106
+ next({
3107
+ connection: {
3108
+ state: import_bridge.ConnectionState.CONNECTED
3109
+ }
3110
+ });
3111
+ });
3112
+ transport.errors.handle((err) => {
3113
+ next({
3114
+ connection: {
3115
+ state: import_bridge.ConnectionState.CLOSED,
3116
+ error: err.toString()
3117
+ }
3118
+ });
3119
+ close(err);
3120
+ });
3121
+ transport.closed.on(() => {
3122
+ next({
3123
+ connection: {
3124
+ state: import_bridge.ConnectionState.CLOSED
3125
+ }
3126
+ });
3127
+ close();
3128
+ });
3129
+ const transportState = {
3130
+ transport,
3131
+ stream: duplex,
3132
+ writeCallbacks: [],
3133
+ state: "OPEN"
3134
+ };
3135
+ ready();
3136
+ this.transports.set(request.proxyId, transportState);
3137
+ });
3138
+ return rpcStream;
3139
+ }
3140
+ async sendSignal({ proxyId, signal }) {
3141
+ (0, import_invariant11.invariant)(this.transports.has(proxyId), void 0, {
3142
+ F: __dxlog_file13,
3143
+ L: 116,
3144
+ S: this,
3145
+ A: [
3146
+ "this.transports.has(proxyId)",
3147
+ ""
3148
+ ]
3149
+ });
3150
+ await this.transports.get(proxyId).transport.signal(signal);
3151
+ }
3152
+ async getDetails({ proxyId }) {
3153
+ (0, import_invariant11.invariant)(this.transports.has(proxyId), void 0, {
3154
+ F: __dxlog_file13,
3155
+ L: 121,
3156
+ S: this,
3157
+ A: [
3158
+ "this.transports.has(proxyId)",
3159
+ ""
3160
+ ]
3161
+ });
3162
+ return {
3163
+ details: await this.transports.get(proxyId).transport.getDetails()
3164
+ };
3165
+ }
3166
+ async getStats({ proxyId }) {
3167
+ (0, import_invariant11.invariant)(this.transports.has(proxyId), void 0, {
3168
+ F: __dxlog_file13,
3169
+ L: 126,
3170
+ S: this,
3171
+ A: [
3172
+ "this.transports.has(proxyId)",
3173
+ ""
3174
+ ]
3175
+ });
3176
+ return {
3177
+ stats: await this.transports.get(proxyId).transport.getStats()
3178
+ };
3179
+ }
3180
+ async sendData({ proxyId, payload }) {
3181
+ if (this.transports.get(proxyId)?.state !== "OPEN") {
3182
+ import_log12.log.debug("transport is closed", void 0, {
3183
+ F: __dxlog_file13,
3184
+ L: 132,
3185
+ S: this,
3186
+ C: (f, a) => f(...a)
3187
+ });
3188
+ }
3189
+ (0, import_invariant11.invariant)(this.transports.has(proxyId), void 0, {
3190
+ F: __dxlog_file13,
3191
+ L: 134,
3192
+ S: this,
3193
+ A: [
3194
+ "this.transports.has(proxyId)",
3195
+ ""
3196
+ ]
3197
+ });
3198
+ const state = this.transports.get(proxyId);
3199
+ const bufferHasSpace = state.stream.push(payload);
3200
+ if (!bufferHasSpace) {
3201
+ await new Promise((resolve) => {
3202
+ state.writeCallbacks.push(resolve);
3203
+ });
3204
+ }
3205
+ }
3206
+ async close({ proxyId }) {
3207
+ await this.transports.get(proxyId)?.transport.destroy();
3208
+ await this.transports.get(proxyId)?.stream.end();
3209
+ if (this.transports.get(proxyId)) {
3210
+ this.transports.get(proxyId).state = "CLOSED";
3211
+ }
3212
+ (0, import_log12.log)("Closed.", void 0, {
3213
+ F: __dxlog_file13,
3214
+ L: 150,
3215
+ S: this,
3216
+ C: (f, a) => f(...a)
3217
+ });
3218
+ }
3219
+ };
3220
+ var __dxlog_file14 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/simplepeer-transport-proxy.ts";
3221
+ var RESP_MIN_THRESHOLD = 500;
3222
+ var TIMEOUT_THRESHOLD = 10;
3223
+ var SimplePeerTransportProxy = class {
3224
+ constructor(_params) {
3225
+ this._params = _params;
3226
+ this._proxyId = import_keys12.PublicKey.random();
3227
+ this._ctx = new import_context6.Context();
3228
+ this._timeoutCount = 0;
3229
+ this.closed = new import_async10.Event();
3230
+ this.connected = new import_async10.Event();
3231
+ this.errors = new import_debug6.ErrorStream();
3232
+ this._closed = false;
3233
+ this._serviceStream = this._params.bridgeService.open({
3234
+ proxyId: this._proxyId,
3235
+ initiator: this._params.initiator
3236
+ });
3237
+ this._serviceStream.waitUntilReady().then(() => {
3238
+ this._serviceStream.subscribe(async (event) => {
3239
+ (0, import_log13.log)("SimplePeerTransportProxy: event", event, {
3240
+ F: __dxlog_file14,
3241
+ L: 59,
3242
+ S: this,
3243
+ C: (f, a) => f(...a)
3244
+ });
3245
+ if (event.connection) {
3246
+ await this._handleConnection(event.connection);
3247
+ } else if (event.data) {
3248
+ this._handleData(event.data);
3249
+ } else if (event.signal) {
3250
+ await this._handleSignal(event.signal);
3251
+ }
3252
+ });
3253
+ const proxyStream = new import_node_stream3.Writable({
3254
+ write: (chunk, _, callback) => {
3255
+ const then = performance.now();
3256
+ this._params.bridgeService.sendData({
3257
+ proxyId: this._proxyId,
3258
+ payload: chunk
3259
+ }).then(() => {
3260
+ if (performance.now() - then > RESP_MIN_THRESHOLD) {
3261
+ (0, import_log13.log)("slow response, delaying callback", void 0, {
3262
+ F: __dxlog_file14,
3263
+ L: 80,
3264
+ S: this,
3265
+ C: (f, a) => f(...a)
3266
+ });
3267
+ (0, import_async10.scheduleTask)(this._ctx, () => callback(), RESP_MIN_THRESHOLD);
3268
+ } else {
3269
+ callback();
3270
+ }
3271
+ this._timeoutCount = 0;
3272
+ }, (err) => {
3273
+ if (err instanceof import_protocols8.TimeoutError || err.constructor.name === "TimeoutError") {
3274
+ if (this._timeoutCount++ > TIMEOUT_THRESHOLD) {
3275
+ throw new import_protocols8.TimeoutError(`too many timeoutes (${this._timeoutCount} > ${TIMEOUT_THRESHOLD}`);
3276
+ } else {
3277
+ (0, import_log13.log)("timeout error, but still invoking callback", void 0, {
3278
+ F: __dxlog_file14,
3279
+ L: 92,
3280
+ S: this,
3281
+ C: (f, a) => f(...a)
3282
+ });
3283
+ callback();
3284
+ }
3285
+ } else {
3286
+ import_log13.log.catch(err, void 0, {
3287
+ F: __dxlog_file14,
3288
+ L: 96,
3289
+ S: this,
3290
+ C: (f, a) => f(...a)
3291
+ });
3292
+ }
3293
+ });
3294
+ }
3295
+ });
3296
+ proxyStream.on("error", (err) => {
3297
+ (0, import_log13.log)("proxystream error", {
3298
+ err
3299
+ }, {
3300
+ F: __dxlog_file14,
3301
+ L: 104,
3302
+ S: this,
3303
+ C: (f, a) => f(...a)
3304
+ });
3305
+ });
3306
+ this._params.stream.pipe(proxyStream);
3307
+ }, (error) => import_log13.log.catch(error, void 0, {
3308
+ F: __dxlog_file14,
3309
+ L: 109,
3310
+ S: this,
3311
+ C: (f, a) => f(...a)
3312
+ }));
3313
+ }
3314
+ async _handleConnection(connectionEvent) {
3315
+ if (connectionEvent.error) {
3316
+ this.errors.raise(decodeError(connectionEvent.error));
3317
+ }
3318
+ switch (connectionEvent.state) {
3319
+ case import_bridge2.ConnectionState.CONNECTED: {
3320
+ this.connected.emit();
3321
+ break;
3322
+ }
3323
+ case import_bridge2.ConnectionState.CLOSED: {
3324
+ await this.destroy();
3325
+ break;
3326
+ }
3327
+ }
3328
+ }
3329
+ _handleData(dataEvent) {
3330
+ this._params.stream.write((0, import_util9.arrayToBuffer)(dataEvent.payload));
3331
+ }
3332
+ async _handleSignal(signalEvent) {
3333
+ await this._params.sendSignal(signalEvent.payload);
3334
+ }
3335
+ signal(signal) {
3336
+ this._params.bridgeService.sendSignal({
3337
+ proxyId: this._proxyId,
3338
+ signal
3339
+ }).catch((err) => this.errors.raise(decodeError(err)));
3340
+ }
3341
+ async getDetails() {
3342
+ return (await this._params.bridgeService.getDetails({
3343
+ proxyId: this._proxyId
3344
+ })).details;
3345
+ }
3346
+ async getStats() {
3347
+ return (await this._params.bridgeService.getStats({
3348
+ proxyId: this._proxyId
3349
+ })).stats;
3350
+ }
3351
+ // TODO(burdon): Move open from constructor.
3352
+ async destroy() {
3353
+ await this._ctx.dispose();
3354
+ if (this._closed) {
3355
+ return;
3356
+ }
3357
+ await this._serviceStream.close();
3358
+ try {
3359
+ await this._params.bridgeService.close({
3360
+ proxyId: this._proxyId
3361
+ });
3362
+ } catch (err) {
3363
+ import_log13.log.catch(err, void 0, {
3364
+ F: __dxlog_file14,
3365
+ L: 168,
3366
+ S: this,
3367
+ C: (f, a) => f(...a)
3368
+ });
3369
+ }
3370
+ this.closed.emit();
3371
+ this._closed = true;
3372
+ }
3373
+ /**
3374
+ * Called when underlying proxy service becomes unavailable.
3375
+ */
3376
+ // TODO(burdon): Option on close method.
3377
+ forceClose() {
3378
+ void this._serviceStream.close();
3379
+ this.closed.emit();
3380
+ this._closed = true;
3381
+ }
3382
+ };
3383
+ var SimplePeerTransportProxyFactory = class {
3384
+ constructor() {
3385
+ this._connections = /* @__PURE__ */ new Set();
3386
+ }
3387
+ /**
3388
+ * Sets the current BridgeService to be used to open connections.
3389
+ * Calling this method will close any existing connections.
3390
+ */
3391
+ setBridgeService(bridgeService) {
3392
+ this._bridgeService = bridgeService;
3393
+ for (const connection of this._connections) {
3394
+ connection.forceClose();
3395
+ }
3396
+ return this;
3397
+ }
3398
+ createTransport(options) {
3399
+ (0, import_invariant12.invariant)(this._bridgeService, "SimplePeerTransportProxyFactory is not ready to open connections", {
3400
+ F: __dxlog_file14,
3401
+ L: 205,
3402
+ S: this,
3403
+ A: [
3404
+ "this._bridgeService",
3405
+ "'SimplePeerTransportProxyFactory is not ready to open connections'"
3406
+ ]
3407
+ });
3408
+ const transport = new SimplePeerTransportProxy({
3409
+ ...options,
3410
+ bridgeService: this._bridgeService
3411
+ });
3412
+ this._connections.add(transport);
3413
+ transport.closed.on(() => this._connections.delete(transport));
3414
+ return transport;
3415
+ }
3416
+ };
3417
+ var decodeError = (err) => {
3418
+ const message = typeof err === "string" ? err : err.message;
3419
+ if (message.includes("CONNECTION_RESET")) {
3420
+ return new import_protocols8.ConnectionResetError(message);
3421
+ } else if (message.includes("TIMEOUT")) {
3422
+ return new import_protocols8.TimeoutError(message);
3423
+ } else if (message.includes("PROTOCOL_ERROR")) {
3424
+ return new import_protocols8.ProtocolError(message);
3425
+ } else if (message.includes("CONNECTIVITY_ERROR")) {
3426
+ return new import_protocols8.ConnectivityError(message);
3427
+ } else if (message.includes("UNKNOWN_PROTOCOL_ERROR")) {
3428
+ return new import_protocols8.UnknownProtocolError(message);
3429
+ } else {
3430
+ return typeof err === "string" ? new Error(err) : err;
3431
+ }
3432
+ };
3433
+ function _ts_decorate5(decorators, target, key, desc) {
3434
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3435
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3436
+ r = Reflect.decorate(decorators, target, key, desc);
3437
+ else
3438
+ for (var i = decorators.length - 1; i >= 0; i--)
3439
+ if (d = decorators[i])
3440
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3441
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
3442
+ }
3443
+ var __dxlog_file15 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/libdatachannel-transport.ts";
3444
+ var DATACHANNEL_LABEL = "dxos.mesh.transport";
3445
+ var MAX_BUFFERED_AMOUNT = 64 * 1024;
3446
+ var MAX_MESSAGE_SIZE = 64 * 1024;
3447
+ var LibDataChannelTransport = class {
3448
+ constructor(params) {
3449
+ this.params = params;
3450
+ this._closed = false;
3451
+ this.closed = new import_async11.Event();
3452
+ this._connected = false;
3453
+ this.connected = new import_async11.Event();
3454
+ this.errors = new import_debug7.ErrorStream();
3455
+ this._readyForCandidates = new import_async11.Trigger();
3456
+ this._writeCallback = null;
3457
+ this._peer = (async () => {
3458
+ const { RTCPeerConnection: PeerConnection } = await import("./datachannel-ABYQKZRC.cjs");
3459
+ if (this._closed) {
3460
+ this.errors.raise(new Error("connection already closed"));
3461
+ }
3462
+ const peer = new PeerConnection(params.webrtcConfig);
3463
+ peer.onicecandidateerror = (event) => {
3464
+ import_log14.log.error("peer.onicecandidateerror", {
3465
+ event
3466
+ }, {
3467
+ F: __dxlog_file15,
3468
+ L: 53,
3469
+ S: this,
3470
+ C: (f, a) => f(...a)
3471
+ });
3472
+ };
3473
+ peer.onconnectionstatechange = (event) => {
3474
+ import_log14.log.debug("peer.onconnectionstatechange", {
3475
+ event,
3476
+ peerConnectionState: peer.connectionState,
3477
+ transportConnectionState: this._connected
3478
+ }, {
3479
+ F: __dxlog_file15,
3480
+ L: 57,
3481
+ S: this,
3482
+ C: (f, a) => f(...a)
3483
+ });
3484
+ };
3485
+ peer.onicecandidate = async (event) => {
3486
+ import_log14.log.debug("peer.onicecandidate", {
3487
+ event
3488
+ }, {
3489
+ F: __dxlog_file15,
3490
+ L: 66,
3491
+ S: this,
3492
+ C: (f, a) => f(...a)
3493
+ });
3494
+ if (event.candidate) {
3495
+ try {
3496
+ await params.sendSignal({
3497
+ payload: {
3498
+ data: {
3499
+ type: "candidate",
3500
+ candidate: {
3501
+ candidate: event.candidate.candidate,
3502
+ // these fields never seem to be not null, but connecting to Chrome doesn't work if they are
3503
+ sdpMLineIndex: event.candidate.sdpMLineIndex ?? 0,
3504
+ sdpMid: event.candidate.sdpMid ?? 0
3505
+ }
3506
+ }
3507
+ }
3508
+ });
3509
+ } catch (err) {
3510
+ import_log14.log.info("signaling errror", {
3511
+ err
3512
+ }, {
3513
+ F: __dxlog_file15,
3514
+ L: 83,
3515
+ S: this,
3516
+ C: (f, a) => f(...a)
3517
+ });
3518
+ }
3519
+ }
3520
+ };
3521
+ if (params.initiator) {
3522
+ peer.createOffer().then(async (offer) => {
3523
+ if (peer.connectionState !== "connecting") {
3524
+ import_log14.log.error("i am initiator but peer not in state connecting", {
3525
+ peer
3526
+ }, {
3527
+ F: __dxlog_file15,
3528
+ L: 92,
3529
+ S: this,
3530
+ C: (f, a) => f(...a)
3531
+ });
3532
+ this.errors.raise(new Error("invalid state: peer is initiator, but other peer not in state connecting"));
3533
+ }
3534
+ import_log14.log.debug(`im the initiator, creating offer, peer is in state ${peer.connectionState}`, {
3535
+ offer
3536
+ }, {
3537
+ F: __dxlog_file15,
3538
+ L: 95,
3539
+ S: this,
3540
+ C: (f, a) => f(...a)
3541
+ });
3542
+ await peer.setLocalDescription(offer);
3543
+ await params.sendSignal({
3544
+ payload: {
3545
+ data: {
3546
+ type: offer.type,
3547
+ sdp: offer.sdp
3548
+ }
3549
+ }
3550
+ });
3551
+ return offer;
3552
+ }).catch((err) => {
3553
+ this.errors.raise(err);
3554
+ });
3555
+ this.handleChannel(peer.createDataChannel(DATACHANNEL_LABEL));
3556
+ import_log14.log.debug("created data channel", void 0, {
3557
+ F: __dxlog_file15,
3558
+ L: 104,
3559
+ S: this,
3560
+ C: (f, a) => f(...a)
3561
+ });
3562
+ peer.ondatachannel = (event) => {
3563
+ this.errors.raise(new Error("got ondatachannel when i am the initiator?"));
3564
+ };
3565
+ } else {
3566
+ peer.ondatachannel = (event) => {
3567
+ import_log14.log.debug("peer.ondatachannel (non-initiator)", {
3568
+ event
3569
+ }, {
3570
+ F: __dxlog_file15,
3571
+ L: 110,
3572
+ S: this,
3573
+ C: (f, a) => f(...a)
3574
+ });
3575
+ if (event.channel.label !== DATACHANNEL_LABEL) {
3576
+ this.errors.raise(new Error(`unexpected channel label ${event.channel.label}`));
3577
+ }
3578
+ this.handleChannel(event.channel);
3579
+ };
3580
+ }
3581
+ return peer;
3582
+ })();
3583
+ }
3584
+ handleChannel(dataChannel) {
3585
+ this._channel = dataChannel;
3586
+ this._channel.onopen = () => {
3587
+ import_log14.log.debug("dataChannel.onopen", void 0, {
3588
+ F: __dxlog_file15,
3589
+ L: 126,
3590
+ S: this,
3591
+ C: (f, a) => f(...a)
3592
+ });
3593
+ const duplex = new import_stream.Duplex({
3594
+ read: () => {
3595
+ },
3596
+ write: async (chunk, encoding, callback) => {
3597
+ if (chunk.length > MAX_MESSAGE_SIZE) {
3598
+ this.errors.raise(new Error(`message too large: ${chunk.length} > ${MAX_MESSAGE_SIZE}`));
3599
+ }
3600
+ try {
3601
+ dataChannel.send(chunk);
3602
+ } catch (err) {
3603
+ this.errors.raise(err);
3604
+ await this._close();
3605
+ }
3606
+ if (this._channel.bufferedAmount > MAX_BUFFERED_AMOUNT) {
3607
+ if (this._writeCallback !== null) {
3608
+ import_log14.log.error("consumer trying to write before we're ready for more data", void 0, {
3609
+ F: __dxlog_file15,
3610
+ L: 143,
3611
+ S: this,
3612
+ C: (f, a) => f(...a)
3613
+ });
3614
+ }
3615
+ this._writeCallback = callback;
3616
+ } else {
3617
+ callback();
3618
+ }
3619
+ }
3620
+ });
3621
+ duplex.pipe(this.params.stream).pipe(duplex);
3622
+ this._stream = duplex;
3623
+ this._connected = true;
3624
+ this.connected.emit();
3625
+ };
3626
+ this._channel.onerror = async (err) => {
3627
+ this.errors.raise(new Error("channel error: " + err.toString()));
3628
+ await this._close();
3629
+ };
3630
+ this._channel.onclose = async (err) => {
3631
+ import_log14.log.info("channel onclose", {
3632
+ err
3633
+ }, {
3634
+ F: __dxlog_file15,
3635
+ L: 163,
3636
+ S: this,
3637
+ C: (f, a) => f(...a)
3638
+ });
3639
+ await this._close();
3640
+ };
3641
+ this._channel.onmessage = (event) => {
3642
+ let data = event.data;
3643
+ if (data instanceof ArrayBuffer) {
3644
+ data = Buffer.from(data);
3645
+ }
3646
+ this._stream.push(data);
3647
+ };
3648
+ this._channel.onbufferedamountlow = () => {
3649
+ const cb = this._writeCallback;
3650
+ this._writeCallback = null;
3651
+ cb?.();
3652
+ };
3653
+ }
3654
+ async _close() {
3655
+ if (this._closed) {
3656
+ return;
3657
+ }
3658
+ await this._disconnectStreams();
3659
+ this._closed = true;
3660
+ this.closed.emit();
3661
+ }
3662
+ signal(signal) {
3663
+ this._peer.then(async (peer) => {
3664
+ const data = signal.payload.data;
3665
+ switch (data.type) {
3666
+ case "offer": {
3667
+ if ((await this._peer).connectionState !== "new") {
3668
+ import_log14.log.error("received offer but peer not in state new", {
3669
+ peer
3670
+ }, {
3671
+ F: __dxlog_file15,
3672
+ L: 198,
3673
+ S: this,
3674
+ C: (f, a) => f(...a)
3675
+ });
3676
+ this.errors.raise(new Error("invalid signalling state: received offer when peer is not in state new"));
3677
+ break;
3678
+ }
3679
+ try {
3680
+ await peer.setRemoteDescription({
3681
+ type: data.type,
3682
+ sdp: data.sdp
3683
+ });
3684
+ const answer = await peer.createAnswer();
3685
+ await peer.setLocalDescription(answer);
3686
+ await this.params.sendSignal({
3687
+ payload: {
3688
+ data: {
3689
+ type: answer.type,
3690
+ sdp: answer.sdp
3691
+ }
3692
+ }
3693
+ });
3694
+ this._readyForCandidates.wake();
3695
+ } catch (err) {
3696
+ import_log14.log.error("can't handle offer from signalling server", {
3697
+ err
3698
+ }, {
3699
+ F: __dxlog_file15,
3700
+ L: 209,
3701
+ S: this,
3702
+ C: (f, a) => f(...a)
3703
+ });
3704
+ this.errors.raise(new Error("error handling offer"));
3705
+ }
3706
+ break;
3707
+ }
3708
+ case "answer":
3709
+ try {
3710
+ await peer.setRemoteDescription({
3711
+ type: data.type,
3712
+ sdp: data.sdp
3713
+ });
3714
+ this._readyForCandidates.wake();
3715
+ } catch (err) {
3716
+ import_log14.log.error("can't handle answer from signalling server", {
3717
+ err
3718
+ }, {
3719
+ F: __dxlog_file15,
3720
+ L: 220,
3721
+ S: this,
3722
+ C: (f, a) => f(...a)
3723
+ });
3724
+ this.errors.raise(new Error("error handling answer"));
3725
+ }
3726
+ break;
3727
+ case "candidate":
3728
+ await this._readyForCandidates.wait();
3729
+ await peer.addIceCandidate({
3730
+ candidate: data.candidate.candidate
3731
+ });
3732
+ break;
3733
+ default:
3734
+ import_log14.log.error("unhandled signal type", {
3735
+ type: data.type,
3736
+ signal
3737
+ }, {
3738
+ F: __dxlog_file15,
3739
+ L: 231,
3740
+ S: this,
3741
+ C: (f, a) => f(...a)
3742
+ });
3743
+ this.errors.raise(new Error(`unhandled signal type ${data.type}`));
3744
+ }
3745
+ }).catch((err) => {
3746
+ import_log14.log.catch(err, void 0, {
3747
+ F: __dxlog_file15,
3748
+ L: 236,
3749
+ S: this,
3750
+ C: (f, a) => f(...a)
3751
+ });
3752
+ });
3753
+ }
3754
+ async getDetails() {
3755
+ return this._peer.then(async (peer) => {
3756
+ const cp = await peer.getSelectedCandidatePair();
3757
+ if (!cp) {
3758
+ return "unavailable";
3759
+ }
3760
+ return `${cp.remote.address}:${cp.remote.port}/${cp.remote.transportType} ${cp.remote.type}`;
3761
+ }).catch((err) => {
3762
+ import_log14.log.catch(err, void 0, {
3763
+ F: __dxlog_file15,
3764
+ L: 250,
3765
+ S: this,
3766
+ C: (f, a) => f(...a)
3767
+ });
3768
+ return "unavailable";
3769
+ });
3770
+ }
3771
+ async getStats() {
3772
+ return this._peer.then((peer) => {
3773
+ return {
3774
+ bytesSent: peer.bytesSent(),
3775
+ bytesReceived: peer.bytesReceived(),
3776
+ packetsSent: 0,
3777
+ packetsReceived: 0
3778
+ };
3779
+ }).catch((err) => {
3780
+ import_log14.log.catch(err, void 0, {
3781
+ F: __dxlog_file15,
3782
+ L: 266,
3783
+ S: this,
3784
+ C: (f, a) => f(...a)
3785
+ });
3786
+ return {
3787
+ bytesSent: 0,
3788
+ bytesReceived: 0,
3789
+ packetsSent: 0,
3790
+ packetsReceived: 0
3791
+ };
3792
+ });
3793
+ }
3794
+ // TODO(nf): add classmethod to call node-datachannel.cleanup() when all instances have been destroyed?
3795
+ async destroy() {
3796
+ await this._close();
3797
+ }
3798
+ async _disconnectStreams() {
3799
+ this.params.stream.unpipe?.(this._stream)?.unpipe?.(this.params.stream);
3800
+ }
3801
+ };
3802
+ _ts_decorate5([
3803
+ import_async11.synchronized
3804
+ ], LibDataChannelTransport.prototype, "_close", null);
3805
+ var createLibDataChannelTransportFactory = (webrtcConfig) => ({
3806
+ createTransport: (params) => new LibDataChannelTransport({
3807
+ ...params,
3808
+ webrtcConfig
3809
+ })
3810
+ });
3811
+ var __dxlog_file16 = "/home/runner/work/dxos/dxos/packages/core/mesh/network-manager/src/transport/tcp-transport.ts";
3812
+ var TcpTransportFactory = {
3813
+ createTransport: (params) => new TcpTransport(params)
3814
+ };
3815
+ var TcpTransport = class {
3816
+ constructor(options) {
3817
+ this.options = options;
3818
+ this._server = void 0;
3819
+ this._socket = void 0;
3820
+ this.closed = new import_async12.Event();
3821
+ this.connected = new import_async12.Event();
3822
+ this.errors = new import_debug8.ErrorStream();
3823
+ this._destroyed = false;
3824
+ this._connected = false;
3825
+ (0, import_log15.log)("creating", void 0, {
3826
+ F: __dxlog_file16,
3827
+ L: 34,
3828
+ S: this,
3829
+ C: (f, a) => f(...a)
3830
+ });
3831
+ if (this.options.initiator) {
3832
+ setTimeout(async () => {
3833
+ const { Server } = await import("node:net");
3834
+ this._server = new Server((socket) => {
3835
+ (0, import_log15.log)("new connection", void 0, {
3836
+ F: __dxlog_file16,
3837
+ L: 42,
3838
+ S: this,
3839
+ C: (f, a) => f(...a)
3840
+ });
3841
+ if (this._connected) {
3842
+ socket.destroy();
3843
+ }
3844
+ this._handleSocket(socket);
3845
+ });
3846
+ this._server.on("listening", () => {
3847
+ const { port } = this._server.address();
3848
+ (0, import_log15.log)("listening", {
3849
+ port
3850
+ }, {
3851
+ F: __dxlog_file16,
3852
+ L: 51,
3853
+ S: this,
3854
+ C: (f, a) => f(...a)
3855
+ });
3856
+ void this.options.sendSignal({
3857
+ payload: {
3858
+ port
3859
+ }
3860
+ }).catch((err) => {
3861
+ if (!this._destroyed) {
3862
+ this.errors.raise(err);
3863
+ }
3864
+ });
3865
+ });
3866
+ this._server.on("error", (err) => {
3867
+ this.errors.raise(err);
3868
+ });
3869
+ this._server.listen(0);
3870
+ });
3871
+ }
3872
+ }
3873
+ async destroy() {
3874
+ (0, import_log15.log)("closing", void 0, {
3875
+ F: __dxlog_file16,
3876
+ L: 72,
3877
+ S: this,
3878
+ C: (f, a) => f(...a)
3879
+ });
3880
+ this._socket?.destroy();
3881
+ this._server?.close();
3882
+ this._destroyed = true;
3883
+ }
3884
+ signal({ payload }) {
3885
+ (0, import_log15.log)("received signal", {
3886
+ payload
3887
+ }, {
3888
+ F: __dxlog_file16,
3889
+ L: 80,
3890
+ S: this,
3891
+ C: (f, a) => f(...a)
3892
+ });
3893
+ if (this.options.initiator || this._connected) {
3894
+ return;
3895
+ }
3896
+ const socket = new import_node_net.Socket();
3897
+ this._handleSocket(socket);
3898
+ socket.connect({
3899
+ port: payload.port,
3900
+ host: "localhost"
3901
+ });
3902
+ }
3903
+ async getDetails() {
3904
+ if (this.options.initiator) {
3905
+ const { port: port2, address: address2 } = this._server?.address();
3906
+ return `LISTEN ${address2}:${port2}`;
3907
+ }
3908
+ const { port, address } = this._socket?.address();
3909
+ return `ACCEPT ${address}:${port}`;
3910
+ }
3911
+ async getStats() {
3912
+ return {
3913
+ bytesSent: 0,
3914
+ bytesReceived: 0,
3915
+ packetsSent: 0,
3916
+ packetsReceived: 0
3917
+ };
3918
+ }
3919
+ _handleSocket(socket) {
3920
+ (0, import_log15.log)("handling socket", {
3921
+ remotePort: socket.remotePort,
3922
+ localPort: socket.localPort
3923
+ }, {
3924
+ F: __dxlog_file16,
3925
+ L: 109,
3926
+ S: this,
3927
+ C: (f, a) => f(...a)
3928
+ });
3929
+ this._socket = socket;
3930
+ this.connected.emit();
3931
+ this.options.stream.pipe(this._socket).pipe(this.options.stream);
3932
+ this._socket.on("connect", () => {
3933
+ (0, import_log15.log)("connected to", {
3934
+ port: this._socket?.remotePort
3935
+ }, {
3936
+ F: __dxlog_file16,
3937
+ L: 115,
3938
+ S: this,
3939
+ C: (f, a) => f(...a)
3940
+ });
3941
+ this._connected = true;
3942
+ });
3943
+ this._socket.on("error", (err) => {
3944
+ this.errors.raise(err);
3945
+ });
3946
+ this._socket.on("close", () => {
3947
+ this.closed.emit();
3948
+ });
3949
+ }
3950
+ };
3951
+ var createTeleportProtocolFactory = (onConnection) => {
3952
+ return (params) => {
3953
+ const teleport = new import_teleport.Teleport(params);
3954
+ return {
3955
+ stream: teleport.stream,
3956
+ open: async (sessionId) => {
3957
+ await teleport.open(sessionId);
3958
+ await onConnection(teleport);
3959
+ },
3960
+ close: async () => {
3961
+ await teleport.close();
3962
+ },
3963
+ abort: async () => {
3964
+ await teleport.abort();
3965
+ }
3966
+ };
3967
+ };
3968
+ };
3969
+ // Annotate the CommonJS export names for ESM import in node:
3970
+ 0 && (module.exports = {
3971
+ Connection,
3972
+ ConnectionLimiter,
3973
+ ConnectionLog,
3974
+ ConnectionState,
3975
+ EventType,
3976
+ FullyConnectedTopology,
3977
+ LibDataChannelTransport,
3978
+ MAX_CONCURRENT_INITIATING_CONNECTIONS,
3979
+ MMSTTopology,
3980
+ MemoryTransport,
3981
+ MemoryTransportFactory,
3982
+ NetworkManager,
3983
+ SimplePeerTransport,
3984
+ SimplePeerTransportProxy,
3985
+ SimplePeerTransportProxyFactory,
3986
+ SimplePeerTransportService,
3987
+ StarTopology,
3988
+ Swarm,
3989
+ SwarmMapper,
3990
+ SwarmMessenger,
3991
+ TcpTransport,
3992
+ TcpTransportFactory,
3993
+ TransportKind,
3994
+ createLibDataChannelTransportFactory,
3995
+ createSimplePeerTransportFactory,
3996
+ createTeleportProtocolFactory
3997
+ });
3998
+ //# sourceMappingURL=chunk-3SCPMSHV.cjs.map