@dxos/network-manager 0.1.21 → 0.1.23

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.
@@ -22,7 +22,6 @@ export declare class Swarm {
22
22
  private readonly _messenger;
23
23
  private readonly _transportFactory;
24
24
  private readonly _label;
25
- private readonly _peers;
26
25
  private readonly _swarmMessenger;
27
26
  private _ctx;
28
27
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"swarm.d.ts","sourceRoot":"","sources":["../../../../src/swarm/swarm.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAG/D,OAAO,EAAiB,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAmB,QAAQ,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAmB,MAAM,cAAc,CAAC;AAQ3D;;;;GAIG;AACH,qBAAa,KAAK;IAqCd,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM;IA1CzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmD;IAE1E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgB;IAEhD,OAAO,CAAC,IAAI,CAAiB;IAE7B;;OAEG;IAEH,QAAQ,CAAC,UAAU,YAAsB;IAoBzC,QAAQ,CAAC,MAAM,cAAqB;gBAMjB,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,SAAS,EAC9B,SAAS,EAAE,QAAQ,EACV,iBAAiB,EAAE,oBAAoB,EACvC,UAAU,EAAE,SAAS,EACrB,iBAAiB,EAAE,gBAAgB,EACnC,MAAM,EAAE,MAAM,GAAG,SAAS;IAqB7C,IAAI,WAAW,iBAId;IAED,IACI,SAAS,cAEZ;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAE9B;IAED,IACI,KAAK,IAAI,KAAK,CAEjB;IAGK,OAAO;IAQP,WAAW,CAAC,QAAQ,EAAE,QAAQ;IAiBpC,YAAY,CAAC,UAAU,EAAE,UAAU;IA6B7B,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAwB/C,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB/C,SAAS;IAUT,QAAQ;IASd,OAAO,CAAC,gBAAgB;YA8CV,YAAY;IAM1B,OAAO,CAAC,mBAAmB;IAuC3B;;OAEG;YACW,mBAAmB;YAwBnB,gBAAgB;CAQ/B"}
1
+ {"version":3,"file":"swarm.d.ts","sourceRoot":"","sources":["../../../../src/swarm/swarm.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAG/D,OAAO,EAAiB,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAmB,QAAQ,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAmB,MAAM,cAAc,CAAC;AAQ3D;;;;GAIG;AACH,qBAAa,KAAK;IAwCd,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAxCzB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgB;IAEhD,OAAO,CAAC,IAAI,CAAiB;IAE7B;;OAEG;IAEH,QAAQ,CAAC,UAAU,YAAsB;IAoBzC,QAAQ,CAAC,MAAM,cAAqB;gBAMjB,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,SAAS,EAC9B,SAAS,EAAE,QAAQ,EACV,iBAAiB,EAAE,oBAAoB,EACvC,UAAU,EAAE,SAAS,EACrB,iBAAiB,EAAE,gBAAgB,EACnC,MAAM,EAAE,MAAM,GAAG,SAAS;IAqB7C,IAAI,WAAW,iBAId;IAED,IACI,SAAS,cAEZ;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAE9B;IAED,IACI,KAAK,IAAI,KAAK,CAEjB;IAGK,OAAO;IAQP,WAAW,CAAC,QAAQ,EAAE,QAAQ;IAiBpC,YAAY,CAAC,UAAU,EAAE,UAAU;IA8B7B,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAyB/C,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB/C,SAAS;IAOT,QAAQ;IAId,OAAO,CAAC,gBAAgB;YA8CV,YAAY;IAM1B,OAAO,CAAC,mBAAmB;IAuC3B;;OAEG;YACW,mBAAmB;YA0BnB,gBAAgB;CAQ/B"}
@@ -1 +1 @@
1
- {"version":3,"file":"test-wire-protocol.d.ts","sourceRoot":"","sources":["../../../../src/testing/test-wire-protocol.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC,qBAAa,gBAAgB;aAIC,MAAM,EAAE,SAAS;IAH7C,SAAgB,WAAW,uCAA4D;IACvF,SAAgB,SAAS,mBAA0B;gBAEvB,MAAM,EAAE,SAAS;IAE7C,QAAQ,CAAC,OAAO,kDAUb;IAEG,iBAAiB,CAAC,MAAM,EAAE,SAAS;IASnC,cAAc,CAAC,MAAM,EAAE,SAAS;CAIvC"}
1
+ {"version":3,"file":"test-wire-protocol.d.ts","sourceRoot":"","sources":["../../../../src/testing/test-wire-protocol.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,KAAK,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC,qBAAa,gBAAgB;aAIC,MAAM,EAAE,SAAS;IAH7C,SAAgB,WAAW,uCAA4D;IACvF,SAAgB,SAAS,mBAA0B;gBAEvB,MAAM,EAAE,SAAS;IAE7C,QAAQ,CAAC,OAAO,kDAUb;IAEG,iBAAiB,CAAC,MAAM,EAAE,SAAS;IAYnC,cAAc,CAAC,MAAM,EAAE,SAAS;CAIvC"}
@@ -1 +1 @@
1
- {"version":3,"file":"basic-test-suite.d.ts","sourceRoot":"","sources":["../../../../src/tests/basic-test-suite.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAMzC;;GAEG;AACH,eAAO,MAAM,cAAc,gBAAiB,WAAW,6BAuItD,CAAC"}
1
+ {"version":3,"file":"basic-test-suite.d.ts","sourceRoot":"","sources":["../../../../src/tests/basic-test-suite.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAMzC;;GAEG;AACH,eAAO,MAAM,cAAc,gBAAiB,WAAW,6BA8JtD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/network-manager",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "Network Manager",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -25,20 +25,20 @@
25
25
  "simple-peer": "9.11.0",
26
26
  "ws": "^7.4.4",
27
27
  "xor-distance": "^2.0.0",
28
- "@dxos/async": "0.1.21",
29
- "@dxos/codec-protobuf": "0.1.21",
30
- "@dxos/context": "0.1.21",
31
- "@dxos/credentials": "0.1.21",
32
- "@dxos/crypto": "0.1.21",
33
- "@dxos/debug": "0.1.21",
34
- "@dxos/keys": "0.1.21",
35
- "@dxos/log": "0.1.21",
36
- "@dxos/messaging": "0.1.21",
37
- "@dxos/node-std": "0.1.21",
38
- "@dxos/protocols": "0.1.21",
39
- "@dxos/rpc": "0.1.21",
40
- "@dxos/teleport": "0.1.21",
41
- "@dxos/util": "0.1.21"
28
+ "@dxos/async": "0.1.23",
29
+ "@dxos/codec-protobuf": "0.1.23",
30
+ "@dxos/context": "0.1.23",
31
+ "@dxos/credentials": "0.1.23",
32
+ "@dxos/crypto": "0.1.23",
33
+ "@dxos/debug": "0.1.23",
34
+ "@dxos/keys": "0.1.23",
35
+ "@dxos/log": "0.1.23",
36
+ "@dxos/messaging": "0.1.23",
37
+ "@dxos/node-std": "0.1.23",
38
+ "@dxos/protocols": "0.1.23",
39
+ "@dxos/rpc": "0.1.23",
40
+ "@dxos/teleport": "0.1.23",
41
+ "@dxos/util": "0.1.23"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@swc-node/register": "^1.5.4",
@@ -48,7 +48,7 @@
48
48
  "earljs": "~0.1.10",
49
49
  "fast-check": "~3.3.0",
50
50
  "typescript": "^4.8.4",
51
- "@dxos/signal": "0.1.21"
51
+ "@dxos/signal": "0.1.23"
52
52
  },
53
53
  "publishConfig": {
54
54
  "access": "public"
@@ -213,17 +213,17 @@ export class NetworkManager {
213
213
  case ConnectionState.OFFLINE: {
214
214
  this._connectionState = state;
215
215
  // go offline
216
+ await Promise.all([...this._swarms.values()].map((swarm) => swarm.goOffline()));
216
217
  await this._messenger.close();
217
218
  await this._signalManager.close();
218
- await Promise.all([...this._swarms.values()].map((swarm) => swarm.goOffline()));
219
219
  break;
220
220
  }
221
221
  case ConnectionState.ONLINE: {
222
222
  this._connectionState = state;
223
223
  // go online
224
+ await Promise.all([...this._swarms.values()].map((swarm) => swarm.goOnline()));
224
225
  this._messenger.open();
225
226
  await this._signalManager.open();
226
- await Promise.all([...this._swarms.values()].map((swarm) => swarm.goOnline()));
227
227
  break;
228
228
  }
229
229
  }
@@ -33,7 +33,10 @@ const getClassName = (obj: any) => Object.getPrototypeOf(obj).constructor.name;
33
33
  * Routes signal events and maintains swarm topology.
34
34
  */
35
35
  export class Swarm {
36
- private readonly _peers = new ComplexMap<PublicKey, Peer>(PublicKey.hash);
36
+ /**
37
+ * @internal
38
+ */
39
+ readonly _peers = new ComplexMap<PublicKey, Peer>(PublicKey.hash);
37
40
 
38
41
  private readonly _swarmMessenger: MessageRouter;
39
42
 
@@ -148,11 +151,12 @@ export class Swarm {
148
151
  onSwarmEvent(swarmEvent: SwarmEvent) {
149
152
  log('swarm event', { swarmEvent }); // TODO(burdon): Stringify.
150
153
 
154
+ if (this._ctx.disposed) {
155
+ log.warn('ignored for offline swarm');
156
+ return;
157
+ }
158
+
151
159
  if (swarmEvent.peerAvailable) {
152
- if (this._ctx.disposed) {
153
- log.warn('ignored for offline swarm');
154
- return;
155
- }
156
160
  const peerId = PublicKey.from(swarmEvent.peerAvailable.peer);
157
161
  log('new peer', { peerId });
158
162
  if (!peerId.equals(this._ownPeerId)) {
@@ -163,7 +167,7 @@ export class Swarm {
163
167
  const peer = this._peers.get(PublicKey.from(swarmEvent.peerLeft.peer));
164
168
  if (peer) {
165
169
  peer.advertizing = false;
166
- if (!peer.connection || peer.connection.state !== ConnectionState.CONNECTED) {
170
+ if (peer.connection?.state !== ConnectionState.CONNECTED) {
167
171
  // Destroy peer only if there is no p2p-connection established
168
172
  void this._destroyPeer(peer.id).catch((err) => log.catch(err));
169
173
  }
@@ -198,6 +202,7 @@ export class Swarm {
198
202
  return answer;
199
203
  }
200
204
 
205
+ @synchronized
201
206
  async onSignal(message: SignalMessage): Promise<void> {
202
207
  log('signal', { message });
203
208
  if (this._ctx.disposed) {
@@ -216,23 +221,16 @@ export class Swarm {
216
221
  }
217
222
 
218
223
  // For debug purposes
224
+ @synchronized
219
225
  async goOffline() {
220
226
  await this._ctx.dispose();
221
- [...this._peers.values()].forEach((peer) => {
222
- peer.advertizing = false;
223
- });
224
- await Promise.all([...this._peers.keys()].map((peerId) => this._closeConnection(peerId)));
227
+ await Promise.all([...this._peers.keys()].map((peerId) => this._destroyPeer(peerId)));
225
228
  }
226
229
 
227
230
  // For debug purposes
228
231
  @synchronized
229
232
  async goOnline() {
230
233
  this._ctx = new Context();
231
-
232
- [...this._peers.values()].forEach((peer) => {
233
- peer.advertizing = true;
234
- });
235
- this._topology.update();
236
234
  }
237
235
 
238
236
  private _getOrCreatePeer(peerId: PublicKey): Peer {
@@ -330,13 +328,15 @@ export class Swarm {
330
328
  * Creates a connection then sends message over signal network.
331
329
  */
332
330
  private async _initiateConnection(remoteId: PublicKey) {
331
+ const ctx = this._ctx; // Copy to avoid getting reset while sleeping.
332
+
333
333
  // It is likely that the other peer will also try to connect to us at the same time.
334
334
  // If our peerId is higher, we will wait for a bit so that other peer has a chance to connect first.
335
335
  if (remoteId.toHex() < this._ownPeerId.toHex()) {
336
336
  log('initiation delay', { remoteId });
337
337
  await sleep(INITIATION_DELAY);
338
338
  }
339
- if (this._ctx.disposed) {
339
+ if (ctx.disposed) {
340
340
  return;
341
341
  }
342
342
 
@@ -2,7 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import { Event } from '@dxos/async';
5
+ import { asyncTimeout, Event } from '@dxos/async';
6
6
  import { PublicKey } from '@dxos/keys';
7
7
  import { log } from '@dxos/log';
8
8
  import { TestExtension } from '@dxos/teleport';
@@ -33,7 +33,10 @@ export class TestWireProtocol {
33
33
  return this.connections.get(peerId)!;
34
34
  }
35
35
  log('waitForConnection', { peerId });
36
- await this.connected.waitFor((connectedId) => connectedId.equals(peerId));
36
+ await asyncTimeout(
37
+ this.connected.waitFor((connectedId) => connectedId.equals(peerId)),
38
+ 1_000
39
+ );
37
40
  return this.connections.get(peerId)!;
38
41
  }
39
42
 
@@ -3,6 +3,7 @@
3
3
  //
4
4
 
5
5
  import { expect } from 'chai';
6
+ import waitForExpect from 'wait-for-expect';
6
7
 
7
8
  import { PublicKey } from '@dxos/keys';
8
9
  import { log } from '@dxos/log';
@@ -109,27 +110,50 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
109
110
  ]);
110
111
  });
111
112
 
112
- test('going offline and back online', async () => {
113
- const peer1 = testBuilder.createPeer();
114
- const peer2 = testBuilder.createPeer();
115
- await openAndCloseAfterTest([peer1, peer2]);
113
+ // TODO(mykola): Flaky test because of test signal server.
114
+ test
115
+ .skip('going offline and back online', async () => {
116
+ const peer1 = testBuilder.createPeer();
117
+ const peer2 = testBuilder.createPeer();
118
+ await openAndCloseAfterTest([peer1, peer2]);
116
119
 
117
- const topic1 = PublicKey.random();
120
+ const topic = PublicKey.random();
118
121
 
119
- const [swarm1, swarm2] = await joinSwarm([peer1, peer2], topic1);
120
- await exchangeMessages(swarm1, swarm2);
122
+ const [swarm1, swarm2] = await joinSwarm([peer1, peer2], topic);
123
+ await exchangeMessages(swarm1, swarm2);
121
124
 
122
- //
123
- // Going offline and back online
124
- //
125
- const peerLeft = peer2._networkManager.signalManager.swarmEvent.waitFor((event) => !!event.swarmEvent.peerLeft);
126
- await peer1.goOffline();
127
- await peerLeft;
128
- await peer1.goOnline();
125
+ //
126
+ // Going offline and back online
127
+ //
128
+ const connectionDropped = peer2._networkManager
129
+ .getSwarm(topic)
130
+ ?.disconnected.waitFor((peerId) => peerId.equals(peer1.peerId));
129
131
 
130
- await exchangeMessages(swarm1, swarm2);
131
- await leaveSwarm([peer1, peer2], topic1);
132
- }).timeout(2_000);
132
+ const peerLeft = peer2._networkManager.signalManager.swarmEvent.waitFor(
133
+ (event) => !!event.swarmEvent.peerLeft && peer1.peerId.equals(event.swarmEvent.peerLeft?.peer)
134
+ );
135
+
136
+ await peer1.goOffline();
137
+ await connectionDropped;
138
+ await peerLeft;
139
+
140
+ // Wait for peer to be removed from the swarm.
141
+ await waitForExpect(() => {
142
+ expect(!!peer2._networkManager.getSwarm(topic)!._peers.get(peer1.peerId)?.advertizing).to.be.false;
143
+ }, 1_000);
144
+
145
+ await peer1.goOnline();
146
+
147
+ await waitForExpect(() => {
148
+ expect(peer1._networkManager.getSwarm(topic)?._peers.get(peer2.peerId)?.advertizing).to.be.true;
149
+
150
+ expect(peer2._networkManager.getSwarm(topic)?._peers.get(peer1.peerId)?.advertizing).to.be.true;
151
+ }, 2_000);
152
+
153
+ await exchangeMessages(swarm1, swarm2);
154
+ await leaveSwarm([peer1, peer2], topic);
155
+ })
156
+ .timeout(2_000);
133
157
 
134
158
  // TODO(mykola): broken.
135
159
  test.skip('many peers and connections', async () => {
@@ -10,10 +10,7 @@ describe('WebRTC transport', () => {
10
10
  basicTestSuite(testBuilder);
11
11
  }).timeout(10_000);
12
12
 
13
- /*
14
- // TODO(burdon): Flaky.
15
13
  describe('WebRTC transport proxy', () => {
16
14
  const testBuilder = new TestBuilder({ signalHosts: [TEST_SIGNAL_URL], bridge: true });
17
15
  basicTestSuite(testBuilder);
18
16
  }).timeout(10_000);
19
- */