@dxos/network-manager 0.6.8-main.3be982f → 0.6.8-staging.77f93a3
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.
- package/dist/lib/browser/{chunk-ZT4NXID2.mjs → chunk-ZQ4OU7JZ.mjs} +289 -251
- package/dist/lib/browser/chunk-ZQ4OU7JZ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +5 -2
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-DZJ3BJOK.cjs → chunk-IQBYIEAR.cjs} +294 -256
- package/dist/lib/node/chunk-IQBYIEAR.cjs.map +7 -0
- package/dist/lib/node/index.cjs +28 -28
- package/dist/lib/node/index.cjs.map +1 -1
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +22 -19
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/types/src/network-manager.d.ts +9 -6
- package/dist/types/src/network-manager.d.ts.map +1 -1
- package/dist/types/src/signal/signal-connection.d.ts +3 -2
- package/dist/types/src/signal/signal-connection.d.ts.map +1 -1
- package/dist/types/src/signal/signal-messenger.d.ts +5 -4
- package/dist/types/src/signal/signal-messenger.d.ts.map +1 -1
- package/dist/types/src/signal/swarm-messenger.d.ts +4 -7
- package/dist/types/src/signal/swarm-messenger.d.ts.map +1 -1
- package/dist/types/src/swarm/connection.d.ts +4 -4
- package/dist/types/src/swarm/connection.d.ts.map +1 -1
- package/dist/types/src/swarm/peer.d.ts +5 -4
- package/dist/types/src/swarm/peer.d.ts.map +1 -1
- package/dist/types/src/swarm/swarm-mapper.d.ts.map +1 -1
- package/dist/types/src/swarm/swarm.d.ts +4 -4
- package/dist/types/src/swarm/swarm.d.ts.map +1 -1
- package/dist/types/src/tests/basic-test-suite.d.ts.map +1 -1
- package/dist/types/src/tests/property-test-suite.d.ts.map +1 -1
- package/package.json +19 -18
- package/src/connection-log.ts +1 -1
- package/src/network-manager.ts +27 -13
- package/src/signal/integration.test.ts +25 -19
- package/src/signal/signal-connection.ts +3 -2
- package/src/signal/signal-messenger.ts +5 -4
- package/src/signal/swarm-messenger.test.ts +21 -21
- package/src/signal/swarm-messenger.ts +11 -10
- package/src/swarm/connection.test.ts +19 -17
- package/src/swarm/connection.ts +16 -15
- package/src/swarm/peer.ts +41 -35
- package/src/swarm/swarm-mapper.ts +7 -6
- package/src/swarm/swarm.test.ts +36 -28
- package/src/swarm/swarm.ts +57 -53
- package/src/testing/test-builder.ts +1 -1
- package/src/tests/basic-test-suite.ts +8 -5
- package/src/tests/property-test-suite.ts +4 -1
- package/dist/lib/browser/chunk-ZT4NXID2.mjs.map +0 -7
- package/dist/lib/node/chunk-DZJ3BJOK.cjs.map +0 -7
package/src/swarm/swarm.test.ts
CHANGED
|
@@ -6,7 +6,13 @@ import { expect } from 'chai';
|
|
|
6
6
|
|
|
7
7
|
import { asyncTimeout, sleep } from '@dxos/async';
|
|
8
8
|
import { PublicKey } from '@dxos/keys';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
MemorySignalManager,
|
|
11
|
+
MemorySignalManagerContext,
|
|
12
|
+
Messenger,
|
|
13
|
+
type PeerInfo,
|
|
14
|
+
type SignalManager,
|
|
15
|
+
} from '@dxos/messaging';
|
|
10
16
|
import { afterTest, describe, test } from '@dxos/test';
|
|
11
17
|
import { ComplexSet } from '@dxos/util';
|
|
12
18
|
|
|
@@ -19,7 +25,7 @@ import { createLibDataChannelTransportFactory, createSimplePeerTransportFactory
|
|
|
19
25
|
|
|
20
26
|
type TestPeer = {
|
|
21
27
|
swarm: Swarm;
|
|
22
|
-
|
|
28
|
+
peer: PeerInfo;
|
|
23
29
|
protocol: TestWireProtocol;
|
|
24
30
|
topic: PublicKey;
|
|
25
31
|
signalManager: SignalManager;
|
|
@@ -30,21 +36,21 @@ describe('Swarm', () => {
|
|
|
30
36
|
|
|
31
37
|
const setupSwarm = async ({
|
|
32
38
|
topic = PublicKey.random(),
|
|
33
|
-
|
|
39
|
+
peer = { peerKey: PublicKey.random().toHex() },
|
|
34
40
|
connectionLimiter = new ConnectionLimiter(),
|
|
35
41
|
signalManager = new MemorySignalManager(context),
|
|
36
42
|
initiationDelay = 100,
|
|
37
43
|
}: {
|
|
38
44
|
topic?: PublicKey;
|
|
39
|
-
|
|
45
|
+
peer?: PeerInfo;
|
|
40
46
|
connectionLimiter?: ConnectionLimiter;
|
|
41
47
|
signalManager?: SignalManager;
|
|
42
48
|
initiationDelay?: number;
|
|
43
49
|
}): Promise<TestPeer> => {
|
|
44
|
-
const protocol = new TestWireProtocol(
|
|
50
|
+
const protocol = new TestWireProtocol(PublicKey.from(peer.peerKey));
|
|
45
51
|
const swarm = new Swarm(
|
|
46
52
|
topic,
|
|
47
|
-
|
|
53
|
+
peer,
|
|
48
54
|
new FullyConnectedTopology(),
|
|
49
55
|
protocol.factory,
|
|
50
56
|
new Messenger({ signalManager }),
|
|
@@ -62,7 +68,7 @@ describe('Swarm', () => {
|
|
|
62
68
|
|
|
63
69
|
await swarm.open();
|
|
64
70
|
|
|
65
|
-
return { swarm, protocol, topic,
|
|
71
|
+
return { swarm, protocol, topic, peer, signalManager };
|
|
66
72
|
};
|
|
67
73
|
|
|
68
74
|
test('connects two peers in a swarm', async () => {
|
|
@@ -92,16 +98,16 @@ describe('Swarm', () => {
|
|
|
92
98
|
test('with simultaneous connections one of the peers drops initiated connection', async () => {
|
|
93
99
|
const topic = PublicKey.random();
|
|
94
100
|
|
|
95
|
-
const
|
|
96
|
-
const
|
|
101
|
+
const peerInfo1 = { peerKey: '39ba0e42' };
|
|
102
|
+
const peerInfo2 = { peerKey: '7d2bc6ab' };
|
|
97
103
|
|
|
98
|
-
const peer1 = await setupSwarm({
|
|
99
|
-
const peer2 = await setupSwarm({
|
|
104
|
+
const peer1 = await setupSwarm({ peer: peerInfo1, topic, initiationDelay: 0 });
|
|
105
|
+
const peer2 = await setupSwarm({ peer: peerInfo2, topic, initiationDelay: 0 });
|
|
100
106
|
|
|
101
107
|
expect(peer1.swarm.connections.length).to.equal(0);
|
|
102
108
|
expect(peer2.swarm.connections.length).to.equal(0);
|
|
103
109
|
|
|
104
|
-
const connectionDisplaced = peer2.swarm._peers.get(
|
|
110
|
+
const connectionDisplaced = peer2.swarm._peers.get(peerInfo1)?.connectionDisplaced.waitForCount(1);
|
|
105
111
|
|
|
106
112
|
await connectSwarms(peer1, peer2);
|
|
107
113
|
await asyncTimeout(connectionDisplaced!, 1000);
|
|
@@ -125,17 +131,17 @@ describe('Swarm', () => {
|
|
|
125
131
|
test('connection limiter', async () => {
|
|
126
132
|
// remotePeer1 <--> peer (connectionLimiter: max = 1) <--> remotePeer2
|
|
127
133
|
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
-
const
|
|
134
|
+
const localPeerInfo = { peerKey: '7701dc2d' };
|
|
135
|
+
const remotePeerInfo1 = { peerKey: '7d2bc6aa' };
|
|
136
|
+
const remotePeerInfo2 = { peerKey: '39ba0e41' };
|
|
131
137
|
|
|
132
138
|
const topic = PublicKey.random();
|
|
133
139
|
const connectionLimiter = new ConnectionLimiter({ maxConcurrentInitConnections: 1 });
|
|
134
140
|
|
|
135
141
|
const signalManager = new MemorySignalManager(context);
|
|
136
142
|
const sendOriginal = signalManager.sendMessage.bind(signalManager);
|
|
137
|
-
const messages = new ComplexSet<{ author:
|
|
138
|
-
({ author, recipient }) => author.
|
|
143
|
+
const messages = new ComplexSet<{ author: PeerInfo; recipient: PeerInfo }>(
|
|
144
|
+
({ author, recipient }) => author.peerKey + recipient.peerKey,
|
|
139
145
|
);
|
|
140
146
|
signalManager.sendMessage = async (message) => {
|
|
141
147
|
messages.add({ author: message.author, recipient: message.recipient });
|
|
@@ -146,12 +152,12 @@ describe('Swarm', () => {
|
|
|
146
152
|
|
|
147
153
|
const peer = await setupSwarm({
|
|
148
154
|
topic,
|
|
149
|
-
|
|
155
|
+
peer: localPeerInfo,
|
|
150
156
|
connectionLimiter,
|
|
151
157
|
signalManager,
|
|
152
158
|
});
|
|
153
|
-
const remotePeer1 = await setupSwarm({
|
|
154
|
-
const remotePeer2 = await setupSwarm({
|
|
159
|
+
const remotePeer1 = await setupSwarm({ peer: remotePeerInfo1, topic });
|
|
160
|
+
const remotePeer2 = await setupSwarm({ peer: remotePeerInfo2, topic });
|
|
155
161
|
|
|
156
162
|
let connected1: Promise<void>;
|
|
157
163
|
{
|
|
@@ -171,8 +177,8 @@ describe('Swarm', () => {
|
|
|
171
177
|
|
|
172
178
|
{
|
|
173
179
|
// Peer sent messages only to first remote peer.
|
|
174
|
-
expect(messages.has({ author:
|
|
175
|
-
expect(messages.has({ author:
|
|
180
|
+
expect(messages.has({ author: localPeerInfo, recipient: remotePeerInfo1 })).to.equal(true);
|
|
181
|
+
expect(messages.has({ author: localPeerInfo, recipient: remotePeerInfo2 })).to.equal(false);
|
|
176
182
|
}
|
|
177
183
|
|
|
178
184
|
signalManager.unfreeze();
|
|
@@ -186,8 +192,9 @@ const connectSwarms = async (peer1: TestPeer, peer2: TestPeer, delay = async ()
|
|
|
186
192
|
const connect2 = peer2.swarm.connected.waitForCount(1);
|
|
187
193
|
|
|
188
194
|
peer1.swarm.onSwarmEvent({
|
|
195
|
+
topic: peer2.topic,
|
|
189
196
|
peerAvailable: {
|
|
190
|
-
peer: peer2.
|
|
197
|
+
peer: peer2.peer,
|
|
191
198
|
since: new Date(),
|
|
192
199
|
},
|
|
193
200
|
});
|
|
@@ -195,15 +202,16 @@ const connectSwarms = async (peer1: TestPeer, peer2: TestPeer, delay = async ()
|
|
|
195
202
|
await delay();
|
|
196
203
|
|
|
197
204
|
peer2.swarm.onSwarmEvent({
|
|
205
|
+
topic: peer1.topic,
|
|
198
206
|
peerAvailable: {
|
|
199
|
-
peer: peer1.
|
|
207
|
+
peer: peer1.peer,
|
|
200
208
|
since: new Date(),
|
|
201
209
|
},
|
|
202
210
|
});
|
|
203
211
|
|
|
204
212
|
if (
|
|
205
213
|
!(
|
|
206
|
-
peer1.swarm.connections.find((connection) => connection.
|
|
214
|
+
peer1.swarm.connections.find((connection) => connection.remoteInfo.peerKey === peer2.peer.peerKey)?.state ===
|
|
207
215
|
ConnectionState.CONNECTED
|
|
208
216
|
)
|
|
209
217
|
) {
|
|
@@ -211,13 +219,13 @@ const connectSwarms = async (peer1: TestPeer, peer2: TestPeer, delay = async ()
|
|
|
211
219
|
}
|
|
212
220
|
if (
|
|
213
221
|
!(
|
|
214
|
-
peer2.swarm.connections.find((connection) => connection.
|
|
222
|
+
peer2.swarm.connections.find((connection) => connection.remoteInfo.peerKey === peer1.peer.peerKey)?.state ===
|
|
215
223
|
ConnectionState.CONNECTED
|
|
216
224
|
)
|
|
217
225
|
) {
|
|
218
226
|
await asyncTimeout(connect2, 3000);
|
|
219
227
|
}
|
|
220
228
|
|
|
221
|
-
await peer1.protocol.testConnection(peer2.
|
|
222
|
-
await peer2.protocol.testConnection(peer1.
|
|
229
|
+
await peer1.protocol.testConnection(PublicKey.from(peer2.peer.peerKey), 'test message 1');
|
|
230
|
+
await peer2.protocol.testConnection(PublicKey.from(peer1.peer.peerKey), 'test message 2');
|
|
223
231
|
};
|
package/src/swarm/swarm.ts
CHANGED
|
@@ -8,9 +8,8 @@ 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 ListeningHandle, type Messenger } from '@dxos/messaging';
|
|
11
|
+
import { type SwarmEvent, type ListeningHandle, type Messenger, type PeerInfo, PeerInfoHash } from '@dxos/messaging';
|
|
12
12
|
import { trace } from '@dxos/protocols';
|
|
13
|
-
import { type SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
|
|
14
13
|
import { type Answer } from '@dxos/protocols/proto/dxos/mesh/swarm';
|
|
15
14
|
import { ComplexMap, isNotNullOrUndefined } from '@dxos/util';
|
|
16
15
|
|
|
@@ -41,9 +40,10 @@ export class Swarm {
|
|
|
41
40
|
private _listeningHandle?: ListeningHandle = undefined;
|
|
42
41
|
|
|
43
42
|
/**
|
|
43
|
+
* PeerInfo -> Peer.
|
|
44
44
|
* @internal
|
|
45
45
|
*/
|
|
46
|
-
readonly _peers = new ComplexMap<
|
|
46
|
+
readonly _peers = new ComplexMap<PeerInfo, Peer>(PeerInfoHash);
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* Unique id of the swarm, local to the current peer, generated when swarm is joined.
|
|
@@ -61,13 +61,13 @@ export class Swarm {
|
|
|
61
61
|
* Connection to a peer is dropped.
|
|
62
62
|
* @internal
|
|
63
63
|
*/
|
|
64
|
-
readonly disconnected = new Event<
|
|
64
|
+
readonly disconnected = new Event<PeerInfo>();
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
* Connection is established to a new peer.
|
|
68
68
|
* @internal
|
|
69
69
|
*/
|
|
70
|
-
readonly connected = new Event<
|
|
70
|
+
readonly connected = new Event<PeerInfo>();
|
|
71
71
|
|
|
72
72
|
readonly errors = new ErrorStream();
|
|
73
73
|
|
|
@@ -76,8 +76,7 @@ export class Swarm {
|
|
|
76
76
|
// TODO(burdon): Pass in object.
|
|
77
77
|
constructor(
|
|
78
78
|
private readonly _topic: PublicKey,
|
|
79
|
-
|
|
80
|
-
private readonly _ownPeerId: PublicKey,
|
|
79
|
+
private readonly _ownPeer: PeerInfo,
|
|
81
80
|
private _topology: Topology,
|
|
82
81
|
private readonly _protocolProvider: WireProtocolProvider,
|
|
83
82
|
private readonly _messenger: Messenger,
|
|
@@ -88,9 +87,9 @@ export class Swarm {
|
|
|
88
87
|
) {
|
|
89
88
|
log.trace(
|
|
90
89
|
'dxos.mesh.swarm.constructor',
|
|
91
|
-
trace.begin({ id: this._instanceId, data: { topic: this._topic.toHex(),
|
|
90
|
+
trace.begin({ id: this._instanceId, data: { topic: this._topic.toHex(), peer: this._ownPeer } }),
|
|
92
91
|
);
|
|
93
|
-
log('creating swarm', { peerId:
|
|
92
|
+
log('creating swarm', { peerId: _ownPeer });
|
|
94
93
|
_topology.init(this._getSwarmController());
|
|
95
94
|
|
|
96
95
|
this._swarmMessenger = new SwarmMessenger({
|
|
@@ -108,9 +107,13 @@ export class Swarm {
|
|
|
108
107
|
.filter(isNotNullOrUndefined);
|
|
109
108
|
}
|
|
110
109
|
|
|
111
|
-
@logInfo
|
|
112
110
|
get ownPeerId() {
|
|
113
|
-
return this.
|
|
111
|
+
return PublicKey.from(this._ownPeer.peerKey);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@logInfo
|
|
115
|
+
get ownPeer() {
|
|
116
|
+
return this._ownPeer;
|
|
114
117
|
}
|
|
115
118
|
|
|
116
119
|
/**
|
|
@@ -128,7 +131,7 @@ export class Swarm {
|
|
|
128
131
|
async open() {
|
|
129
132
|
invariant(!this._listeningHandle);
|
|
130
133
|
this._listeningHandle = await this._messenger.listen({
|
|
131
|
-
|
|
134
|
+
peer: this._ownPeer,
|
|
132
135
|
payloadType: 'dxos.mesh.swarm.SwarmMessage',
|
|
133
136
|
onMessage: async (message) => {
|
|
134
137
|
await this._swarmMessenger
|
|
@@ -176,22 +179,22 @@ export class Swarm {
|
|
|
176
179
|
}
|
|
177
180
|
|
|
178
181
|
if (swarmEvent.peerAvailable) {
|
|
179
|
-
const peerId =
|
|
180
|
-
if (
|
|
182
|
+
const peerId = swarmEvent.peerAvailable.peer.peerKey;
|
|
183
|
+
if (peerId !== this._ownPeer.peerKey) {
|
|
181
184
|
log('new peer', { peerId });
|
|
182
|
-
const peer = this._getOrCreatePeer(
|
|
185
|
+
const peer = this._getOrCreatePeer(swarmEvent.peerAvailable.peer);
|
|
183
186
|
peer.advertizing = true;
|
|
184
187
|
}
|
|
185
188
|
} else if (swarmEvent.peerLeft) {
|
|
186
|
-
const peer = this._peers.get(
|
|
189
|
+
const peer = this._peers.get(swarmEvent.peerLeft.peer);
|
|
187
190
|
if (peer) {
|
|
188
191
|
peer.advertizing = false;
|
|
189
192
|
if (peer.connection?.state !== ConnectionState.CONNECTED) {
|
|
190
193
|
// Destroy peer only if there is no p2p-connection established
|
|
191
|
-
void this._destroyPeer(peer
|
|
194
|
+
void this._destroyPeer(swarmEvent.peerLeft.peer, 'peer left').catch((err) => log.catch(err));
|
|
192
195
|
}
|
|
193
196
|
} else {
|
|
194
|
-
log('received peerLeft but no peer found', { peer: swarmEvent.peerLeft.peer });
|
|
197
|
+
log('received peerLeft but no peer found', { peer: swarmEvent.peerLeft.peer.peerKey });
|
|
195
198
|
}
|
|
196
199
|
}
|
|
197
200
|
|
|
@@ -208,7 +211,7 @@ export class Swarm {
|
|
|
208
211
|
|
|
209
212
|
// Id of the peer offering us the connection.
|
|
210
213
|
invariant(message.author);
|
|
211
|
-
if (
|
|
214
|
+
if (message.recipient.peerKey !== this._ownPeer.peerKey) {
|
|
212
215
|
log('rejecting offer with incorrect peerId', { message });
|
|
213
216
|
return { accept: false };
|
|
214
217
|
}
|
|
@@ -230,7 +233,7 @@ export class Swarm {
|
|
|
230
233
|
return;
|
|
231
234
|
}
|
|
232
235
|
invariant(
|
|
233
|
-
message.recipient
|
|
236
|
+
message.recipient.peerKey === this._ownPeer.peerKey,
|
|
234
237
|
`Invalid signal peer id expected=${this.ownPeerId}, actual=${message.recipient}`,
|
|
235
238
|
);
|
|
236
239
|
invariant(message.topic?.equals(this._topic));
|
|
@@ -253,13 +256,14 @@ export class Swarm {
|
|
|
253
256
|
this._ctx = new Context();
|
|
254
257
|
}
|
|
255
258
|
|
|
256
|
-
private _getOrCreatePeer(
|
|
257
|
-
|
|
259
|
+
private _getOrCreatePeer(peerInfo: PeerInfo): Peer {
|
|
260
|
+
invariant(peerInfo.peerKey, 'PeerInfo.peerKey is required');
|
|
261
|
+
let peer = this._peers.get(peerInfo);
|
|
258
262
|
if (!peer) {
|
|
259
263
|
peer = new Peer(
|
|
260
|
-
|
|
264
|
+
peerInfo,
|
|
261
265
|
this._topic,
|
|
262
|
-
this.
|
|
266
|
+
this._ownPeer,
|
|
263
267
|
this._swarmMessenger,
|
|
264
268
|
this._protocolProvider,
|
|
265
269
|
this._transportFactory,
|
|
@@ -269,62 +273,62 @@ export class Swarm {
|
|
|
269
273
|
this.connectionAdded.emit(connection);
|
|
270
274
|
},
|
|
271
275
|
onConnected: () => {
|
|
272
|
-
this.connected.emit(
|
|
276
|
+
this.connected.emit(peerInfo);
|
|
273
277
|
},
|
|
274
278
|
onDisconnected: async () => {
|
|
275
279
|
if (this._isUnregistered(peer)) {
|
|
276
280
|
return;
|
|
277
281
|
}
|
|
278
282
|
if (!peer!.advertizing) {
|
|
279
|
-
await this._destroyPeer(
|
|
283
|
+
await this._destroyPeer(peerInfo, 'peer disconnected');
|
|
280
284
|
}
|
|
281
285
|
|
|
282
|
-
this.disconnected.emit(
|
|
286
|
+
this.disconnected.emit(peerInfo);
|
|
283
287
|
this._topology.update();
|
|
284
288
|
},
|
|
285
289
|
onRejected: () => {
|
|
286
290
|
// If the peer rejected our connection remove it from the set of candidates.
|
|
287
291
|
// TODO(dmaretskyi): Set flag instead.
|
|
288
292
|
if (!this._isUnregistered(peer)) {
|
|
289
|
-
log('peer rejected connection', {
|
|
290
|
-
void this._destroyPeer(
|
|
293
|
+
log('peer rejected connection', { peerInfo });
|
|
294
|
+
void this._destroyPeer(peerInfo, 'peer rejected connection');
|
|
291
295
|
}
|
|
292
296
|
},
|
|
293
297
|
onAccepted: () => {
|
|
294
298
|
this._topology.update();
|
|
295
299
|
},
|
|
296
300
|
onOffer: (remoteId) => {
|
|
297
|
-
return this._topology.onOffer(remoteId);
|
|
301
|
+
return this._topology.onOffer(PublicKey.from(remoteId.peerKey));
|
|
298
302
|
},
|
|
299
303
|
onPeerAvailable: () => {
|
|
300
304
|
this._topology.update();
|
|
301
305
|
},
|
|
302
306
|
},
|
|
303
307
|
);
|
|
304
|
-
this._peers.set(
|
|
308
|
+
this._peers.set(peerInfo, peer);
|
|
305
309
|
}
|
|
306
310
|
|
|
307
311
|
return peer;
|
|
308
312
|
}
|
|
309
313
|
|
|
310
|
-
private async _destroyPeer(
|
|
311
|
-
const peer = this._peers.get(
|
|
314
|
+
private async _destroyPeer(peerInfo: PeerInfo, reason?: string) {
|
|
315
|
+
const peer = this._peers.get(peerInfo);
|
|
312
316
|
invariant(peer);
|
|
313
|
-
this._peers.delete(
|
|
317
|
+
this._peers.delete(peerInfo);
|
|
314
318
|
await peer.safeDestroy(new Error(reason));
|
|
315
319
|
}
|
|
316
320
|
|
|
317
321
|
private _getSwarmController(): SwarmController {
|
|
318
322
|
return {
|
|
319
323
|
getState: () => ({
|
|
320
|
-
ownPeerId: this.
|
|
321
|
-
connected: Array.from(this._peers.
|
|
322
|
-
.filter((peer) => peer.connection)
|
|
323
|
-
.map((
|
|
324
|
-
candidates: Array.from(this._peers.
|
|
325
|
-
.filter((peer) => !peer.connection && peer.advertizing && peer.availableToConnect)
|
|
326
|
-
.map((
|
|
327
|
-
allPeers: Array.from(this._peers.
|
|
324
|
+
ownPeerId: PublicKey.from(this._ownPeer.peerKey),
|
|
325
|
+
connected: Array.from(this._peers.entries())
|
|
326
|
+
.filter(([_, peer]) => peer.connection)
|
|
327
|
+
.map(([info]) => PublicKey.from(info.peerKey)),
|
|
328
|
+
candidates: Array.from(this._peers.entries())
|
|
329
|
+
.filter(([_, peer]) => !peer.connection && peer.advertizing && peer.availableToConnect)
|
|
330
|
+
.map(([info]) => PublicKey.from(info.peerKey)),
|
|
331
|
+
allPeers: Array.from(this._peers.keys()).map((info) => PublicKey.from(info.peerKey)),
|
|
328
332
|
}),
|
|
329
333
|
connect: (peer) => {
|
|
330
334
|
if (this._ctx.disposed) {
|
|
@@ -334,7 +338,7 @@ export class Swarm {
|
|
|
334
338
|
// Run in a separate non-blocking task.
|
|
335
339
|
scheduleTask(this._ctx, async () => {
|
|
336
340
|
try {
|
|
337
|
-
await this._initiateConnection(peer);
|
|
341
|
+
await this._initiateConnection({ peerKey: peer.toHex() });
|
|
338
342
|
} catch (err: any) {
|
|
339
343
|
log('initiation error', err);
|
|
340
344
|
}
|
|
@@ -347,7 +351,7 @@ export class Swarm {
|
|
|
347
351
|
|
|
348
352
|
// Run in a separate non-blocking task.
|
|
349
353
|
scheduleTask(this._ctx, async () => {
|
|
350
|
-
await this._closeConnection(peer);
|
|
354
|
+
await this._closeConnection({ peerKey: peer.toHex() });
|
|
351
355
|
this._topology.update();
|
|
352
356
|
});
|
|
353
357
|
},
|
|
@@ -357,14 +361,14 @@ export class Swarm {
|
|
|
357
361
|
/**
|
|
358
362
|
* Creates a connection then sends message over signal network.
|
|
359
363
|
*/
|
|
360
|
-
private async _initiateConnection(
|
|
364
|
+
private async _initiateConnection(remotePeer: PeerInfo) {
|
|
361
365
|
const ctx = this._ctx; // Copy to avoid getting reset while sleeping.
|
|
362
366
|
|
|
363
367
|
// It is likely that the other peer will also try to connect to us at the same time.
|
|
364
368
|
// If our peerId is higher, we will wait for a bit so that other peer has a chance to connect first.
|
|
365
|
-
const peer = this._getOrCreatePeer(
|
|
366
|
-
if (
|
|
367
|
-
log('initiation delay', {
|
|
369
|
+
const peer = this._getOrCreatePeer(remotePeer);
|
|
370
|
+
if (remotePeer.peerKey < this._ownPeer.peerKey) {
|
|
371
|
+
log('initiation delay', { remotePeer });
|
|
368
372
|
await sleep(this._initiationDelay);
|
|
369
373
|
}
|
|
370
374
|
if (ctx.disposed) {
|
|
@@ -380,14 +384,14 @@ export class Swarm {
|
|
|
380
384
|
return;
|
|
381
385
|
}
|
|
382
386
|
|
|
383
|
-
log('initiating connection...', {
|
|
387
|
+
log('initiating connection...', { remotePeer });
|
|
384
388
|
await peer.initiateConnection();
|
|
385
389
|
this._topology.update();
|
|
386
|
-
log('initiated', {
|
|
390
|
+
log('initiated', { remotePeer });
|
|
387
391
|
}
|
|
388
392
|
|
|
389
|
-
private async _closeConnection(
|
|
390
|
-
const peer = this._peers.get(
|
|
393
|
+
private async _closeConnection(peerInfo: PeerInfo) {
|
|
394
|
+
const peer = this._peers.get(peerInfo);
|
|
391
395
|
if (!peer) {
|
|
392
396
|
return;
|
|
393
397
|
}
|
|
@@ -396,6 +400,6 @@ export class Swarm {
|
|
|
396
400
|
}
|
|
397
401
|
|
|
398
402
|
private _isUnregistered(peer?: Peer): boolean {
|
|
399
|
-
return !peer || this._peers.get(peer.
|
|
403
|
+
return !peer || this._peers.get(peer.remoteInfo) !== peer;
|
|
400
404
|
}
|
|
401
405
|
}
|
|
@@ -227,7 +227,7 @@ export class TestSwarmConnection {
|
|
|
227
227
|
async join(topology = new FullyConnectedTopology()) {
|
|
228
228
|
await this.peer._networkManager.joinSwarm({
|
|
229
229
|
topic: this.topic,
|
|
230
|
-
peerId: this.peer.peerId,
|
|
230
|
+
peerInfo: { peerKey: this.peer.peerId.toHex(), identityKey: this.peer.peerId.toHex() },
|
|
231
231
|
protocolProvider: this.protocol.factory,
|
|
232
232
|
topology,
|
|
233
233
|
});
|
|
@@ -147,10 +147,10 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
147
147
|
//
|
|
148
148
|
const connectionDropped = peer2._networkManager
|
|
149
149
|
.getSwarm(topic)
|
|
150
|
-
?.disconnected.waitFor((
|
|
150
|
+
?.disconnected.waitFor(({ peerKey }) => peer1.peerId.equals(peerKey!));
|
|
151
151
|
|
|
152
152
|
const peerLeft = peer2._signalManager.swarmEvent.waitFor(
|
|
153
|
-
(event) => !!event.
|
|
153
|
+
(event) => !!event.peerLeft && peer1.peerId.equals(event.peerLeft.peer.peerKey),
|
|
154
154
|
);
|
|
155
155
|
|
|
156
156
|
await peer1.goOffline();
|
|
@@ -159,14 +159,17 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
159
159
|
|
|
160
160
|
// Wait for peer to be removed from the swarm.
|
|
161
161
|
await waitForExpect(() => {
|
|
162
|
-
expect(!!peer2._networkManager.getSwarm(topic)!._peers.get(peer1.peerId)?.advertizing).to.be
|
|
162
|
+
expect(!!peer2._networkManager.getSwarm(topic)!._peers.get({ peerKey: peer1.peerId.toHex() })?.advertizing).to.be
|
|
163
|
+
.false;
|
|
163
164
|
}, 1_000);
|
|
164
165
|
|
|
165
166
|
await peer1.goOnline();
|
|
166
167
|
|
|
167
168
|
await waitForExpect(() => {
|
|
168
|
-
expect(peer1._networkManager.getSwarm(topic)?._peers.get(peer2.peerId)?.advertizing).to.be
|
|
169
|
-
|
|
169
|
+
expect(peer1._networkManager.getSwarm(topic)?._peers.get({ peerKey: peer2.peerId.toHex() })?.advertizing).to.be
|
|
170
|
+
.true;
|
|
171
|
+
expect(peer2._networkManager.getSwarm(topic)?._peers.get({ peerKey: peer1.peerId.toHex() })?.advertizing).to.be
|
|
172
|
+
.true;
|
|
170
173
|
}, 2_000);
|
|
171
174
|
|
|
172
175
|
await exchangeMessages(swarm1, swarm2);
|
|
@@ -121,7 +121,10 @@ export const propertyTestSuite = () => {
|
|
|
121
121
|
// const protocol = createProtocolFactory(model.topic, this.peerId, [presence]);
|
|
122
122
|
|
|
123
123
|
await peer.networkManager.joinSwarm({
|
|
124
|
-
|
|
124
|
+
peerInfo: {
|
|
125
|
+
peerKey: this.peerId.toHex(),
|
|
126
|
+
identityKey: this.peerId.toHex(),
|
|
127
|
+
},
|
|
125
128
|
topic: model.topic,
|
|
126
129
|
protocolProvider: todo(),
|
|
127
130
|
topology: new FullyConnectedTopology(),
|