@dxos/network-manager 0.8.4-main.b97322e → 0.8.4-main.bcb3aa67d6

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 (95) hide show
  1. package/dist/lib/browser/{chunk-2XXESTV3.mjs → chunk-WMCWASCJ.mjs} +770 -999
  2. package/dist/lib/browser/chunk-WMCWASCJ.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +342 -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 +78 -49
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/browser/transport/tcp/index.mjs +2 -35
  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 +160 -0
  13. package/dist/lib/browser/transport/tcp/tcp-transport.mjs.map +7 -0
  14. package/dist/lib/node-esm/{chunk-RPB6YS7U.mjs → chunk-AL2EW6AJ.mjs} +770 -999
  15. package/dist/lib/node-esm/chunk-AL2EW6AJ.mjs.map +7 -0
  16. package/dist/lib/node-esm/index.mjs +342 -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 +78 -49
  20. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  21. package/dist/lib/node-esm/transport/tcp/index.mjs +2 -156
  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 +160 -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 +5 -4
  29. package/dist/types/src/network-manager.d.ts.map +1 -1
  30. package/dist/types/src/signal/signal-connection.d.ts +3 -2
  31. package/dist/types/src/signal/signal-connection.d.ts.map +1 -1
  32. package/dist/types/src/signal/signal-messenger.d.ts +3 -2
  33. package/dist/types/src/signal/signal-messenger.d.ts.map +1 -1
  34. package/dist/types/src/signal/swarm-messenger.d.ts +8 -8
  35. package/dist/types/src/signal/swarm-messenger.d.ts.map +1 -1
  36. package/dist/types/src/swarm/connection.d.ts +2 -1
  37. package/dist/types/src/swarm/connection.d.ts.map +1 -1
  38. package/dist/types/src/swarm/peer.d.ts +6 -5
  39. package/dist/types/src/swarm/peer.d.ts.map +1 -1
  40. package/dist/types/src/swarm/swarm.d.ts +6 -5
  41. package/dist/types/src/swarm/swarm.d.ts.map +1 -1
  42. package/dist/types/src/testing/test-builder.d.ts +1 -1
  43. package/dist/types/src/testing/test-builder.d.ts.map +1 -1
  44. package/dist/types/src/testing/test-wire-protocol.d.ts +1 -1
  45. package/dist/types/src/testing/test-wire-protocol.d.ts.map +1 -1
  46. package/dist/types/src/tests/basic-test-suite.d.ts.map +1 -1
  47. package/dist/types/src/tests/property-test-suite.d.ts.map +1 -1
  48. package/dist/types/src/transport/tcp/index.d.ts +1 -1
  49. package/dist/types/src/transport/tcp/index.d.ts.map +1 -1
  50. package/dist/types/src/transport/webrtc/rtc-peer-connection.d.ts +2 -2
  51. package/dist/types/src/transport/webrtc/rtc-peer-connection.d.ts.map +1 -1
  52. package/dist/types/src/transport/webrtc/rtc-transport-channel.d.ts +1 -1
  53. package/dist/types/src/transport/webrtc/rtc-transport-channel.d.ts.map +1 -1
  54. package/dist/types/src/transport/webrtc/rtc-transport-factory.d.ts.map +1 -1
  55. package/dist/types/src/transport/webrtc/rtc-transport-proxy.d.ts.map +1 -1
  56. package/dist/types/src/transport/webrtc/rtc-transport-service.d.ts +1 -1
  57. package/dist/types/src/transport/webrtc/rtc-transport-service.d.ts.map +1 -1
  58. package/dist/types/src/wire-protocol.d.ts +5 -5
  59. package/dist/types/src/wire-protocol.d.ts.map +1 -1
  60. package/dist/types/tsconfig.tsbuildinfo +1 -1
  61. package/package.json +37 -33
  62. package/src/connection-log.ts +1 -1
  63. package/src/network-manager.ts +20 -16
  64. package/src/signal/ice.test.ts +1 -1
  65. package/src/signal/integration.node.test.ts +13 -12
  66. package/src/signal/signal-connection.ts +3 -2
  67. package/src/signal/signal-messenger.ts +3 -2
  68. package/src/signal/swarm-messenger.node.test.ts +26 -25
  69. package/src/signal/swarm-messenger.ts +66 -56
  70. package/src/swarm/connection.test.ts +10 -8
  71. package/src/swarm/connection.ts +15 -13
  72. package/src/swarm/peer.ts +10 -8
  73. package/src/swarm/swarm-mapper.ts +1 -1
  74. package/src/swarm/swarm.test.ts +9 -7
  75. package/src/swarm/swarm.ts +14 -13
  76. package/src/testing/test-builder.ts +15 -7
  77. package/src/testing/test-wire-protocol.ts +2 -2
  78. package/src/tests/basic-test-suite.ts +3 -2
  79. package/src/tests/memory-transport.test.ts +4 -2
  80. package/src/tests/property-test-suite.ts +4 -3
  81. package/src/tests/tcp-transport.node.test.ts +4 -2
  82. package/src/tests/webrtc-transport.test.ts +6 -3
  83. package/src/transport/tcp/index.ts +1 -1
  84. package/src/transport/tcp/tcp-transport.ts +1 -1
  85. package/src/transport/webrtc/rtc-peer-connection.ts +5 -4
  86. package/src/transport/webrtc/rtc-transport-channel.test.ts +3 -1
  87. package/src/transport/webrtc/rtc-transport-channel.ts +3 -2
  88. package/src/transport/webrtc/rtc-transport-factory.ts +3 -2
  89. package/src/transport/webrtc/rtc-transport-proxy.test.ts +7 -4
  90. package/src/transport/webrtc/rtc-transport-proxy.ts +6 -4
  91. package/src/transport/webrtc/rtc-transport-service.ts +6 -5
  92. package/src/transport/webrtc/rtc-transport.test.ts +6 -4
  93. package/src/wire-protocol.ts +6 -6
  94. package/dist/lib/browser/chunk-2XXESTV3.mjs.map +0 -7
  95. package/dist/lib/node-esm/chunk-RPB6YS7U.mjs.map +0 -7
