@dxos/network-manager 0.8.4-main.dedc0f3 → 0.8.4-main.e00bdcdb52

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 (99) hide show
  1. package/dist/lib/browser/{chunk-VAQETEB2.mjs → chunk-LRGOUKHO.mjs} +697 -2383
  2. package/dist/lib/browser/chunk-LRGOUKHO.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +198 -4
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +88 -140
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/browser/transport/tcp/index.mjs +2 -48
  9. package/dist/lib/browser/transport/tcp/index.mjs.map +4 -4
  10. package/dist/lib/browser/transport/tcp/tcp-transport.browser.mjs +36 -0
  11. package/dist/lib/browser/transport/tcp/tcp-transport.browser.mjs.map +7 -0
  12. package/dist/lib/browser/transport/tcp/tcp-transport.mjs +125 -0
  13. package/dist/lib/browser/transport/tcp/tcp-transport.mjs.map +7 -0
  14. package/dist/lib/node-esm/{chunk-RAHYLU4N.mjs → chunk-E6G6B72R.mjs} +697 -2383
  15. package/dist/lib/node-esm/chunk-E6G6B72R.mjs.map +7 -0
  16. package/dist/lib/node-esm/index.mjs +198 -4
  17. package/dist/lib/node-esm/index.mjs.map +4 -4
  18. package/dist/lib/node-esm/meta.json +1 -1
  19. package/dist/lib/node-esm/testing/index.mjs +88 -140
  20. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  21. package/dist/lib/node-esm/transport/tcp/index.mjs +2 -177
  22. package/dist/lib/node-esm/transport/tcp/index.mjs.map +4 -4
  23. package/dist/lib/node-esm/transport/tcp/tcp-transport.browser.mjs +36 -0
  24. package/dist/lib/node-esm/transport/tcp/tcp-transport.browser.mjs.map +7 -0
  25. package/dist/lib/node-esm/transport/tcp/tcp-transport.mjs +125 -0
  26. package/dist/lib/node-esm/transport/tcp/tcp-transport.mjs.map +7 -0
  27. package/dist/types/src/connection-log.d.ts.map +1 -1
  28. package/dist/types/src/network-manager.d.ts +6 -6
  29. package/dist/types/src/network-manager.d.ts.map +1 -1
  30. package/dist/types/src/signal/ice.d.ts.map +1 -1
  31. package/dist/types/src/signal/signal-connection.d.ts +3 -2
  32. package/dist/types/src/signal/signal-connection.d.ts.map +1 -1
  33. package/dist/types/src/signal/signal-messenger.d.ts +3 -2
  34. package/dist/types/src/signal/signal-messenger.d.ts.map +1 -1
  35. package/dist/types/src/signal/swarm-messenger.d.ts +7 -7
  36. package/dist/types/src/signal/swarm-messenger.d.ts.map +1 -1
  37. package/dist/types/src/swarm/connection-limiter.d.ts.map +1 -1
  38. package/dist/types/src/swarm/connection.d.ts +2 -2
  39. package/dist/types/src/swarm/connection.d.ts.map +1 -1
  40. package/dist/types/src/swarm/peer.d.ts +4 -3
  41. package/dist/types/src/swarm/peer.d.ts.map +1 -1
  42. package/dist/types/src/swarm/swarm-mapper.d.ts.map +1 -1
  43. package/dist/types/src/swarm/swarm.d.ts +3 -5
  44. package/dist/types/src/swarm/swarm.d.ts.map +1 -1
  45. package/dist/types/src/testing/test-builder.d.ts.map +1 -1
  46. package/dist/types/src/testing/test-wire-protocol.d.ts.map +1 -1
  47. package/dist/types/src/tests/basic-test-suite.d.ts.map +1 -1
  48. package/dist/types/src/tests/property-test-suite.d.ts.map +1 -1
  49. package/dist/types/src/tests/utils.d.ts.map +1 -1
  50. package/dist/types/src/topology/fully-connected-topology.d.ts.map +1 -1
  51. package/dist/types/src/topology/mmst-topology.d.ts.map +1 -1
  52. package/dist/types/src/topology/star-topology.d.ts.map +1 -1
  53. package/dist/types/src/transport/memory-transport.d.ts.map +1 -1
  54. package/dist/types/src/transport/tcp/index.d.ts +1 -1
  55. package/dist/types/src/transport/tcp/index.d.ts.map +1 -1
  56. package/dist/types/src/transport/tcp/tcp-transport.browser.d.ts.map +1 -1
  57. package/dist/types/src/transport/tcp/tcp-transport.d.ts.map +1 -1
  58. package/dist/types/src/transport/webrtc/rtc-peer-connection.d.ts +4 -4
  59. package/dist/types/src/transport/webrtc/rtc-peer-connection.d.ts.map +1 -1
  60. package/dist/types/src/transport/webrtc/rtc-transport-channel.d.ts.map +1 -1
  61. package/dist/types/src/transport/webrtc/rtc-transport-factory.d.ts.map +1 -1
  62. package/dist/types/src/transport/webrtc/rtc-transport-proxy.d.ts.map +1 -1
  63. package/dist/types/src/transport/webrtc/rtc-transport-service.d.ts.map +1 -1
  64. package/dist/types/src/transport/webrtc/rtc-transport-stats.d.ts.map +1 -1
  65. package/dist/types/src/transport/webrtc/test-utils.d.ts.map +1 -1
  66. package/dist/types/src/transport/webrtc/utils.d.ts.map +1 -1
  67. package/dist/types/src/wire-protocol.d.ts +5 -5
  68. package/dist/types/src/wire-protocol.d.ts.map +1 -1
  69. package/dist/types/tsconfig.tsbuildinfo +1 -1
  70. package/package.json +33 -43
  71. package/src/network-manager.ts +21 -19
  72. package/src/signal/integration.node.test.ts +11 -10
  73. package/src/signal/signal-connection.ts +3 -2
  74. package/src/signal/signal-messenger.ts +3 -2
  75. package/src/signal/swarm-messenger.node.test.ts +25 -24
  76. package/src/signal/swarm-messenger.ts +65 -55
  77. package/src/swarm/connection.test.ts +8 -8
  78. package/src/swarm/connection.ts +15 -22
  79. package/src/swarm/peer.ts +7 -7
  80. package/src/swarm/swarm.test.ts +4 -4
  81. package/src/swarm/swarm.ts +10 -17
  82. package/src/testing/test-builder.ts +4 -4
  83. package/src/tests/basic-test-suite.ts +0 -1
  84. package/src/tests/memory-transport.test.ts +0 -2
  85. package/src/tests/property-test-suite.ts +4 -3
  86. package/src/tests/tcp-transport.node.test.ts +0 -2
  87. package/src/tests/webrtc-transport.test.ts +4 -3
  88. package/src/transport/tcp/index.ts +1 -1
  89. package/src/transport/webrtc/rtc-peer-connection.ts +1 -2
  90. package/src/transport/webrtc/rtc-transport-channel.test.ts +0 -2
  91. package/src/transport/webrtc/rtc-transport-channel.ts +1 -2
  92. package/src/transport/webrtc/rtc-transport-factory.ts +0 -1
  93. package/src/transport/webrtc/rtc-transport-proxy.test.ts +2 -3
  94. package/src/transport/webrtc/rtc-transport-proxy.ts +6 -4
  95. package/src/transport/webrtc/rtc-transport-service.ts +0 -1
  96. package/src/transport/webrtc/rtc-transport.test.ts +2 -2
  97. package/src/wire-protocol.ts +6 -6
  98. package/dist/lib/browser/chunk-VAQETEB2.mjs.map +0 -7
  99. package/dist/lib/node-esm/chunk-RAHYLU4N.mjs.map +0 -7
