@dxos/network-manager 2.31.7-dev.3c7d6556 → 2.31.8-dev.613ef955

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.
@@ -276,6 +276,8 @@ export function inMemoryTests () {
276
276
  peers: ComplexSet<PublicKey>
277
277
  joinedPeers: ComplexSet<PublicKey>
278
278
  }
279
+
280
+ // TODO(burdon): Name?
279
281
  interface Real {
280
282
  peers: ComplexMap<PublicKey, {
281
283
  networkManager: NetworkManager
@@ -283,11 +285,11 @@ export function inMemoryTests () {
283
285
  }>
284
286
  }
285
287
 
286
- async function assertState (m: Model, r: Real) {
288
+ async function assertState (model: Model, real: Real) {
287
289
  await waitForExpect(() => {
288
- for (const peer of r.peers.values()) {
290
+ for (const peer of real.peers.values()) {
289
291
  if (peer.presence) {
290
- for (const expectedJoinedPeer of m.joinedPeers) {
292
+ for (const expectedJoinedPeer of model.joinedPeers) {
291
293
  if (expectedJoinedPeer.equals(peer.presence.peerId)) {
292
294
  continue;
293
295
  }
@@ -301,7 +303,7 @@ export function inMemoryTests () {
301
303
  }
302
304
  }, 5_000);
303
305
 
304
- r.peers.forEach(peer => peer.networkManager.topics.forEach(topic => {
306
+ real.peers.forEach(peer => peer.networkManager.topics.forEach(topic => {
305
307
  peer.networkManager.getSwarm(topic)!.errors.assertNoUnhandledErrors();
306
308
  }));
307
309
  }
@@ -309,19 +311,19 @@ export function inMemoryTests () {
309
311
  class CreatePeerCommand implements fc.AsyncCommand<Model, Real> {
310
312
  constructor (readonly peerId: PublicKey) {}
311
313
 
312
- check = (m: Model) => !m.peers.has(this.peerId);
314
+ check = (model: Model) => !model.peers.has(this.peerId);
313
315
 
314
- async run (m: Model, r: Real) {
315
- m.peers.add(this.peerId);
316
+ async run (model: Model, real: Real) {
317
+ model.peers.add(this.peerId);
316
318
 
317
319
  const networkManager = new NetworkManager();
318
320
  afterTest(() => networkManager.destroy());
319
321
 
320
- r.peers.set(this.peerId, {
322
+ real.peers.set(this.peerId, {
321
323
  networkManager
322
324
  });
323
325
 
324
- await assertState(m, r);
326
+ await assertState(model, real);
325
327
  }
326
328
 
327
329
  toString = () => `CreatePeer(${this.peerId})`;
@@ -330,17 +332,17 @@ export function inMemoryTests () {
330
332
  class RemovePeerCommand implements fc.AsyncCommand<Model, Real> {
331
333
  constructor (readonly peerId: PublicKey) {}
332
334
 
333
- check = (m: Model) => m.peers.has(this.peerId);
335
+ check = (model: Model) => model.peers.has(this.peerId);
334
336
 
335
- async run (m: Model, r: Real) {
336
- m.peers.delete(this.peerId);
337
- m.joinedPeers.delete(this.peerId);
337
+ async run (model: Model, real: Real) {
338
+ model.peers.delete(this.peerId);
339
+ model.joinedPeers.delete(this.peerId);
338
340
 
339
- const peer = r.peers.get(this.peerId);
341
+ const peer = real.peers.get(this.peerId);
340
342
  await peer!.networkManager.destroy();
341
- r.peers.delete(this.peerId);
343
+ real.peers.delete(this.peerId);
342
344
 
343
- await assertState(m, r);
345
+ await assertState(model, real);
344
346
  }
345
347
 
346
348
  toString = () => `RemovePeer(${this.peerId})`;
@@ -349,22 +351,20 @@ export function inMemoryTests () {
349
351
  class JoinTopicCommand implements fc.AsyncCommand<Model, Real> {
350
352
  constructor (readonly peerId: PublicKey) {}
351
353
 
352
- check = (m: Model) =>
353
- m.peers.has(this.peerId) &&
354
- !m.joinedPeers.has(this.peerId);
354
+ check = (model: Model) => model.peers.has(this.peerId) && !model.joinedPeers.has(this.peerId);
355
355
 
356
- async run (m: Model, r: Real) {
357
- m.joinedPeers.add(this.peerId);
356
+ async run (model: Model, real: Real) {
357
+ model.joinedPeers.add(this.peerId);
358
358
 
359
- const peer = r.peers.get(this.peerId)!;
359
+ const peer = real.peers.get(this.peerId)!;
360
360
 
361
361
  const presence = new PresencePlugin(this.peerId.asBuffer());
362
362
  afterTest(() => presence.stop());
363
- const protocol = createProtocolFactory(m.topic, this.peerId, [presence]);
363
+ const protocol = createProtocolFactory(model.topic, this.peerId, [presence]);
364
364
 
365
365
  peer.networkManager.joinProtocolSwarm({
366
366
  peerId: this.peerId, // TODO(burdon): `this`?
367
- topic: m.topic,
367
+ topic: model.topic,
368
368
  protocol,
369
369
  topology: new FullyConnectedTopology(),
370
370
  presence
@@ -372,7 +372,7 @@ export function inMemoryTests () {
372
372
 
373
373
  peer.presence = presence;
374
374
 
375
- await assertState(m, r);
375
+ await assertState(model, real);
376
376
  }
377
377
 
378
378
  toString = () => `JoinTopic(peerId=${this.peerId})`;
@@ -381,19 +381,17 @@ export function inMemoryTests () {
381
381
  class LeaveTopicCommand implements fc.AsyncCommand<Model, Real> {
382
382
  constructor (readonly peerId: PublicKey) {}
383
383
 
384
- check = (m: Model) =>
385
- m.peers.has(this.peerId) &&
386
- m.joinedPeers.has(this.peerId);
384
+ check = (model: Model) => model.peers.has(this.peerId) && model.joinedPeers.has(this.peerId);
387
385
 
388
- async run (m: Model, r: Real) {
389
- m.joinedPeers.delete(this.peerId);
386
+ async run (model: Model, real: Real) {
387
+ model.joinedPeers.delete(this.peerId);
390
388
 
391
- const peer = r.peers.get(this.peerId)!;
389
+ const peer = real.peers.get(this.peerId)!;
392
390
 
393
- await peer.networkManager.leaveProtocolSwarm(m.topic);
391
+ await peer.networkManager.leaveProtocolSwarm(model.topic);
394
392
  peer.presence = undefined;
395
393
 
396
- await assertState(m, r);
394
+ await assertState(model, real);
397
395
  }
398
396
 
399
397
  toString = () => `LeaveTopic(peerId=${this.peerId})`;
@@ -35,35 +35,24 @@ const log = debug('dxos:network-manager');
35
35
  */
36
36
  export class NetworkManager {
37
37
  private readonly _ice?: any[];
38
- private readonly _swarms = new ComplexMap<PublicKey, Swarm>(x => x.toHex());
39
- private readonly _maps = new ComplexMap<PublicKey, SwarmMapper>(x => x.toHex());
38
+ private readonly _swarms = new ComplexMap<PublicKey, Swarm>(key => key.toHex());
39
+ private readonly _maps = new ComplexMap<PublicKey, SwarmMapper>(key => key.toHex());
40
40
  private readonly _signal: SignalManager;
41
41
  private readonly _connectionLog?: ConnectionLog;
42
42
 
43
43
  public readonly topicsUpdated = new Event<void>();
44
44
 
45
- get signal () {
46
- return this._signal;
47
- }
48
-
49
- get topics () {
50
- return Array.from(this._swarms.keys());
51
- }
52
-
53
- get connectionLog () {
54
- return this._connectionLog;
55
- }
56
-
57
45
  constructor (options: NetworkManagerOptions = {}) {
58
46
  this._ice = options.ice ?? [];
59
47
 
60
- const onOffer = async (msg: SignalApi.SignalMessage) => await this._swarms.get(msg.topic)?.onOffer(msg) ?? { accept: false };
61
-
48
+ const onOffer = async (message: SignalApi.SignalMessage) =>
49
+ await this._swarms.get(message.topic)?.onOffer(message) ?? { accept: false };
62
50
  this._signal = options.signal
63
51
  ? new WebsocketSignalManager(options.signal, onOffer)
64
52
  : new InMemorySignalManager(onOffer);
65
53
 
66
- this._signal.peerCandidatesChanged.on(([topic, candidates]) => this._swarms.get(topic)?.onPeerCandidatesChanged(candidates));
54
+ this._signal.peerCandidatesChanged.on(([topic, candidates]) =>
55
+ this._swarms.get(topic)?.onPeerCandidatesChanged(candidates));
67
56
  this._signal.onSignal.on(msg => this._swarms.get(msg.topic)?.onSignal(msg));
68
57
 
69
58
  if (options.log) {
@@ -71,6 +60,18 @@ export class NetworkManager {
71
60
  }
72
61
  }
73
62
 
63
+ get signal () {
64
+ return this._signal;
65
+ }
66
+
67
+ get topics () {
68
+ return Array.from(this._swarms.keys());
69
+ }
70
+
71
+ get connectionLog () {
72
+ return this._connectionLog;
73
+ }
74
+
74
75
  getSwarmMap (topic: PublicKey): SwarmMapper | undefined {
75
76
  return this._maps.get(topic);
76
77
  }
@@ -80,29 +81,36 @@ export class NetworkManager {
80
81
  }
81
82
 
82
83
  joinProtocolSwarm (options: SwarmOptions) {
84
+ // TODO(burdon): Use TS to constrain properties.
83
85
  assert(typeof options === 'object', 'Incorrect arguments format.');
84
86
  const { topic, peerId, topology, protocol, presence } = options;
85
87
  assert(PublicKey.isPublicKey(topic), 'Incorrect arguments format.');
86
88
  assert(PublicKey.isPublicKey(peerId), 'Incorrect arguments format.');
87
89
  assert(topology, 'Incorrect arguments format.');
88
90
  assert(typeof protocol === 'function', 'Incorrect arguments format.');
89
- log(`Join ${options.topic} as ${options.peerId} with ${options.topology.toString()} topology.`);
90
91
 
92
+ log(`Join ${options.topic} as ${options.peerId} with ${options.topology.toString()} topology.`);
91
93
  if (this._swarms.has(topic)) {
92
- throw new ERR_EXTENSION_RESPONSE_FAILED(GreetingCommandPlugin.EXTENSION_NAME, ERR_GREET_ALREADY_CONNECTED_TO_SWARM, `Already connected to swarm ${topic}`);
94
+ throw new ERR_EXTENSION_RESPONSE_FAILED(
95
+ GreetingCommandPlugin.EXTENSION_NAME, ERR_GREET_ALREADY_CONNECTED_TO_SWARM, `Already connected to swarm ${topic}`);
93
96
  }
94
97
 
98
+ // TODO(burdon): Bundle common transport related classes.
99
+ const transportFactory = this._signal instanceof InMemorySignalManager
100
+ ? inMemoryTransportFactory : createWebRtcTransportFactory({ iceServers: this._ice });
101
+
95
102
  const swarm = new Swarm(
96
103
  topic,
97
104
  peerId,
98
105
  topology,
99
106
  protocol,
107
+
108
+ // TODO(burdon): Merge.
100
109
  async offer => this._signal.offer(offer),
101
110
  async msg => this._signal.signal(msg),
102
- () => {
103
- this._signal.lookup(topic);
104
- },
105
- this._signal instanceof InMemorySignalManager ? inMemoryTransportFactory : createWebRtcTransportFactory({ iceServers: this._ice }),
111
+ () => this._signal.lookup(topic),
112
+
113
+ transportFactory,
106
114
  options.label
107
115
  );
108
116
 
@@ -144,10 +152,10 @@ export class NetworkManager {
144
152
  await this.topicsUpdated.emit();
145
153
  }
146
154
 
147
- // TODO(marik-d): Remove.
148
155
  /**
149
- * @default
156
+ * @deprecated
150
157
  */
158
+ // TODO(marik-d): Remove.
151
159
  async start () {
152
160
  console.warn('NetworkManger.start is deprecated.');
153
161
  }
@@ -159,6 +167,7 @@ export class NetworkManager {
159
167
  log(err);
160
168
  });
161
169
  }
170
+
162
171
  await this._signal.destroy();
163
172
  }
164
173
  }
@@ -57,6 +57,7 @@ export class Swarm {
57
57
 
58
58
  readonly errors = new ErrorStream();
59
59
 
60
+ // TODO(burdon): Split up properties.
60
61
  constructor (
61
62
  private readonly _topic: PublicKey,
62
63
  private readonly _ownPeerId: PublicKey,
@@ -32,6 +32,7 @@ function createPair () {
32
32
  topic,
33
33
  protocolProvider1({ channel: discoveryKey(topic), initiator: true }).stream
34
34
  );
35
+
35
36
  afterTest(() => connection1.close());
36
37
  afterTest(() => connection1.errors.assertNoUnhandledErrors());
37
38
 
@@ -44,6 +45,7 @@ function createPair () {
44
45
  topic,
45
46
  protocolProvider2({ channel: discoveryKey(topic), initiator: false }).stream
46
47
  );
48
+
47
49
  afterTest(() => connection2.close());
48
50
  afterTest(() => connection2.errors.assertNoUnhandledErrors());
49
51
 
@@ -16,17 +16,20 @@ import { Transport, TransportFactory } from './transport';
16
16
 
17
17
  const log = debug('dxos:network-manager:swarm:transport:in-memory-transport');
18
18
 
19
- type ConnectionKey = [topic: PublicKey, nodeId: PublicKey, remoteId: PublicKey];
19
+ type ConnectionKey = [topic: PublicKey, nodeId: PublicKey, remoteId: PublicKey]
20
20
 
21
21
  // Delay (in milliseconds) for data being sent through in-memory connections to simulate network latency.
22
22
  const IN_MEMORY_TRANSPORT_DELAY = 1;
23
23
 
24
+ // TODO(burdon): Rename.
24
25
  export class InMemoryTransport implements Transport {
25
- private static readonly _connections = new ComplexMap<ConnectionKey, InMemoryTransport>(([topic, nodeId, remoteId]) => topic.toHex() + nodeId.toHex() + remoteId.toHex());
26
+
27
+ // TODO(burdon): Remove global properties.
28
+ private static readonly _connections = new ComplexMap<ConnectionKey, InMemoryTransport>(
29
+ ([topic, nodeId, remoteId]) => topic.toHex() + nodeId.toHex() + remoteId.toHex());
26
30
 
27
31
  public readonly closed = new Event<void>();
28
32
  public readonly connected = new Event<void>();
29
-
30
33
  public readonly errors = new ErrorStream();
31
34
 
32
35
  private readonly _ownKey: ConnectionKey;
@@ -99,7 +102,6 @@ export class InMemoryTransport implements Transport {
99
102
  this._incomingDelay.unpipe();
100
103
 
101
104
  this._remoteConnection.closed.emit();
102
-
103
105
  this._remoteConnection._remoteConnection = undefined;
104
106
  this._remoteConnection = undefined;
105
107
  }
@@ -109,6 +111,7 @@ export class InMemoryTransport implements Transport {
109
111
  }
110
112
  }
111
113
 
114
+ // TODO(burdon): Remove.
112
115
  export const inMemoryTransportFactory: TransportFactory = opts => new InMemoryTransport(
113
116
  opts.ownId,
114
117
  opts.remoteId,
@@ -120,11 +123,11 @@ export const inMemoryTransportFactory: TransportFactory = opts => new InMemoryTr
120
123
  /**
121
124
  * Creates a binary stream that delays data being sent through the stream by the specified amount of time.
122
125
  */
123
- function createStreamDelay (delay: number): NodeJS.ReadWriteStream {
126
+ const createStreamDelay = (delay: number): NodeJS.ReadWriteStream => {
124
127
  return new Transform({
125
128
  objectMode: true,
126
129
  transform: (chunk, enc, cb) => {
127
130
  setTimeout(() => cb(null, chunk), delay);
128
131
  }
129
132
  });
130
- }
133
+ };
@@ -105,7 +105,7 @@ export class WebrtcTransport implements Transport {
105
105
  }
106
106
  }
107
107
 
108
- export function createWebRtcTransportFactory (webrtcConfig?: any): TransportFactory {
108
+ export const createWebRtcTransportFactory = (webrtcConfig?: any): TransportFactory => {
109
109
  return opts => new WebrtcTransport(
110
110
  opts.initiator,
111
111
  opts.stream,
@@ -116,4 +116,4 @@ export function createWebRtcTransportFactory (webrtcConfig?: any): TransportFact
116
116
  opts.sendSignal,
117
117
  webrtcConfig
118
118
  );
119
- }
119
+ };