@@ -7,7 +7,7 @@ import { Context } from '@dxos/context';
7
7
  import { invariant } from '@dxos/invariant';
8
8
  import { PublicKey } from '@dxos/keys';
9
9
  import { log } from '@dxos/log';
10
- import { type PeerInfo, type Message } from '@dxos/messaging';
10
+ import { type Message, type PeerInfo } from '@dxos/messaging';
11
11
  import { TimeoutError } from '@dxos/protocols';
12
12
  import { schema } from '@dxos/protocols/proto';
13
13
  import { type Answer, type SwarmMessage } from '@dxos/protocols/proto/dxos/mesh/swarm';
@@ -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
  }
@@ -7,12 +7,14 @@ import { describe, test } from 'vitest';
7
7
  import { sleep } from '@dxos/async';
8
8
  import { PublicKey } from '@dxos/keys';
9
9
 
10
- import { Connection } from './connection';
11
10
  import { TestWireProtocol } from '../testing/test-wire-protocol';
12
11
  import { createRtcTransportFactory } from '../transport';
13
12
  import { chooseInitiatorPeer } from '../transport/webrtc/utils';
14
13
 
15
- describe('Connection', () => {
14
+ import { Connection } from './connection';
15
+
16
+ // Segfault in node-datachannel.
17
+ describe.skip('Connection', () => {
16
18
  test('responder opens after initiator', async () => {
17
19
  const { initiator, responder } = createPeerKeys();
18
20
  await connectionTest({
@@ -42,9 +44,9 @@ describe('Connection', () => {
42
44
  sessionId,
43
45
  true,
44
46
  {
45
- offer: async (msg) => ({ accept: true }),
46
- signal: async (msg) => {
47
- await fastConnection.signal(msg);
47
+ offer: async (_ctx, _msg) => ({ accept: true }),
48
+ signal: async (ctx, msg) => {
49
+ await fastConnection.signal(ctx, msg);
48
50
  },
49
51
  },
50
52
  slowPeerProtocol.factory({
@@ -64,9 +66,9 @@ describe('Connection', () => {
64
66
  sessionId,
65
67
  false,
66
68
  {
67
- offer: async (msg) => ({ accept: true }),
68
- signal: async (msg) => {
69
- await slowConnection.signal(msg);
69
+ offer: async (_ctx, _msg) => ({ accept: true }),
70
+ signal: async (ctx, msg) => {
71
+ await slowConnection.signal(ctx, msg);
70
72
  },
71
73
  },
72
74
  fastPeerProtocol.factory({
@@ -2,8 +2,8 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
- import { DeferredTask, Event, sleep, scheduleTask, scheduleTaskInterval, synchronized, Trigger } from '@dxos/async';
6
- import { Context, cancelWithContext, ContextDisposedError } from '@dxos/context';
5
+ import { DeferredTask, Event, Trigger, scheduleTask, scheduleTaskInterval, sleep, synchronized } from '@dxos/async';
6
+ import { Context, ContextDisposedError, cancelWithContext } from '@dxos/context';
7
7
  import { ErrorStream } from '@dxos/debug';
8
8
  import { invariant } from '@dxos/invariant';
9
9
  import { PublicKey } from '@dxos/keys';
@@ -11,9 +11,9 @@ import { log, logInfo } from '@dxos/log';
11
11
  import { type PeerInfo } from '@dxos/messaging';
12
12
  import {
13
13
  CancelledError,
14
- ProtocolError,
15
14
  ConnectionResetError,
16
15
  ConnectivityError,
16
+ ProtocolError,
17
17
  TimeoutError,
18
18
  trace,
19
19
  } from '@dxos/protocols';
@@ -118,7 +118,7 @@ export class Connection {
118
118
  public readonly transportStats = new Event<TransportStats>();
119
119
 
120
120
  private readonly _signalSendTask = new DeferredTask(this._ctx, async () => {
121
- await this._flushSignalBuffer();
121
+ await this._flushSignalBuffer(this._ctx);
122
122
  });
123
123
 
124
124
  private _signallingDelay = STARTING_SIGNALLING_DELAY;
@@ -185,16 +185,18 @@ export class Connection {
185
185
  this._protocol.stream.on('close', () => {
186
186
  log('protocol stream closed');
187
187
  this._protocolClosed.wake();
188
- this.close({ error: new ProtocolError('protocol stream closed') }).catch((err) => this.errors.raise(err));
188
+ this.close({ error: new ProtocolError({ message: 'protocol stream closed' }) }).catch((err) =>
189
+ this.errors.raise(err),
190
+ );
189
191
  });
190
192
 
191
193
  scheduleTask(
192
194
  this.connectedTimeoutContext,
193
195
  async () => {
194
196
  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
- );
197
+ await this.abort(
198
+ new TimeoutError({ message: `${TRANSPORT_CONNECTION_TIMEOUT / 1000}s for transport to connect` }),
199
+ ).catch((err) => this.errors.raise(err));
198
200
  },
199
201
  TRANSPORT_CONNECTION_TIMEOUT,
200
202
  );
@@ -364,21 +366,21 @@ export class Connection {
364
366
  this._signalSendTask.schedule();
365
367
  }
366
368
 
367
- private async _flushSignalBuffer(): Promise<void> {
369
+ private async _flushSignalBuffer(ctx: Context): Promise<void> {
368
370
  if (this._outgoingSignalBuffer.length === 0) {
369
371
  return;
370
372
  }
371
373
 
372
374
  try {
373
375
  if (process.env.NODE_ENV !== 'test') {
374
- await cancelWithContext(this._ctx, sleep(this._signallingDelay));
376
+ await cancelWithContext(ctx, sleep(this._signallingDelay));
375
377
  this._signallingDelay = Math.min(this._signallingDelay * 2, MAX_SIGNALLING_DELAY);
376
378
  }
377
379
 
378
380
  const signals = [...this._outgoingSignalBuffer];
379
381
  this._outgoingSignalBuffer.length = 0;
380
382
 
381
- await this._signalMessaging.signal({
383
+ await this._signalMessaging.signal(ctx, {
382
384
  author: this.localInfo,
383
385
  recipient: this.remoteInfo,
384
386
  sessionId: this.sessionId,
@@ -397,14 +399,14 @@ export class Connection {
397
399
 
398
400
  // If signal fails treat connection as failed
399
401
  log.info('signal message failed to deliver', { err });
400
- await this.close({ error: new ConnectivityError('signal message failed to deliver', err) });
402
+ await this.close({ error: new ConnectivityError({ message: 'signal message failed to deliver', cause: err }) });
401
403
  }
402
404
  }
403
405
 
404
406
  /**
405
407
  * Receive a signal from the remote peer.
406
408
  */
407
- async signal(msg: SignalMessage): Promise<void> {
409
+ async signal(_ctx: Context, msg: SignalMessage): Promise<void> {
408
410
  invariant(msg.sessionId);
409
411
  if (!msg.sessionId.equals(this.sessionId)) {
410
412
  log('dropping signal for incorrect session id');
package/src/swarm/peer.ts CHANGED
@@ -11,15 +11,16 @@ import { type PeerInfo } from '@dxos/messaging';
11
11
  import { CancelledError, SystemError } from '@dxos/protocols';
12
12
  import { type Answer } from '@dxos/protocols/proto/dxos/mesh/swarm';
13
13
 
14
- import { Connection, ConnectionState } from './connection';
15
- import { type ConnectionLimiter } from './connection-limiter';
16
14
  import { type OfferMessage, type SignalMessage, type SignalMessenger } from '../signal';
17
15
  import { type TransportFactory } from '../transport';
18
16
  import { type WireProtocolProvider } from '../wire-protocol';
19
17
 
18
+ import { Connection, ConnectionState } from './connection';
19
+ import { type ConnectionLimiter } from './connection-limiter';
20
+
20
21
  export class ConnectionDisplacedError extends SystemError {
21
22
  constructor() {
22
- super('Connection displaced by remote initiator.');
23
+ super({ message: 'Connection displaced by remote initiator.' });
23
24
  }
24
25
  }
25
26
 
@@ -105,7 +106,7 @@ export class Peer {
105
106
  /**
106
107
  * Respond to remote offer.
107
108
  */
108
- async onOffer(message: OfferMessage): Promise<Answer> {
109
+ async onOffer(_ctx: Context, message: OfferMessage): Promise<Answer> {
109
110
  const remote = message.author;
110
111
 
111
112
  if (
@@ -161,13 +162,14 @@ export class Peer {
161
162
  return { accept: true };
162
163
  }
163
164
  }
165
+
164
166
  return { accept: false };
165
167
  }
166
168
 
167
169
  /**
168
170
  * Initiate a connection to the remote peer.
169
171
  */
170
- async initiateConnection(): Promise<void> {
172
+ async initiateConnection(ctx: Context): Promise<void> {
171
173
  invariant(!this.initiating, 'Initiation in progress.');
172
174
  invariant(!this.connection, 'Already connected.');
173
175
  const sessionId = PublicKey.random();
@@ -181,7 +183,7 @@ export class Peer {
181
183
  await this._connectionLimiter.connecting(sessionId);
182
184
  connection.initiate();
183
185
 
184
- answer = await this._signalMessaging.offer({
186
+ answer = await this._signalMessaging.offer(ctx, {
185
187
  author: this.localInfo,
186
188
  recipient: this.remoteInfo,
187
189
  sessionId,
@@ -376,13 +378,13 @@ export class Peer {
376
378
  log('closed', { peerId: this.remoteInfo, sessionId: connection.sessionId });
377
379
  }
378
380
 
379
- async onSignal(message: SignalMessage): Promise<void> {
381
+ async onSignal(ctx: Context, message: SignalMessage): Promise<void> {
380
382
  if (!this.connection) {
381
383
  log('dropping signal message for non-existent connection', { message });
382
384
  return;
383
385
  }
384
386
 
385
- await this.connection.signal(message);
387
+ await this.connection.signal(ctx, message);
386
388
  }
387
389
 
388
390
  @synchronized
@@ -5,7 +5,7 @@
5
5
  import { type CleanupFn, Event, SubscriptionList } from '@dxos/async';
6
6
  import { PublicKey } from '@dxos/keys';
7
7
  import { log } from '@dxos/log';
8
- import { PeerInfoHash, type PeerInfo as MessagingPeer } from '@dxos/messaging';
8
+ import { type PeerInfo as MessagingPeer, PeerInfoHash } from '@dxos/messaging';
9
9
  import { ComplexMap } from '@dxos/util';
10
10
 
11
11
  import { type ConnectionState } from './connection';
@@ -2,7 +2,7 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import { onTestFinished, describe, expect, test } from 'vitest';
5
+ import { describe, expect, onTestFinished, test } from 'vitest';
6
6
 
7
7
  import { asyncTimeout, sleep } from '@dxos/async';
8
8
  import { PublicKey } from '@dxos/keys';
@@ -15,13 +15,14 @@ import {
15
15
  } from '@dxos/messaging';
16
16
  import { ComplexSet } from '@dxos/util';
17
17
 
18
- import { ConnectionState } from './connection';
19
- import { ConnectionLimiter } from './connection-limiter';
20
- import { Swarm } from './swarm';
21
18
  import { TestWireProtocol } from '../testing/test-wire-protocol';
22
19
  import { FullyConnectedTopology } from '../topology';
23
20
  import { createRtcTransportFactory } from '../transport';
24
21
 
22
+ import { ConnectionState } from './connection';
23
+ import { ConnectionLimiter } from './connection-limiter';
24
+ import { Swarm } from './swarm';
25
+
25
26
  type TestPeer = {
26
27
  swarm: Swarm;
27
28
  peer: PeerInfo;
@@ -30,7 +31,8 @@ type TestPeer = {
30
31
  signalManager: SignalManager;
31
32
  };
32
33
 
33
- describe('Swarm', () => {
34
+ // Segfault in node-datachannel.
35
+ describe.skip('Swarm', () => {
34
36
  const context = new MemorySignalManagerContext();
35
37
 
36
38
  const setupSwarm = async ({
@@ -157,9 +159,9 @@ describe('Swarm', () => {
157
159
  const messages = new ComplexSet<{ author: PeerInfo; recipient: PeerInfo }>(
158
160
  ({ author, recipient }) => author.peerKey + recipient.peerKey,
159
161
  );
160
- signalManager.sendMessage = async (message) => {
162
+ signalManager.sendMessage = async (ctx, message) => {
161
163
  messages.add({ author: message.author, recipient: message.recipient });
162
- return sendOriginal(message);
164
+ return sendOriginal(ctx, message);
163
165
  };
164
166
  // Stop signaling to stop connection in initiation state.
165
167
  signalManager.freeze();
@@ -8,20 +8,21 @@ import { ErrorStream } from '@dxos/debug';
8
8
  import { invariant } from '@dxos/invariant';
9
9
  import { PublicKey } from '@dxos/keys';
10
10
  import { log, logInfo } from '@dxos/log';
11
- import { type SwarmEvent, type ListeningHandle, type Messenger, type PeerInfo, PeerInfoHash } from '@dxos/messaging';
11
+ import { type ListeningHandle, type Messenger, type PeerInfo, PeerInfoHash, type SwarmEvent } from '@dxos/messaging';
12
12
  import { trace } from '@dxos/protocols';
13
13
  import { type Answer } from '@dxos/protocols/proto/dxos/mesh/swarm';
14
14
  import { ComplexMap, isNonNullable } from '@dxos/util';
15
15
 
16
- import { type Connection, ConnectionState } from './connection';
17
- import { type ConnectionLimiter } from './connection-limiter';
18
- import { Peer } from './peer';
19
16
  import { type OfferMessage, type SignalMessage, SwarmMessenger } from '../signal';
20
17
  import { type SwarmController, type Topology } from '../topology';
21
18
  import { type TransportFactory } from '../transport';
22
19
  import { type Topic } from '../types';
23
20
  import { type WireProtocolProvider } from '../wire-protocol';
24
21
 
22
+ import { type Connection, ConnectionState } from './connection';
23
+ import { type ConnectionLimiter } from './connection-limiter';
24
+ import { Peer } from './peer';
25
+
25
26
  const INITIATION_DELAY = 100;
26
27
 
27
28
  // TODO(burdon): Factor out.
@@ -93,9 +94,9 @@ export class Swarm {
93
94
  _topology.init(this._getSwarmController());
94
95
 
95
96
  this._swarmMessenger = new SwarmMessenger({
96
- sendMessage: async (msg) => await this._messenger.sendMessage(msg),
97
- onSignal: async (msg) => await this.onSignal(msg),
98
- onOffer: async (msg) => await this.onOffer(msg),
97
+ sendMessage: async (ctx, msg) => await this._messenger.sendMessage(ctx, msg),
98
+ onSignal: async (ctx, msg) => await this.onSignal(ctx, msg),
99
+ onOffer: async (ctx, msg) => await this.onOffer(ctx, msg),
99
100
  topic: this._topic,
100
101
  });
101
102
  log.trace('dxos.mesh.swarm.constructor', trace.end({ id: this._instanceId }));
@@ -135,7 +136,7 @@ export class Swarm {
135
136
  payloadType: 'dxos.mesh.swarm.SwarmMessage',
136
137
  onMessage: async (message) => {
137
138
  await this._swarmMessenger
138
- .receiveMessage(message)
139
+ .receiveMessage(this._ctx, message)
139
140
  // TODO(nf): discriminate between errors
140
141
  .catch((err) => log.info('Error while receiving message', { err }));
141
142
  },
@@ -204,7 +205,7 @@ export class Swarm {
204
205
  }
205
206
 
206
207
  @synchronized
207
- async onOffer(message: OfferMessage): Promise<Answer> {
208
+ async onOffer(ctx: Context, message: OfferMessage): Promise<Answer> {
208
209
  log('offer', { message });
209
210
  if (this._ctx.disposed) {
210
211
  log('ignored for disposed swarm');
@@ -223,7 +224,7 @@ export class Swarm {
223
224
  }
224
225
 
225
226
  const peer = this._getOfferSenderPeer(message.author);
226
- const answer = await peer.onOffer(message);
227
+ const answer = await peer.onOffer(ctx, message);
227
228
  this._topology.update();
228
229
  return answer;
229
230
  }
@@ -242,7 +243,7 @@ export class Swarm {
242
243
  return peer;
243
244
  }
244
245
 
245
- async onSignal(message: SignalMessage): Promise<void> {
246
+ async onSignal(ctx: Context, message: SignalMessage): Promise<void> {
246
247
  log('signal', { message });
247
248
  if (this._ctx.disposed) {
248
249
  log.info('ignored for offline swarm');
@@ -256,7 +257,7 @@ export class Swarm {
256
257
  invariant(message.author);
257
258
 
258
259
  const peer = this._getOrCreatePeer(message.author);
259
- await peer.onSignal(message);
260
+ await peer.onSignal(ctx, message);
260
261
  }
261
262
 
262
263
  // For debug purposes
@@ -403,7 +404,7 @@ export class Swarm {
403
404
  }
404
405
 
405
406
  log('initiating connection...', { remotePeer });
406
- await peer.initiateConnection();
407
+ await peer.initiateConnection(ctx);
407
408
  this._topology.update();
408
409
  log('initiated', { remotePeer });
409
410
  }
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { PublicKey } from '@dxos/keys';
6
6
  import { log } from '@dxos/log';
7
+ import { Context } from '@dxos/context';
7
8
  import {
8
9
  MemorySignalManager,
9
10
  MemorySignalManagerContext,
@@ -13,16 +14,23 @@ import {
13
14
  import { schema } from '@dxos/protocols/proto';
14
15
  import { ConnectionState } from '@dxos/protocols/proto/dxos/client/services';
15
16
  import { type Runtime } from '@dxos/protocols/proto/dxos/config';
16
- import { createLinkedPorts, createProtoRpcPeer, type ProtoRpcPeer } from '@dxos/rpc';
17
+ import { type ProtoRpcPeer, createLinkedPorts, createProtoRpcPeer } from '@dxos/rpc';
17
18
  import { ComplexMap } from '@dxos/util';
18
19
 
19
20
  import { TcpTransportFactory } from '#tcp-transport';
20
21
 
21
- import { type TestTeleportExtensionFactory, TestWireProtocol } from './test-wire-protocol';
22
22
  import { SwarmNetworkManager } from '../network-manager';
23
23
  import { FullyConnectedTopology } from '../topology';
24
- import { MemoryTransportFactory, type TransportFactory, TransportKind } from '../transport';
25
- import { createRtcTransportFactory, RtcTransportProxyFactory, RtcTransportService } from '../transport';
24
+ import {
25
+ MemoryTransportFactory,
26
+ RtcTransportProxyFactory,
27
+ RtcTransportService,
28
+ type TransportFactory,
29
+ TransportKind,
30
+ createRtcTransportFactory,
31
+ } from '../transport';
32
+
33
+ import { type TestTeleportExtensionFactory, TestWireProtocol } from './test-wire-protocol';
26
34
 
27
35
  // Signal server will be started by the setup script.
28
36
  const port = process.env.SIGNAL_PORT ?? 4000;
@@ -162,7 +170,7 @@ export class TestPeer {
162
170
 
163
171
  await this._proxy?.close();
164
172
  await this._service?.close();
165
- await this._networkManager.close();
173
+ await this._networkManager.close(Context.default());
166
174
  }
167
175
 
168
176
  getSwarm(topic: PublicKey): TestSwarmConnection {
@@ -211,7 +219,7 @@ export class TestSwarmConnection {
211
219
  // TODO(burdon): Need to create new plugin instance per swarm?
212
220
  // If so, then perhaps joinSwarm should return swarm object with access to plugins.
213
221
  async join(topology = new FullyConnectedTopology()): Promise<this> {
214
- await this.peer._networkManager.joinSwarm({
222
+ await this.peer._networkManager.joinSwarm(Context.default(), {
215
223
  topic: this.topic,
216
224
  peerInfo: { peerKey: this.peer.peerId.toHex(), identityKey: this.peer.peerId.toHex() },
217
225
  protocolProvider: this.protocol.factory,
@@ -222,7 +230,7 @@ export class TestSwarmConnection {
222
230
  }
223
231
 
224
232
  async leave(): Promise<this> {
225
- await this.peer._networkManager.leaveSwarm(this.topic);
233
+ await this.peer._networkManager.leaveSwarm(Context.default(), this.topic);
226
234
  return this;
227
235
  }
228
236
  }
@@ -2,11 +2,11 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { asyncTimeout, Event } from '@dxos/async';
5
+ import { Event, asyncTimeout } from '@dxos/async';
6
6
  import { PublicKey } from '@dxos/keys';
7
7
  import { log } from '@dxos/log';
8
8
  import { TestExtension, TestExtensionWithStreams } from '@dxos/teleport';
9
- import type { TestStreamStats, TeleportExtension } from '@dxos/teleport';
9
+ import type { TeleportExtension, TestStreamStats } from '@dxos/teleport';
10
10
  import { ComplexMap } from '@dxos/util';
11
11
 
12
12
  import { createTeleportProtocolFactory } from '../wire-protocol';
@@ -2,17 +2,18 @@
2
2
  // Copyright 2021 DXOS.org
3
3
  //
4
4
 
5
- import { onTestFinished, expect, test } from 'vitest';
5
+ import { expect, onTestFinished, test } from 'vitest';
6
6
 
7
7
  import { asyncTimeout } from '@dxos/async';
8
8
  import { PublicKey } from '@dxos/keys';
9
9
  import { log } from '@dxos/log';
10
10
  import { range } from '@dxos/util';
11
11
 
12
- import { exchangeMessages, joinSwarm, leaveSwarm, openAndCloseAfterTest } from './utils';
13
12
  import { type TestBuilder } from '../testing';
14
13
  import { FullyConnectedTopology, StarTopology } from '../topology';
15
14
 
15
+ import { exchangeMessages, joinSwarm, leaveSwarm, openAndCloseAfterTest } from './utils';
16
+
16
17
  // TODO(burdon): Use PublicKey throughout (remove conversion to strings, from buffers, etc.)
17
18
 
18
19
  /**