@@ -20,9 +20,9 @@ interface OfferRecord {
20
20
  }
21
21
 
22
22
  export type SwarmMessengerOptions = {
23
- sendMessage: (params: Message) => Promise<void>;
24
- onOffer: (message: OfferMessage) => Promise<Answer>;
25
- onSignal: (message: SignalMessage) => Promise<void>;
23
+ sendMessage: (ctx: Context, params: Message) => Promise<void>;
24
+ onOffer: (ctx: Context, message: OfferMessage) => Promise<Answer>;
25
+ onSignal: (ctx: Context, message: SignalMessage) => Promise<void>;
26
26
  topic: PublicKey;
27
27
  };
28
28
 
@@ -32,11 +32,9 @@ const SwarmMessage = schema.getCodecForType('dxos.mesh.swarm.SwarmMessage');
32
32
  * Adds offer/answer and signal interfaces.
33
33
  */
34
34
  export class SwarmMessenger implements SignalMessenger {
35
- private readonly _ctx = new Context();
36
-
37
- private readonly _sendMessage: (msg: Message) => Promise<void>;
38
- private readonly _onSignal: (message: SignalMessage) => Promise<void>;
39
- private readonly _onOffer: (message: OfferMessage) => Promise<Answer>;
35
+ private readonly _sendMessage: SwarmMessengerOptions['sendMessage'];
36
+ private readonly _onSignal: SwarmMessengerOptions['onSignal'];
37
+ private readonly _onOffer: SwarmMessengerOptions['onOffer'];
40
38
  private readonly _topic: PublicKey;
41
39
 
42
40
  private readonly _offerRecords: ComplexMap<PublicKey, OfferRecord> = new ComplexMap((key) => key.toHex());
@@ -48,15 +46,18 @@ export class SwarmMessenger implements SignalMessenger {
48
46
  this._topic = topic;
49
47
  }
50
48
 
51
- async receiveMessage({
52
- author,
53
- recipient,
54
- payload,
55
- }: {
56
- author: PeerInfo;
57
- recipient: PeerInfo;
58
- payload: Any;
59
- }): Promise<void> {
49
+ async receiveMessage(
50
+ ctx: Context,
51
+ {
52
+ author,
53
+ recipient,
54
+ payload,
55
+ }: {
56
+ author: PeerInfo;
57
+ recipient: PeerInfo;
58
+ payload: Any;
59
+ },
60
+ ): Promise<void> {
60
61
  if (payload.type_url !== 'dxos.mesh.swarm.SwarmMessage') {
61
62
  // Ignore not swarm messages.
62
63
  return;
@@ -71,35 +72,35 @@ export class SwarmMessenger implements SignalMessenger {
71
72
  log('received', { from: author, to: recipient, msg: message });
72
73
 
73
74
  if (message.data?.offer) {
74
- await this._handleOffer({ author, recipient, message });
75
+ await this._handleOffer(ctx, { author, recipient, message });
75
76
  } else if (message.data?.answer) {
76
77
  await this._resolveAnswers(message);
77
78
  } else if (message.data?.signal) {
78
- await this._handleSignal({ author, recipient, message });
79
+ await this._handleSignal(ctx, { author, recipient, message });
79
80
  } else if (message.data?.signalBatch) {
80
- await this._handleSignal({ author, recipient, message });
81
+ await this._handleSignal(ctx, { author, recipient, message });
81
82
  } else {
82
83
  log.warn('unknown message', { message });
83
84
  }
84
85
  }
85
86
 
86
- async signal(message: SignalMessage): Promise<void> {
87
+ async signal(ctx: Context, message: SignalMessage): Promise<void> {
87
88
  invariant(message.data?.signal || message.data?.signalBatch, 'Invalid message');
88
- await this._sendReliableMessage({
89
+ await this._sendReliableMessage(ctx, {
89
90
  author: message.author,
90
91
  recipient: message.recipient,
91
92
  message,
92
93
  });
93
94
  }
94
95
 
95
- async offer(message: OfferMessage): Promise<Answer> {
96
+ async offer(ctx: Context, message: OfferMessage): Promise<Answer> {
96
97
  const networkMessage: SwarmMessage = {
97
98
  ...message,
98
99
  messageId: PublicKey.random(),
99
100
  };
100
101
  return new Promise<Answer>((resolve, reject) => {
101
102
  this._offerRecords.set(networkMessage.messageId!, { resolve });
102
- this._sendReliableMessage({
103
+ this._sendReliableMessage(ctx, {
103
104
  author: message.author,
104
105
  recipient: message.recipient,
105
106
  message: networkMessage,
@@ -107,15 +108,18 @@ export class SwarmMessenger implements SignalMessenger {
107
108
  });
108
109
  }
109
110
 
110
- private async _sendReliableMessage({
111
- author,
112
- recipient,
113
- message,
114
- }: {
115
- author: PeerInfo;
116
- recipient: PeerInfo;
117
- message: MakeOptional<SwarmMessage, 'messageId'>;
118
- }): Promise<void> {
111
+ private async _sendReliableMessage(
112
+ ctx: Context,
113
+ {
114
+ author,
115
+ recipient,
116
+ message,
117
+ }: {
118
+ author: PeerInfo;
119
+ recipient: PeerInfo;
120
+ message: MakeOptional<SwarmMessage, 'messageId'>;
121
+ },
122
+ ): Promise<void> {
119
123
  const networkMessage: SwarmMessage = {
120
124
  ...message,
121
125
  // Setting unique message_id if it not specified yet.
@@ -123,7 +127,7 @@ export class SwarmMessenger implements SignalMessenger {
123
127
  };
124
128
 
125
129
  log('sending', { from: author, to: recipient, msg: networkMessage });
126
- await this._sendMessage({
130
+ await this._sendMessage(ctx, {
127
131
  author,
128
132
  recipient,
129
133
  payload: {
@@ -144,15 +148,18 @@ export class SwarmMessenger implements SignalMessenger {
144
148
  }
145
149
  }
146
150
 
147
- private async _handleOffer({
148
- author,
149
- recipient,
150
- message,
151
- }: {
152
- author: PeerInfo;
153
- recipient: PeerInfo;
154
- message: SwarmMessage;
155
- }): Promise<void> {
151
+ private async _handleOffer(
152
+ ctx: Context,
153
+ {
154
+ author,
155
+ recipient,
156
+ message,
157
+ }: {
158
+ author: PeerInfo;
159
+ recipient: PeerInfo;
160
+ message: SwarmMessage;
161
+ },
162
+ ): Promise<void> {
156
163
  invariant(message.data.offer, 'No offer');
157
164
  const offerMessage: OfferMessage = {
158
165
  author,
@@ -160,10 +167,10 @@ export class SwarmMessenger implements SignalMessenger {
160
167
  ...message,
161
168
  data: { offer: message.data.offer },
162
169
  };
163
- const answer = await this._onOffer(offerMessage);
170
+ const answer = await this._onOffer(ctx, offerMessage);
164
171
  answer.offerMessageId = message.messageId;
165
172
  try {
166
- await this._sendReliableMessage({
173
+ await this._sendReliableMessage(ctx, {
167
174
  author: recipient,
168
175
  recipient: author,
169
176
  message: {
@@ -181,15 +188,18 @@ export class SwarmMessenger implements SignalMessenger {
181
188
  }
182
189
  }
183
190
 
184
- private async _handleSignal({
185
- author,
186
- recipient,
187
- message,
188
- }: {
189
- author: PeerInfo;
190
- recipient: PeerInfo;
191
- message: SwarmMessage;
192
- }): Promise<void> {
191
+ private async _handleSignal(
192
+ ctx: Context,
193
+ {
194
+ author,
195
+ recipient,
196
+ message,
197
+ }: {
198
+ author: PeerInfo;
199
+ recipient: PeerInfo;
200
+ message: SwarmMessage;
201
+ },
202
+ ): Promise<void> {
193
203
  invariant(message.messageId);
194
204
  invariant(message.data.signal || message.data.signalBatch, 'Invalid message');
195
205
  const signalMessage: SignalMessage = {
@@ -202,6 +212,6 @@ export class SwarmMessenger implements SignalMessenger {
202
212
  },
203
213
  };
204
214
 
205
- await this._onSignal(signalMessage);
215
+ await this._onSignal(ctx, signalMessage);
206
216
  }
207
217
  }
@@ -10,10 +10,10 @@ import { PublicKey } from '@dxos/keys';
10
10
  import { TestWireProtocol } from '../testing/test-wire-protocol';
11
11
  import { createRtcTransportFactory } from '../transport';
12
12
  import { chooseInitiatorPeer } from '../transport/webrtc/utils';
13
-
14
13
  import { Connection } from './connection';
15
14
 
16
- describe('Connection', () => {
15
+ // Segfault in node-datachannel.
16
+ describe.skip('Connection', () => {
17
17
  test('responder opens after initiator', async () => {
18
18
  const { initiator, responder } = createPeerKeys();
19
19
  await connectionTest({
@@ -43,9 +43,9 @@ describe('Connection', () => {
43
43
  sessionId,
44
44
  true,
45
45
  {
46
- offer: async (msg) => ({ accept: true }),
47
- signal: async (msg) => {
48
- await fastConnection.signal(msg);
46
+ offer: async (_ctx, _msg) => ({ accept: true }),
47
+ signal: async (ctx, msg) => {
48
+ await fastConnection.signal(ctx, msg);
49
49
  },
50
50
  },
51
51
  slowPeerProtocol.factory({
@@ -65,9 +65,9 @@ describe('Connection', () => {
65
65
  sessionId,
66
66
  false,
67
67
  {
68
- offer: async (msg) => ({ accept: true }),
69
- signal: async (msg) => {
70
- await slowConnection.signal(msg);
68
+ offer: async (_ctx, _msg) => ({ accept: true }),
69
+ signal: async (ctx, msg) => {
70
+ await slowConnection.signal(ctx, msg);
71
71
  },
72
72
  },
73
73
  fastPeerProtocol.factory({
@@ -9,14 +9,7 @@ import { invariant } from '@dxos/invariant';
9
9
  import { PublicKey } from '@dxos/keys';
10
10
  import { log, logInfo } from '@dxos/log';
11
11
  import { type PeerInfo } from '@dxos/messaging';
12
- import {
13
- CancelledError,
14
- ConnectionResetError,
15
- ConnectivityError,
16
- ProtocolError,
17
- TimeoutError,
18
- trace,
19
- } from '@dxos/protocols';
12
+ import { CancelledError, ConnectionResetError, ConnectivityError, ProtocolError, TimeoutError } from '@dxos/protocols';
20
13
  import { type Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
21
14
 
22
15
  import { type SignalMessage, type SignalMessenger } from '../signal';
@@ -113,12 +106,10 @@ export class Connection {
113
106
  readonly stateChanged = new Event<ConnectionState>();
114
107
  readonly errors = new ErrorStream();
115
108
 
116
- public _instanceId = PublicKey.random().toHex();
117
-
118
109
  public readonly transportStats = new Event<TransportStats>();
119
110
 
120
111
  private readonly _signalSendTask = new DeferredTask(this._ctx, async () => {
121
- await this._flushSignalBuffer();
112
+ await this._flushSignalBuffer(this._ctx);
122
113
  });
123
114
 
124
115
  private _signallingDelay = STARTING_SIGNALLING_DELAY;
@@ -165,7 +156,7 @@ export class Connection {
165
156
  */
166
157
  async openConnection(): Promise<void> {
167
158
  invariant(this._state === ConnectionState.INITIAL, 'Invalid state.');
168
- log.trace('dxos.mesh.connection.open-connection', trace.begin({ id: this._instanceId }));
159
+ log('opening connection');
169
160
  log.trace('dxos.mesh.connection.open', {
170
161
  sessionId: this.sessionId,
171
162
  topic: this.topic,
@@ -185,16 +176,18 @@ export class Connection {
185
176
  this._protocol.stream.on('close', () => {
186
177
  log('protocol stream closed');
187
178
  this._protocolClosed.wake();
188
- this.close({ error: new ProtocolError('protocol stream closed') }).catch((err) => this.errors.raise(err));
179
+ this.close({ error: new ProtocolError({ message: 'protocol stream closed' }) }).catch((err) =>
180
+ this.errors.raise(err),
181
+ );
189
182
  });
190
183
 
191
184
  scheduleTask(
192
185
  this.connectedTimeoutContext,
193
186
  async () => {
194
187
  log.info(`timeout waiting ${TRANSPORT_CONNECTION_TIMEOUT / 1000}s for transport to connect, aborting`);
195
- await this.abort(new TimeoutError(`${TRANSPORT_CONNECTION_TIMEOUT / 1000}s for transport to connect`)).catch(
196
- (err) => this.errors.raise(err),
197
- );
188
+ await this.abort(
189
+ new TimeoutError({ message: `${TRANSPORT_CONNECTION_TIMEOUT / 1000}s for transport to connect` }),
190
+ ).catch((err) => this.errors.raise(err));
198
191
  },
199
192
  TRANSPORT_CONNECTION_TIMEOUT,
200
193
  );
@@ -255,7 +248,7 @@ export class Connection {
255
248
 
256
249
  this._incomingSignalBuffer = [];
257
250
 
258
- log.trace('dxos.mesh.connection.open-connection', trace.end({ id: this._instanceId }));
251
+ log('opened connection');
259
252
  }
260
253
 
261
254
  @synchronized
@@ -364,21 +357,21 @@ export class Connection {
364
357
  this._signalSendTask.schedule();
365
358
  }
366
359
 
367
- private async _flushSignalBuffer(): Promise<void> {
360
+ private async _flushSignalBuffer(ctx: Context): Promise<void> {
368
361
  if (this._outgoingSignalBuffer.length === 0) {
369
362
  return;
370
363
  }
371
364
 
372
365
  try {
373
366
  if (process.env.NODE_ENV !== 'test') {
374
- await cancelWithContext(this._ctx, sleep(this._signallingDelay));
367
+ await cancelWithContext(ctx, sleep(this._signallingDelay));
375
368
  this._signallingDelay = Math.min(this._signallingDelay * 2, MAX_SIGNALLING_DELAY);
376
369
  }
377
370
 
378
371
  const signals = [...this._outgoingSignalBuffer];
379
372
  this._outgoingSignalBuffer.length = 0;
380
373
 
381
- await this._signalMessaging.signal({
374
+ await this._signalMessaging.signal(ctx, {
382
375
  author: this.localInfo,
383
376
  recipient: this.remoteInfo,
384
377
  sessionId: this.sessionId,
@@ -397,14 +390,14 @@ export class Connection {
397
390
 
398
391
  // If signal fails treat connection as failed
399
392
  log.info('signal message failed to deliver', { err });
400
- await this.close({ error: new ConnectivityError('signal message failed to deliver', err) });
393
+ await this.close({ error: new ConnectivityError({ message: 'signal message failed to deliver', cause: err }) });
401
394
  }
402
395
  }
403
396
 
404
397
  /**
405
398
  * Receive a signal from the remote peer.
406
399
  */
407
- async signal(msg: SignalMessage): Promise<void> {
400
+ async signal(_ctx: Context, msg: SignalMessage): Promise<void> {
408
401
  invariant(msg.sessionId);
409
402
  if (!msg.sessionId.equals(this.sessionId)) {
410
403
  log('dropping signal for incorrect session id');
package/src/swarm/peer.ts CHANGED
@@ -14,13 +14,12 @@ import { type Answer } from '@dxos/protocols/proto/dxos/mesh/swarm';
14
14
  import { type OfferMessage, type SignalMessage, type SignalMessenger } from '../signal';
15
15
  import { type TransportFactory } from '../transport';
16
16
  import { type WireProtocolProvider } from '../wire-protocol';
17
-
18
17
  import { Connection, ConnectionState } from './connection';
19
18
  import { type ConnectionLimiter } from './connection-limiter';
20
19
 
21
20
  export class ConnectionDisplacedError extends SystemError {
22
21
  constructor() {
23
- super('Connection displaced by remote initiator.');
22
+ super({ message: 'Connection displaced by remote initiator.' });
24
23
  }
25
24
  }
26
25
 
@@ -106,7 +105,7 @@ export class Peer {
106
105
  /**
107
106
  * Respond to remote offer.
108
107
  */
109
- async onOffer(message: OfferMessage): Promise<Answer> {
108
+ async onOffer(_ctx: Context, message: OfferMessage): Promise<Answer> {
110
109
  const remote = message.author;
111
110
 
112
111
  if (
@@ -162,13 +161,14 @@ export class Peer {
162
161
  return { accept: true };
163
162
  }
164
163
  }
164
+
165
165
  return { accept: false };
166
166
  }
167
167
 
168
168
  /**
169
169
  * Initiate a connection to the remote peer.
170
170
  */
171
- async initiateConnection(): Promise<void> {
171
+ async initiateConnection(ctx: Context): Promise<void> {
172
172
  invariant(!this.initiating, 'Initiation in progress.');
173
173
  invariant(!this.connection, 'Already connected.');
174
174
  const sessionId = PublicKey.random();
@@ -182,7 +182,7 @@ export class Peer {
182
182
  await this._connectionLimiter.connecting(sessionId);
183
183
  connection.initiate();
184
184
 
185
- answer = await this._signalMessaging.offer({
185
+ answer = await this._signalMessaging.offer(ctx, {
186
186
  author: this.localInfo,
187
187
  recipient: this.remoteInfo,
188
188
  sessionId,
@@ -377,13 +377,13 @@ export class Peer {
377
377
  log('closed', { peerId: this.remoteInfo, sessionId: connection.sessionId });
378
378
  }
379
379
 
380
- async onSignal(message: SignalMessage): Promise<void> {
380
+ async onSignal(ctx: Context, message: SignalMessage): Promise<void> {
381
381
  if (!this.connection) {
382
382
  log('dropping signal message for non-existent connection', { message });
383
383
  return;
384
384
  }
385
385
 
386
- await this.connection.signal(message);
386
+ await this.connection.signal(ctx, message);
387
387
  }
388
388
 
389
389
  @synchronized
@@ -18,7 +18,6 @@ import { ComplexSet } from '@dxos/util';
18
18
  import { TestWireProtocol } from '../testing/test-wire-protocol';
19
19
  import { FullyConnectedTopology } from '../topology';
20
20
  import { createRtcTransportFactory } from '../transport';
21
-
22
21
  import { ConnectionState } from './connection';
23
22
  import { ConnectionLimiter } from './connection-limiter';
24
23
  import { Swarm } from './swarm';
@@ -31,7 +30,8 @@ type TestPeer = {
31
30
  signalManager: SignalManager;
32
31
  };
33
32
 
34
- describe('Swarm', () => {
33
+ // Segfault in node-datachannel.
34
+ describe.skip('Swarm', () => {
35
35
  const context = new MemorySignalManagerContext();
36
36
 
37
37
  const setupSwarm = async ({
@@ -158,9 +158,9 @@ describe('Swarm', () => {
158
158
  const messages = new ComplexSet<{ author: PeerInfo; recipient: PeerInfo }>(
159
159
  ({ author, recipient }) => author.peerKey + recipient.peerKey,
160
160
  );
161
- signalManager.sendMessage = async (message) => {
161
+ signalManager.sendMessage = async (ctx, message) => {
162
162
  messages.add({ author: message.author, recipient: message.recipient });
163
- return sendOriginal(message);
163
+ return sendOriginal(ctx, message);
164
164
  };
165
165
  // Stop signaling to stop connection in initiation state.
166
166
  signalManager.freeze();
@@ -9,7 +9,6 @@ import { invariant } from '@dxos/invariant';
9
9
  import { PublicKey } from '@dxos/keys';
10
10
  import { log, logInfo } from '@dxos/log';
11
11
  import { type ListeningHandle, type Messenger, type PeerInfo, PeerInfoHash, type SwarmEvent } from '@dxos/messaging';
12
- import { trace } from '@dxos/protocols';
13
12
  import { type Answer } from '@dxos/protocols/proto/dxos/mesh/swarm';
14
13
  import { ComplexMap, isNonNullable } from '@dxos/util';
15
14
 
@@ -18,7 +17,6 @@ import { type SwarmController, type Topology } from '../topology';
18
17
  import { type TransportFactory } from '../transport';
19
18
  import { type Topic } from '../types';
20
19
  import { type WireProtocolProvider } from '../wire-protocol';
21
-
22
20
  import { type Connection, ConnectionState } from './connection';
23
21
  import { type ConnectionLimiter } from './connection-limiter';
24
22
  import { Peer } from './peer';
@@ -86,20 +84,15 @@ export class Swarm {
86
84
  private readonly _connectionLimiter: ConnectionLimiter,
87
85
  private readonly _initiationDelay = INITIATION_DELAY,
88
86
  ) {
89
- log.trace(
90
- 'dxos.mesh.swarm.constructor',
91
- trace.begin({ id: this._instanceId, data: { topic: this._topic.toHex(), peer: this._ownPeer } }),
92
- );
93
- log('creating swarm', { peerId: _ownPeer });
87
+ log('creating swarm', { topic: this._topic.toHex(), peer: this._ownPeer });
94
88
  _topology.init(this._getSwarmController());
95
89
 
96
90
  this._swarmMessenger = new SwarmMessenger({
97
- sendMessage: async (msg) => await this._messenger.sendMessage(msg),
98
- onSignal: async (msg) => await this.onSignal(msg),
99
- onOffer: async (msg) => await this.onOffer(msg),
91
+ sendMessage: async (ctx, msg) => await this._messenger.sendMessage(ctx, msg),
92
+ onSignal: async (ctx, msg) => await this.onSignal(ctx, msg),
93
+ onOffer: async (ctx, msg) => await this.onOffer(ctx, msg),
100
94
  topic: this._topic,
101
95
  });
102
- log.trace('dxos.mesh.swarm.constructor', trace.end({ id: this._instanceId }));
103
96
  }
104
97
 
105
98
  get connections() {
@@ -136,7 +129,7 @@ export class Swarm {
136
129
  payloadType: 'dxos.mesh.swarm.SwarmMessage',
137
130
  onMessage: async (message) => {
138
131
  await this._swarmMessenger
139
- .receiveMessage(message)
132
+ .receiveMessage(this._ctx, message)
140
133
  // TODO(nf): discriminate between errors
141
134
  .catch((err) => log.info('Error while receiving message', { err }));
142
135
  },
@@ -205,7 +198,7 @@ export class Swarm {
205
198
  }
206
199
 
207
200
  @synchronized
208
- async onOffer(message: OfferMessage): Promise<Answer> {
201
+ async onOffer(ctx: Context, message: OfferMessage): Promise<Answer> {
209
202
  log('offer', { message });
210
203
  if (this._ctx.disposed) {
211
204
  log('ignored for disposed swarm');
@@ -224,7 +217,7 @@ export class Swarm {
224
217
  }
225
218
 
226
219
  const peer = this._getOfferSenderPeer(message.author);
227
- const answer = await peer.onOffer(message);
220
+ const answer = await peer.onOffer(ctx, message);
228
221
  this._topology.update();
229
222
  return answer;
230
223
  }
@@ -243,7 +236,7 @@ export class Swarm {
243
236
  return peer;
244
237
  }
245
238
 
246
- async onSignal(message: SignalMessage): Promise<void> {
239
+ async onSignal(ctx: Context, message: SignalMessage): Promise<void> {
247
240
  log('signal', { message });
248
241
  if (this._ctx.disposed) {
249
242
  log.info('ignored for offline swarm');
@@ -257,7 +250,7 @@ export class Swarm {
257
250
  invariant(message.author);
258
251
 
259
252
  const peer = this._getOrCreatePeer(message.author);
260
- await peer.onSignal(message);
253
+ await peer.onSignal(ctx, message);
261
254
  }
262
255
 
263
256
  // For debug purposes
@@ -404,7 +397,7 @@ export class Swarm {
404
397
  }
405
398
 
406
399
  log('initiating connection...', { remotePeer });
407
- await peer.initiateConnection();
400
+ await peer.initiateConnection(ctx);
408
401
  this._topology.update();
409
402
  log('initiated', { remotePeer });
410
403
  }
@@ -2,6 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
+ import { Context } from '@dxos/context';
5
6
  import { PublicKey } from '@dxos/keys';
6
7
  import { log } from '@dxos/log';
7
8
  import {
@@ -28,7 +29,6 @@ import {
28
29
  TransportKind,
29
30
  createRtcTransportFactory,
30
31
  } from '../transport';
31
-
32
32
  import { type TestTeleportExtensionFactory, TestWireProtocol } from './test-wire-protocol';
33
33
 
34
34
  // Signal server will be started by the setup script.
@@ -169,7 +169,7 @@ export class TestPeer {
169
169
 
170
170
  await this._proxy?.close();
171
171
  await this._service?.close();
172
- await this._networkManager.close();
172
+ await this._networkManager.close(Context.default());
173
173
  }
174
174
 
175
175
  getSwarm(topic: PublicKey): TestSwarmConnection {
@@ -218,7 +218,7 @@ export class TestSwarmConnection {
218
218
  // TODO(burdon): Need to create new plugin instance per swarm?
219
219
  // If so, then perhaps joinSwarm should return swarm object with access to plugins.
220
220
  async join(topology = new FullyConnectedTopology()): Promise<this> {
221
- await this.peer._networkManager.joinSwarm({
221
+ await this.peer._networkManager.joinSwarm(Context.default(), {
222
222
  topic: this.topic,
223
223
  peerInfo: { peerKey: this.peer.peerId.toHex(), identityKey: this.peer.peerId.toHex() },
224
224
  protocolProvider: this.protocol.factory,
@@ -229,7 +229,7 @@ export class TestSwarmConnection {
229
229
  }
230
230
 
231
231
  async leave(): Promise<this> {
232
- await this.peer._networkManager.leaveSwarm(this.topic);
232
+ await this.peer._networkManager.leaveSwarm(Context.default(), this.topic);
233
233
  return this;
234
234
  }
235
235
  }
@@ -11,7 +11,6 @@ import { range } from '@dxos/util';
11
11
 
12
12
  import { type TestBuilder } from '../testing';
13
13
  import { FullyConnectedTopology, StarTopology } from '../topology';
14
-
15
14
  import { exchangeMessages, joinSwarm, leaveSwarm, openAndCloseAfterTest } from './utils';
16
15
 
17
16
  // TODO(burdon): Use PublicKey throughout (remove conversion to strings, from buffers, etc.)
@@ -3,7 +3,6 @@
3
3
  //
4
4
 
5
5
  import { randomBytes } from 'node:crypto';
6
-
7
6
  import { describe, test } from 'vitest';
8
7
 
9
8
  import { PublicKey } from '@dxos/keys';
@@ -11,7 +10,6 @@ import { range } from '@dxos/util';
11
10
 
12
11
  import { TestBuilder } from '../testing';
13
12
  import { FullyConnectedTopology } from '../topology';
14
-
15
13
  import { basicTestSuite } from './basic-test-suite';
16
14
  import { exchangeMessages, joinSwarm, leaveSwarm, openAndCloseAfterTest } from './utils';
17
15
 
@@ -6,6 +6,7 @@ import * as fc from 'fast-check';
6
6
  import { type ModelRunSetup } from 'fast-check';
7
7
  import { test } from 'vitest';
8
8
 
9
+ import { Context } from '@dxos/context';
9
10
  import { todo } from '@dxos/debug';
10
11
  import { PublicKey } from '@dxos/keys';
11
12
  import { ComplexMap, ComplexSet, range } from '@dxos/util';
@@ -97,7 +98,7 @@ export const propertyTestSuite = () => {
97
98
  model.joinedPeers.delete(this.peerId);
98
99
 
99
100
  const peer = real.peers.get(this.peerId);
100
- await peer!.networkManager.close();
101
+ await peer!.networkManager.close(Context.default());
101
102
  real.peers.delete(this.peerId);
102
103
 
103
104
  await assertState(model, real);
@@ -119,7 +120,7 @@ export const propertyTestSuite = () => {
119
120
  // afterTest(() => presence.stop());
120
121
  // const protocol = createProtocolFactory(model.topic, this.peerId, [presence]);
121
122
 
122
- await peer.networkManager.joinSwarm({
123
+ await peer.networkManager.joinSwarm(Context.default(), {
123
124
  peerInfo: {
124
125
  peerKey: this.peerId.toHex(),
125
126
  identityKey: this.peerId.toHex(),
@@ -146,7 +147,7 @@ export const propertyTestSuite = () => {
146
147
  model.joinedPeers.delete(this.peerId);
147
148
 
148
149
  const peer = real.peers.get(this.peerId)!;
149
- await peer.networkManager.leaveSwarm(model.topic);
150
+ await peer.networkManager.leaveSwarm(Context.default(), model.topic);
150
151
  peer.presence = undefined;
151
152
 
152
153
  await assertState(model, real);
@@ -3,7 +3,6 @@
3
3
  //
4
4
 
5
5
  import { randomBytes } from 'node:crypto';
6
-
7
6
  import { describe, test } from 'vitest';
8
7
 
9
8
  import { PublicKey } from '@dxos/keys';
@@ -12,7 +11,6 @@ import { range } from '@dxos/util';
12
11
  import { TestBuilder } from '../testing';
13
12
  import { FullyConnectedTopology } from '../topology';
14
13
  import { TransportKind } from '../transport';
15
-
16
14
  import { basicTestSuite } from './basic-test-suite';
17
15
  import { exchangeMessages, joinSwarm, leaveSwarm, openAndCloseAfterTest } from './utils';
18
16