@dxos/network-manager 0.6.12-staging.e11e696 → 0.6.12
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-YOKKEU6T.mjs → chunk-XYSYUN63.mjs} +998 -1192
- package/dist/lib/browser/chunk-XYSYUN63.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +19 -10
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +27 -18
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-7ZWQLO5T.cjs → chunk-4YAYC7WN.cjs} +1166 -1233
- package/dist/lib/node/chunk-4YAYC7WN.cjs.map +7 -0
- package/dist/lib/node/index.cjs +37 -27
- package/dist/lib/node/index.cjs.map +2 -2
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +29 -20
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/types/src/signal/integration.test.d.ts +2 -0
- package/dist/types/src/signal/integration.test.d.ts.map +1 -0
- package/dist/types/src/signal/swarm-messenger.test.d.ts +2 -0
- package/dist/types/src/signal/swarm-messenger.test.d.ts.map +1 -0
- package/dist/types/src/swarm/connection.d.ts.map +1 -1
- package/dist/types/src/swarm/swarm.d.ts +1 -1
- package/dist/types/src/testing/test-builder.d.ts +2 -2
- package/dist/types/src/testing/test-builder.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/dist/types/src/tests/tcp-transport.test.d.ts +2 -0
- package/dist/types/src/tests/tcp-transport.test.d.ts.map +1 -0
- package/dist/types/src/tests/utils.d.ts.map +1 -1
- package/dist/types/src/transport/index.d.ts +5 -1
- package/dist/types/src/transport/index.d.ts.map +1 -1
- package/dist/types/src/transport/libdatachannel-transport.d.ts +42 -0
- package/dist/types/src/transport/libdatachannel-transport.d.ts.map +1 -0
- package/dist/types/src/transport/libdatachannel-transport.test.d.ts +2 -0
- package/dist/types/src/transport/libdatachannel-transport.test.d.ts.map +1 -0
- package/dist/types/src/transport/memory-transport.d.ts +2 -2
- package/dist/types/src/transport/memory-transport.d.ts.map +1 -1
- package/dist/types/src/transport/memory-transport.test.d.ts +2 -0
- package/dist/types/src/transport/memory-transport.test.d.ts.map +1 -0
- package/dist/types/src/transport/simplepeer-simple-peer.d.ts +2 -0
- package/dist/types/src/transport/simplepeer-simple-peer.d.ts.map +1 -0
- package/dist/types/src/transport/simplepeer-transport-proxy-test.d.ts +2 -0
- package/dist/types/src/transport/simplepeer-transport-proxy-test.d.ts.map +1 -0
- package/dist/types/src/transport/{webrtc/rtc-transport-proxy.d.ts → simplepeer-transport-proxy.d.ts} +12 -10
- package/dist/types/src/transport/simplepeer-transport-proxy.d.ts.map +1 -0
- package/dist/types/src/transport/{webrtc/rtc-transport-service.d.ts → simplepeer-transport-service.d.ts} +7 -9
- package/dist/types/src/transport/simplepeer-transport-service.d.ts.map +1 -0
- package/dist/types/src/transport/simplepeer-transport.d.ts +36 -0
- package/dist/types/src/transport/simplepeer-transport.d.ts.map +1 -0
- package/dist/types/src/transport/simplepeer-transport.test.d.ts +2 -0
- package/dist/types/src/transport/simplepeer-transport.test.d.ts.map +1 -0
- package/dist/types/src/transport/{tcp/tcp-transport.browser.d.ts → tcp-transport.browser.d.ts} +3 -3
- package/dist/types/src/transport/tcp-transport.browser.d.ts.map +1 -0
- package/dist/types/src/transport/{tcp/tcp-transport.d.ts → tcp-transport.d.ts} +3 -3
- package/dist/types/src/transport/tcp-transport.d.ts.map +1 -0
- package/dist/types/src/transport/transport.d.ts +6 -7
- package/dist/types/src/transport/transport.d.ts.map +1 -1
- package/dist/types/src/transport/webrtc.d.ts +6 -0
- package/dist/types/src/transport/webrtc.d.ts.map +1 -0
- package/package.json +30 -53
- package/src/globals.d.ts +7 -0
- package/src/signal/ice.test.ts +3 -1
- package/src/signal/{integration.node.test.ts → integration.test.ts} +15 -9
- package/src/signal/{swarm-messenger.node.test.ts → swarm-messenger.test.ts} +23 -13
- package/src/swarm/connection-limiter.test.ts +6 -3
- package/src/swarm/connection.test.ts +38 -63
- package/src/swarm/connection.ts +5 -5
- package/src/swarm/swarm.test.ts +11 -9
- package/src/swarm/swarm.ts +1 -1
- package/src/testing/test-builder.ts +28 -12
- package/src/tests/basic-test-suite.ts +33 -34
- package/src/tests/memory-transport.test.ts +42 -40
- package/src/tests/property-test-suite.ts +22 -21
- package/src/tests/tcp-transport.test.ts +67 -0
- package/src/tests/utils.ts +2 -3
- package/src/tests/webrtc-transport.test.ts +9 -9
- package/src/transport/index.ts +5 -1
- package/src/transport/libdatachannel-transport.test.ts +100 -0
- package/src/transport/libdatachannel-transport.ts +376 -0
- package/src/transport/memory-transport.test.ts +74 -0
- package/src/transport/memory-transport.ts +0 -2
- package/src/transport/simplepeer-simple-peer.ts +26 -0
- package/src/transport/simplepeer-transport-proxy-test.ts +181 -0
- package/src/transport/simplepeer-transport-proxy.ts +246 -0
- package/src/transport/simplepeer-transport-service.ts +160 -0
- package/src/transport/simplepeer-transport.test.ts +61 -0
- package/src/transport/simplepeer-transport.ts +250 -0
- package/src/transport/{tcp/tcp-transport.browser.ts → tcp-transport.browser.ts} +3 -7
- package/src/transport/{tcp/tcp-transport.ts → tcp-transport.ts} +1 -3
- package/src/transport/transport.ts +7 -8
- package/src/transport/webrtc.ts +15 -0
- package/src/typings.d.ts +2 -8
- package/dist/lib/browser/chunk-GW3YM55A.mjs +0 -14
- package/dist/lib/browser/chunk-GW3YM55A.mjs.map +0 -7
- package/dist/lib/browser/chunk-YOKKEU6T.mjs.map +0 -7
- package/dist/lib/browser/transport/tcp/index.mjs +0 -39
- package/dist/lib/browser/transport/tcp/index.mjs.map +0 -7
- package/dist/lib/node/chunk-7ZWQLO5T.cjs.map +0 -7
- package/dist/lib/node/transport/tcp/index.cjs +0 -191
- package/dist/lib/node/transport/tcp/index.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-4VO725JT.mjs +0 -4383
- package/dist/lib/node-esm/chunk-4VO725JT.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -50
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/testing/index.mjs +0 -280
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/lib/node-esm/transport/tcp/index.mjs +0 -159
- package/dist/lib/node-esm/transport/tcp/index.mjs.map +0 -7
- package/dist/types/src/signal/integration.node.test.d.ts +0 -2
- package/dist/types/src/signal/integration.node.test.d.ts.map +0 -1
- package/dist/types/src/signal/swarm-messenger.node.test.d.ts +0 -2
- package/dist/types/src/signal/swarm-messenger.node.test.d.ts.map +0 -1
- package/dist/types/src/tests/tcp-transport.node.test.d.ts +0 -2
- package/dist/types/src/tests/tcp-transport.node.test.d.ts.map +0 -1
- package/dist/types/src/transport/tcp/index.d.ts +0 -2
- package/dist/types/src/transport/tcp/index.d.ts.map +0 -1
- package/dist/types/src/transport/tcp/tcp-transport.browser.d.ts.map +0 -1
- package/dist/types/src/transport/tcp/tcp-transport.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/index.d.ts +0 -4
- package/dist/types/src/transport/webrtc/index.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-connection-factory.d.ts +0 -14
- package/dist/types/src/transport/webrtc/rtc-connection-factory.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-peer-connection.d.ts +0 -68
- package/dist/types/src/transport/webrtc/rtc-peer-connection.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-channel.d.ts +0 -33
- package/dist/types/src/transport/webrtc/rtc-transport-channel.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-channel.test.d.ts +0 -2
- package/dist/types/src/transport/webrtc/rtc-transport-channel.test.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-factory.d.ts +0 -4
- package/dist/types/src/transport/webrtc/rtc-transport-factory.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-proxy.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-proxy.test.d.ts +0 -2
- package/dist/types/src/transport/webrtc/rtc-transport-proxy.test.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-service.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport-stats.d.ts +0 -4
- package/dist/types/src/transport/webrtc/rtc-transport-stats.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/rtc-transport.test.d.ts +0 -2
- package/dist/types/src/transport/webrtc/rtc-transport.test.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/test-utils.d.ts +0 -5
- package/dist/types/src/transport/webrtc/test-utils.d.ts.map +0 -1
- package/dist/types/src/transport/webrtc/utils.d.ts +0 -3
- package/dist/types/src/transport/webrtc/utils.d.ts.map +0 -1
- package/src/tests/tcp-transport.node.test.ts +0 -65
- package/src/transport/tcp/index.ts +0 -5
- package/src/transport/webrtc/index.ts +0 -7
- package/src/transport/webrtc/rtc-connection-factory.ts +0 -82
- package/src/transport/webrtc/rtc-peer-connection.ts +0 -472
- package/src/transport/webrtc/rtc-transport-channel.test.ts +0 -176
- package/src/transport/webrtc/rtc-transport-channel.ts +0 -195
- package/src/transport/webrtc/rtc-transport-factory.ts +0 -28
- package/src/transport/webrtc/rtc-transport-proxy.test.ts +0 -413
- package/src/transport/webrtc/rtc-transport-proxy.ts +0 -264
- package/src/transport/webrtc/rtc-transport-service.ts +0 -192
- package/src/transport/webrtc/rtc-transport-stats.ts +0 -67
- package/src/transport/webrtc/rtc-transport.test.ts +0 -198
- package/src/transport/webrtc/test-utils.ts +0 -22
- package/src/transport/webrtc/utils.ts +0 -36
|
@@ -2,18 +2,22 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// @dxos/test platform=nodejs
|
|
6
|
+
|
|
7
|
+
import { expect } from 'earljs';
|
|
8
|
+
import waitForExpect from 'wait-for-expect';
|
|
6
9
|
|
|
7
10
|
import { type Awaited } from '@dxos/async';
|
|
8
11
|
import { PublicKey } from '@dxos/keys';
|
|
9
12
|
import { Messenger, WebsocketSignalManager } from '@dxos/messaging';
|
|
10
13
|
import { type Answer } from '@dxos/protocols/proto/dxos/mesh/swarm';
|
|
11
14
|
import { runTestSignalServer } from '@dxos/signal';
|
|
15
|
+
import { afterAll, beforeAll, describe, test, afterTest } from '@dxos/test';
|
|
12
16
|
|
|
13
17
|
import { type OfferMessage, type SignalMessage } from './signal-messenger';
|
|
14
18
|
import { SwarmMessenger } from './swarm-messenger';
|
|
15
19
|
|
|
16
|
-
describe('SwarmMessenger',
|
|
20
|
+
describe('SwarmMessenger', () => {
|
|
17
21
|
let topic: PublicKey;
|
|
18
22
|
|
|
19
23
|
let broker1: Awaited<ReturnType<typeof runTestSignalServer>>;
|
|
@@ -44,9 +48,7 @@ describe('SwarmMessenger', { timeout: 7000 }, () => {
|
|
|
44
48
|
const peer = { peerKey: PublicKey.random().toHex() };
|
|
45
49
|
const signalManager = new WebsocketSignalManager([{ server: signalApiUrl }]);
|
|
46
50
|
await signalManager.open();
|
|
47
|
-
|
|
48
|
-
await signalManager.close();
|
|
49
|
-
});
|
|
51
|
+
afterTest(() => signalManager.close());
|
|
50
52
|
|
|
51
53
|
const messenger = new Messenger({ signalManager });
|
|
52
54
|
await messenger.listen({
|
|
@@ -104,8 +106,10 @@ describe('SwarmMessenger', { timeout: 7000 }, () => {
|
|
|
104
106
|
};
|
|
105
107
|
await router2.signal(msg);
|
|
106
108
|
|
|
107
|
-
await
|
|
108
|
-
|
|
109
|
+
await waitForExpect(() => {
|
|
110
|
+
expect(received[0]).toBeAnObjectWith(msg);
|
|
111
|
+
}, 4_000);
|
|
112
|
+
}).timeout(5_000);
|
|
109
113
|
|
|
110
114
|
test('offer/answer', async () => {
|
|
111
115
|
const {
|
|
@@ -135,7 +139,7 @@ describe('SwarmMessenger', { timeout: 7000 }, () => {
|
|
|
135
139
|
data: { offer: {} },
|
|
136
140
|
});
|
|
137
141
|
expect(answer.accept).toEqual(true);
|
|
138
|
-
});
|
|
142
|
+
}).timeout(5_000);
|
|
139
143
|
|
|
140
144
|
test('signaling between 3 clients', async () => {
|
|
141
145
|
const received1: SignalMessage[] = [];
|
|
@@ -194,7 +198,9 @@ describe('SwarmMessenger', { timeout: 7000 }, () => {
|
|
|
194
198
|
data: { signal: { payload: { msg: '1to3' } }, signalBatch: undefined },
|
|
195
199
|
};
|
|
196
200
|
await router1.signal(msg1to3);
|
|
197
|
-
await
|
|
201
|
+
await waitForExpect(() => {
|
|
202
|
+
expect(received3[0]).toBeAnObjectWith(msg1to3);
|
|
203
|
+
}, 4_000);
|
|
198
204
|
|
|
199
205
|
// sending signal from peer2 to peer3.
|
|
200
206
|
const msg2to3: SignalMessage = {
|
|
@@ -205,7 +211,9 @@ describe('SwarmMessenger', { timeout: 7000 }, () => {
|
|
|
205
211
|
data: { signal: { payload: { msg: '2to3' } }, signalBatch: undefined },
|
|
206
212
|
};
|
|
207
213
|
await router2.signal(msg2to3);
|
|
208
|
-
await
|
|
214
|
+
await waitForExpect(() => {
|
|
215
|
+
expect(received3[1]).toBeAnObjectWith(msg2to3);
|
|
216
|
+
}, 4_000);
|
|
209
217
|
|
|
210
218
|
// sending signal from peer3 to peer1.
|
|
211
219
|
const msg3to1: SignalMessage = {
|
|
@@ -216,8 +224,10 @@ describe('SwarmMessenger', { timeout: 7000 }, () => {
|
|
|
216
224
|
data: { signal: { payload: { msg: '3to1' } }, signalBatch: undefined },
|
|
217
225
|
};
|
|
218
226
|
await router3.signal(msg3to1);
|
|
219
|
-
await
|
|
220
|
-
|
|
227
|
+
await waitForExpect(() => {
|
|
228
|
+
expect(received1[0]).toBeAnObjectWith(msg3to1);
|
|
229
|
+
}, 4_000);
|
|
230
|
+
}).timeout(5_000);
|
|
221
231
|
|
|
222
232
|
test('two offers', async () => {
|
|
223
233
|
const {
|
|
@@ -263,5 +273,5 @@ describe('SwarmMessenger', { timeout: 7000 }, () => {
|
|
|
263
273
|
data: { offer: {} },
|
|
264
274
|
});
|
|
265
275
|
expect(answer2.accept).toEqual(true);
|
|
266
|
-
});
|
|
276
|
+
}).timeout(5_000);
|
|
267
277
|
});
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
//
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
|
-
|
|
5
|
-
import
|
|
4
|
+
import chai, { expect } from 'chai';
|
|
5
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
6
6
|
|
|
7
7
|
import { asyncTimeout } from '@dxos/async';
|
|
8
8
|
import { PublicKey } from '@dxos/keys';
|
|
9
|
+
import { describe, test } from '@dxos/test';
|
|
9
10
|
|
|
10
11
|
import { ConnectionLimiter } from './connection-limiter';
|
|
11
12
|
|
|
13
|
+
chai.use(chaiAsPromised);
|
|
14
|
+
|
|
12
15
|
describe('ConnectionLimiter', () => {
|
|
13
16
|
function* setupPeers(
|
|
14
17
|
limiter: ConnectionLimiter,
|
|
@@ -34,7 +37,7 @@ describe('ConnectionLimiter', () => {
|
|
|
34
37
|
test('rejects if done is called', async () => {
|
|
35
38
|
const limiter = new ConnectionLimiter({ maxConcurrentInitConnections: 1 });
|
|
36
39
|
const [first] = setupPeers(limiter);
|
|
37
|
-
const testPromise = expect(first.connecting()).
|
|
40
|
+
const testPromise = expect(first.connecting()).to.be.rejected;
|
|
38
41
|
first.doneConnecting();
|
|
39
42
|
await testPromise;
|
|
40
43
|
});
|
|
@@ -2,103 +2,78 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { describe, test } from 'vitest';
|
|
6
|
-
|
|
7
5
|
import { sleep } from '@dxos/async';
|
|
8
6
|
import { PublicKey } from '@dxos/keys';
|
|
7
|
+
import { describe, test } from '@dxos/test';
|
|
9
8
|
|
|
10
9
|
import { Connection } from './connection';
|
|
11
10
|
import { TestWireProtocol } from '../testing/test-wire-protocol';
|
|
12
|
-
import {
|
|
13
|
-
import { chooseInitiatorPeer } from '../transport/webrtc/utils';
|
|
11
|
+
import { createLibDataChannelTransportFactory, createSimplePeerTransportFactory } from '../transport';
|
|
14
12
|
|
|
15
13
|
describe('Connection', () => {
|
|
16
|
-
test('responder opens after initiator', async () => {
|
|
17
|
-
const { initiator, responder } = createPeerKeys();
|
|
18
|
-
await connectionTest({
|
|
19
|
-
fastConnectionKey: initiator,
|
|
20
|
-
slowConnectionKey: responder,
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
|
|
24
14
|
test('initiator opens after responder', async () => {
|
|
25
|
-
const { initiator, responder } = createPeerKeys();
|
|
26
|
-
await connectionTest({
|
|
27
|
-
fastConnectionKey: responder,
|
|
28
|
-
slowConnectionKey: initiator,
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
const connectionTest = async (setup: { fastConnectionKey: PublicKey; slowConnectionKey: PublicKey }) => {
|
|
33
15
|
const [topic, sessionId] = PublicKey.randomSequence();
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
const slowConnection = new Connection(
|
|
16
|
+
const peer1 = { peerKey: PublicKey.random().toHex() };
|
|
17
|
+
const peer2 = { peerKey: PublicKey.random().toHex() };
|
|
18
|
+
const protocol1 = new TestWireProtocol(PublicKey.from(peer1.peerKey));
|
|
19
|
+
const connection1 = new Connection(
|
|
39
20
|
topic,
|
|
40
|
-
|
|
41
|
-
|
|
21
|
+
peer1,
|
|
22
|
+
peer2,
|
|
42
23
|
sessionId,
|
|
43
24
|
true,
|
|
44
25
|
{
|
|
45
|
-
offer: async (msg) =>
|
|
26
|
+
offer: async (msg) => {
|
|
27
|
+
return { accept: true };
|
|
28
|
+
},
|
|
46
29
|
signal: async (msg) => {
|
|
47
|
-
await
|
|
30
|
+
await connection2.signal(msg);
|
|
48
31
|
},
|
|
49
32
|
},
|
|
50
|
-
|
|
33
|
+
protocol1.factory({
|
|
51
34
|
initiator: true,
|
|
52
|
-
localPeerId: PublicKey.from(
|
|
53
|
-
remotePeerId: PublicKey.from(
|
|
35
|
+
localPeerId: PublicKey.from(peer1.peerKey),
|
|
36
|
+
remotePeerId: PublicKey.from(peer2.peerKey),
|
|
54
37
|
topic,
|
|
55
38
|
}),
|
|
56
|
-
|
|
39
|
+
// TODO(nf): configure better
|
|
40
|
+
process.env.MOCHA_ENV === 'nodejs' ? createLibDataChannelTransportFactory() : createSimplePeerTransportFactory(),
|
|
57
41
|
);
|
|
58
42
|
|
|
59
|
-
const
|
|
60
|
-
const
|
|
43
|
+
const protocol2 = new TestWireProtocol(PublicKey.from(peer2.peerKey));
|
|
44
|
+
const connection2 = new Connection(
|
|
61
45
|
topic,
|
|
62
|
-
|
|
63
|
-
|
|
46
|
+
peer2,
|
|
47
|
+
peer1,
|
|
64
48
|
sessionId,
|
|
65
49
|
false,
|
|
66
50
|
{
|
|
67
|
-
offer: async (msg) =>
|
|
51
|
+
offer: async (msg) => {
|
|
52
|
+
return { accept: true };
|
|
53
|
+
},
|
|
68
54
|
signal: async (msg) => {
|
|
69
|
-
await
|
|
55
|
+
await connection1.signal(msg);
|
|
70
56
|
},
|
|
71
57
|
},
|
|
72
|
-
|
|
58
|
+
protocol2.factory({
|
|
73
59
|
initiator: false,
|
|
74
|
-
localPeerId: PublicKey.from(
|
|
75
|
-
remotePeerId: PublicKey.from(
|
|
60
|
+
localPeerId: PublicKey.from(peer2.peerKey),
|
|
61
|
+
remotePeerId: PublicKey.from(peer1.peerKey),
|
|
76
62
|
topic,
|
|
77
63
|
}),
|
|
78
|
-
|
|
64
|
+
// TODO(nf): configure better
|
|
65
|
+
process.env.MOCHA_ENV === 'nodejs' ? createLibDataChannelTransportFactory() : createSimplePeerTransportFactory(),
|
|
79
66
|
);
|
|
80
67
|
|
|
81
|
-
|
|
82
|
-
await
|
|
83
|
-
await sleep(
|
|
84
|
-
|
|
85
|
-
slowConnection.initiate();
|
|
86
|
-
await slowConnection.openConnection();
|
|
68
|
+
connection2.initiate();
|
|
69
|
+
await connection2.openConnection();
|
|
70
|
+
await sleep(100);
|
|
87
71
|
|
|
72
|
+
connection1.initiate();
|
|
73
|
+
await connection1.openConnection();
|
|
88
74
|
await Promise.all([
|
|
89
|
-
|
|
90
|
-
|
|
75
|
+
protocol1.testConnection(PublicKey.from(peer2.peerKey), 'test message 1'),
|
|
76
|
+
protocol2.testConnection(PublicKey.from(peer1.peerKey), 'test message 2'),
|
|
91
77
|
]);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const createPeerKeys = () => {
|
|
95
|
-
const peer1 = PublicKey.random();
|
|
96
|
-
const peer2 = PublicKey.random();
|
|
97
|
-
const initiator = PublicKey.fromHex(chooseInitiatorPeer(peer1.toHex(), peer2.toHex()));
|
|
98
|
-
if (initiator.equals(peer1)) {
|
|
99
|
-
return { initiator: peer1, responder: peer2 };
|
|
100
|
-
} else {
|
|
101
|
-
return { initiator: peer2, responder: peer1 };
|
|
102
|
-
}
|
|
103
|
-
};
|
|
78
|
+
});
|
|
104
79
|
});
|
package/src/swarm/connection.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
ConnectionResetError,
|
|
16
16
|
ConnectivityError,
|
|
17
17
|
TimeoutError,
|
|
18
|
+
UnknownProtocolError,
|
|
18
19
|
trace,
|
|
19
20
|
} from '@dxos/protocols';
|
|
20
21
|
import { type Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
|
|
@@ -201,15 +202,14 @@ export class Connection {
|
|
|
201
202
|
|
|
202
203
|
invariant(!this._transport);
|
|
203
204
|
this._transport = this._transportFactory.createTransport({
|
|
204
|
-
ownPeerKey: this.localInfo.peerKey,
|
|
205
|
-
remotePeerKey: this.remoteInfo.peerKey,
|
|
206
|
-
topic: this.topic.toHex(),
|
|
207
205
|
initiator: this.initiator,
|
|
208
206
|
stream: this._protocol.stream,
|
|
209
207
|
sendSignal: async (signal) => this._sendSignal(signal),
|
|
210
208
|
sessionId: this.sessionId,
|
|
211
209
|
});
|
|
212
210
|
|
|
211
|
+
await this._transport.open();
|
|
212
|
+
|
|
213
213
|
this._transport.connected.once(async () => {
|
|
214
214
|
this._changeState(ConnectionState.CONNECTED);
|
|
215
215
|
await this.connectedTimeoutContext.dispose();
|
|
@@ -238,6 +238,8 @@ export class Connection {
|
|
|
238
238
|
} else if (err instanceof ConnectivityError) {
|
|
239
239
|
log.info('aborting due to transport ConnectivityError');
|
|
240
240
|
this.abort().catch((err) => this.errors.raise(err));
|
|
241
|
+
} else if (err instanceof UnknownProtocolError) {
|
|
242
|
+
log.warn('unsure what to do with UnknownProtocolError, will keep on truckin', { err });
|
|
241
243
|
}
|
|
242
244
|
|
|
243
245
|
if (this._state !== ConnectionState.CLOSED && this._state !== ConnectionState.CLOSING) {
|
|
@@ -246,8 +248,6 @@ export class Connection {
|
|
|
246
248
|
}
|
|
247
249
|
});
|
|
248
250
|
|
|
249
|
-
await this._transport.open();
|
|
250
|
-
|
|
251
251
|
// Replay signals that were received before transport was created.
|
|
252
252
|
for (const signal of this._incomingSignalBuffer) {
|
|
253
253
|
void this._transport.onSignal(signal); // TODO(burdon): Remove async?
|
package/src/swarm/swarm.test.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2020 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { expect } from 'chai';
|
|
6
6
|
|
|
7
7
|
import { asyncTimeout, sleep } from '@dxos/async';
|
|
8
8
|
import { PublicKey } from '@dxos/keys';
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
type PeerInfo,
|
|
14
14
|
type SignalManager,
|
|
15
15
|
} from '@dxos/messaging';
|
|
16
|
+
import { afterTest, describe, test } from '@dxos/test';
|
|
16
17
|
import { ComplexSet } from '@dxos/util';
|
|
17
18
|
|
|
18
19
|
import { ConnectionState } from './connection';
|
|
@@ -20,7 +21,7 @@ import { ConnectionLimiter } from './connection-limiter';
|
|
|
20
21
|
import { Swarm } from './swarm';
|
|
21
22
|
import { TestWireProtocol } from '../testing/test-wire-protocol';
|
|
22
23
|
import { FullyConnectedTopology } from '../topology';
|
|
23
|
-
import {
|
|
24
|
+
import { createLibDataChannelTransportFactory, createSimplePeerTransportFactory } from '../transport';
|
|
24
25
|
|
|
25
26
|
type TestPeer = {
|
|
26
27
|
swarm: Swarm;
|
|
@@ -53,13 +54,14 @@ describe('Swarm', () => {
|
|
|
53
54
|
new FullyConnectedTopology(),
|
|
54
55
|
protocol.factory,
|
|
55
56
|
new Messenger({ signalManager }),
|
|
56
|
-
|
|
57
|
+
// TODO(nf): configure better
|
|
58
|
+
process.env.MOCHA_ENV === 'nodejs' ? createLibDataChannelTransportFactory() : createSimplePeerTransportFactory(),
|
|
57
59
|
undefined,
|
|
58
60
|
connectionLimiter,
|
|
59
61
|
initiationDelay,
|
|
60
62
|
);
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
afterTest(async () => {
|
|
63
65
|
await swarm.destroy();
|
|
64
66
|
await signalManager.close();
|
|
65
67
|
});
|
|
@@ -79,7 +81,7 @@ describe('Swarm', () => {
|
|
|
79
81
|
expect(peer2.swarm.connections.length).to.equal(0);
|
|
80
82
|
|
|
81
83
|
await connectSwarms(peer1, peer2);
|
|
82
|
-
});
|
|
84
|
+
}).timeout(5_000);
|
|
83
85
|
|
|
84
86
|
test('two peers try to originate connections to each other simultaneously', async () => {
|
|
85
87
|
const topic = PublicKey.random();
|
|
@@ -91,7 +93,7 @@ describe('Swarm', () => {
|
|
|
91
93
|
expect(peer2.swarm.connections.length).to.equal(0);
|
|
92
94
|
|
|
93
95
|
await connectSwarms(peer1, peer2);
|
|
94
|
-
});
|
|
96
|
+
}).timeout(5_000);
|
|
95
97
|
|
|
96
98
|
test('with simultaneous connections one of the peers drops initiated connection', async () => {
|
|
97
99
|
const topic = PublicKey.random();
|
|
@@ -109,9 +111,9 @@ describe('Swarm', () => {
|
|
|
109
111
|
|
|
110
112
|
await connectSwarms(peer1, peer2);
|
|
111
113
|
await asyncTimeout(connectionDisplaced!, 1000);
|
|
112
|
-
});
|
|
114
|
+
}).timeout(5_000);
|
|
113
115
|
|
|
114
|
-
test('second peer discovered after delay',
|
|
116
|
+
test('second peer discovered after delay', async () => {
|
|
115
117
|
const topic = PublicKey.random();
|
|
116
118
|
|
|
117
119
|
const peer1 = await setupSwarm({ topic });
|
|
@@ -124,7 +126,7 @@ describe('Swarm', () => {
|
|
|
124
126
|
expect(peer2.swarm.connections.length).to.equal(0);
|
|
125
127
|
|
|
126
128
|
await connectSwarms(peer1, peer2, () => sleep(15));
|
|
127
|
-
});
|
|
129
|
+
}).timeout(10_000);
|
|
128
130
|
|
|
129
131
|
test('connection limiter', async () => {
|
|
130
132
|
// remotePeer1 <--> peer (connectionLimiter: max = 1) <--> remotePeer2
|
package/src/swarm/swarm.ts
CHANGED
|
@@ -29,7 +29,7 @@ const getClassName = (obj: any) => Object.getPrototypeOf(obj).constructor.name;
|
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* A single peer's view of the swarm.
|
|
32
|
-
* Manages a set of
|
|
32
|
+
* Manages a set of connections implemented by simple-peer instances.
|
|
33
33
|
* Routes signal events and maintains swarm topology.
|
|
34
34
|
*/
|
|
35
35
|
export class Swarm {
|
|
@@ -16,12 +16,19 @@ import { type Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
|
16
16
|
import { createLinkedPorts, createProtoRpcPeer, type ProtoRpcPeer } from '@dxos/rpc';
|
|
17
17
|
import { ComplexMap } from '@dxos/util';
|
|
18
18
|
|
|
19
|
-
import { TcpTransportFactory } from '#tcp-transport';
|
|
20
19
|
import { type TestTeleportExtensionFactory, TestWireProtocol } from './test-wire-protocol';
|
|
21
20
|
import { SwarmNetworkManager } from '../network-manager';
|
|
22
21
|
import { FullyConnectedTopology } from '../topology';
|
|
23
|
-
import {
|
|
24
|
-
|
|
22
|
+
import {
|
|
23
|
+
createLibDataChannelTransportFactory,
|
|
24
|
+
createSimplePeerTransportFactory,
|
|
25
|
+
MemoryTransportFactory,
|
|
26
|
+
SimplePeerTransportProxyFactory,
|
|
27
|
+
SimplePeerTransportService,
|
|
28
|
+
type TransportFactory,
|
|
29
|
+
TransportKind,
|
|
30
|
+
} from '../transport';
|
|
31
|
+
import { TcpTransportFactory } from '../transport/tcp-transport';
|
|
25
32
|
|
|
26
33
|
// Signal server will be started by the setup script.
|
|
27
34
|
const port = process.env.SIGNAL_PORT ?? 4000;
|
|
@@ -78,12 +85,18 @@ export class TestPeer {
|
|
|
78
85
|
constructor(
|
|
79
86
|
private readonly testBuilder: TestBuilder,
|
|
80
87
|
public readonly peerId: PublicKey,
|
|
81
|
-
public readonly transport
|
|
82
|
-
? TransportKind.WEB_RTC
|
|
83
|
-
: TransportKind.MEMORY,
|
|
88
|
+
public readonly transport?: TransportKind,
|
|
84
89
|
) {
|
|
85
90
|
this._signalManager = this.testBuilder.createSignalManager();
|
|
86
|
-
|
|
91
|
+
if (!transport) {
|
|
92
|
+
if (this.testBuilder.options.signalHosts) {
|
|
93
|
+
// TODO(nf): configure better
|
|
94
|
+
transport = process.env.MOCHA_ENV === 'nodejs' ? TransportKind.LIBDATACHANNEL : TransportKind.SIMPLE_PEER;
|
|
95
|
+
} else {
|
|
96
|
+
transport = TransportKind.MEMORY;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
this._networkManager = this.createNetworkManager(transport);
|
|
87
100
|
}
|
|
88
101
|
|
|
89
102
|
// TODO(burdon): Move to TestBuilder.
|
|
@@ -97,10 +110,13 @@ export class TestPeer {
|
|
|
97
110
|
case TransportKind.TCP:
|
|
98
111
|
transportFactory = TcpTransportFactory;
|
|
99
112
|
break;
|
|
100
|
-
case TransportKind.
|
|
101
|
-
transportFactory =
|
|
113
|
+
case TransportKind.SIMPLE_PEER:
|
|
114
|
+
transportFactory = createSimplePeerTransportFactory();
|
|
115
|
+
break;
|
|
116
|
+
case TransportKind.LIBDATACHANNEL:
|
|
117
|
+
transportFactory = createLibDataChannelTransportFactory();
|
|
102
118
|
break;
|
|
103
|
-
case TransportKind.
|
|
119
|
+
case TransportKind.SIMPLE_PEER_PROXY:
|
|
104
120
|
{
|
|
105
121
|
// Simulates bridge to shared worker.
|
|
106
122
|
const [proxyPort, servicePort] = createLinkedPorts();
|
|
@@ -121,14 +137,14 @@ export class TestPeer {
|
|
|
121
137
|
exposed: {
|
|
122
138
|
BridgeService: schema.getService('dxos.mesh.bridge.BridgeService'),
|
|
123
139
|
},
|
|
124
|
-
handlers: { BridgeService: new
|
|
140
|
+
handlers: { BridgeService: new SimplePeerTransportService() },
|
|
125
141
|
noHandshake: true,
|
|
126
142
|
encodingOptions: {
|
|
127
143
|
preserveAny: true,
|
|
128
144
|
},
|
|
129
145
|
});
|
|
130
146
|
|
|
131
|
-
transportFactory = new
|
|
147
|
+
transportFactory = new SimplePeerTransportProxyFactory().setBridgeService(this._proxy.rpc.BridgeService);
|
|
132
148
|
}
|
|
133
149
|
break;
|
|
134
150
|
default:
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
// Copyright 2021 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { expect } from 'chai';
|
|
6
|
+
import waitForExpect from 'wait-for-expect';
|
|
6
7
|
|
|
7
8
|
import { asyncTimeout } from '@dxos/async';
|
|
8
9
|
import { PublicKey } from '@dxos/keys';
|
|
9
10
|
import { log } from '@dxos/log';
|
|
11
|
+
import { afterTest, test } from '@dxos/test';
|
|
10
12
|
import { range } from '@dxos/util';
|
|
11
13
|
|
|
12
14
|
import { exchangeMessages, joinSwarm, leaveSwarm, openAndCloseAfterTest } from './utils';
|
|
@@ -23,7 +25,7 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
23
25
|
return;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
test
|
|
28
|
+
test('joins swarm, sends messages, and cleanly exits', async () => {
|
|
27
29
|
const peer1 = testBuilder.createPeer();
|
|
28
30
|
const peer2 = testBuilder.createPeer();
|
|
29
31
|
await openAndCloseAfterTest([peer1, peer2]);
|
|
@@ -32,24 +34,24 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
32
34
|
const [swarm1, swarm2] = await joinSwarm([peer1, peer2], topic, () => new FullyConnectedTopology());
|
|
33
35
|
await exchangeMessages(swarm1, swarm2);
|
|
34
36
|
await leaveSwarm([peer1, peer2], topic);
|
|
35
|
-
});
|
|
37
|
+
}).tag('flaky');
|
|
36
38
|
|
|
37
39
|
// TODO(burdon): Test with more peers (configure and test messaging).
|
|
38
|
-
test
|
|
40
|
+
test('joins swarm with star topology', async () => {
|
|
39
41
|
const peer1 = testBuilder.createPeer();
|
|
40
|
-
|
|
42
|
+
afterTest(() => peer1.close());
|
|
41
43
|
const peer2 = testBuilder.createPeer();
|
|
42
|
-
|
|
44
|
+
afterTest(() => peer2.close());
|
|
43
45
|
await openAndCloseAfterTest([peer1, peer2]);
|
|
44
46
|
|
|
45
47
|
const topic = PublicKey.random();
|
|
46
48
|
const [swarm1, swarm2] = await joinSwarm([peer1, peer2], topic, () => new StarTopology(peer1.peerId)); // NOTE: Same peer.
|
|
47
49
|
await exchangeMessages(swarm1, swarm2);
|
|
48
50
|
await leaveSwarm([peer1, peer2], topic);
|
|
49
|
-
});
|
|
51
|
+
}).tag('flaky');
|
|
50
52
|
|
|
51
53
|
// TODO(burdon): Fails when trying to reconnect to same topic.
|
|
52
|
-
test
|
|
54
|
+
test('joins swarm multiple times', async () => {
|
|
53
55
|
const peer1 = testBuilder.createPeer();
|
|
54
56
|
const peer2 = testBuilder.createPeer();
|
|
55
57
|
await openAndCloseAfterTest([peer1, peer2]);
|
|
@@ -73,9 +75,9 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
73
75
|
await exchangeMessages(swarm1, swarm2);
|
|
74
76
|
await leaveSwarm([peer1, peer2], topic2);
|
|
75
77
|
}
|
|
76
|
-
});
|
|
78
|
+
}).tag('flaky');
|
|
77
79
|
|
|
78
|
-
test
|
|
80
|
+
test('joins multiple swarms', async () => {
|
|
79
81
|
// TODO(burdon): N peers.
|
|
80
82
|
// TODO(burdon): Merge with test below.
|
|
81
83
|
const peer1 = testBuilder.createPeer();
|
|
@@ -85,9 +87,9 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
85
87
|
const numSwarms = 5;
|
|
86
88
|
const topics = Array.from(Array(numSwarms)).map(() => PublicKey.random());
|
|
87
89
|
expect(topics).to.have.length(numSwarms);
|
|
88
|
-
});
|
|
90
|
+
}).tag('flaky');
|
|
89
91
|
|
|
90
|
-
test
|
|
92
|
+
test('joins multiple swarms concurrently', async () => {
|
|
91
93
|
const createSwarm = async () => {
|
|
92
94
|
const topicA = PublicKey.random();
|
|
93
95
|
const peer1a = testBuilder.createPeer();
|
|
@@ -107,9 +109,9 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
107
109
|
test1.swarm1a.protocol.testConnection(test1.peer2a.peerId),
|
|
108
110
|
test2.swarm1a.protocol.testConnection(test2.peer2a.peerId),
|
|
109
111
|
]);
|
|
110
|
-
});
|
|
112
|
+
}).tag('flaky');
|
|
111
113
|
|
|
112
|
-
test
|
|
114
|
+
test('peers reconnect after and error in connection', async () => {
|
|
113
115
|
const peer1 = testBuilder.createPeer();
|
|
114
116
|
const peer2 = testBuilder.createPeer();
|
|
115
117
|
await openAndCloseAfterTest([peer1, peer2]);
|
|
@@ -129,9 +131,9 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
129
131
|
await exchangeMessages(swarm1, swarm2);
|
|
130
132
|
|
|
131
133
|
await leaveSwarm([peer1, peer2], topic);
|
|
132
|
-
});
|
|
134
|
+
}).tag('flaky');
|
|
133
135
|
|
|
134
|
-
test
|
|
136
|
+
test('going offline and back online', async () => {
|
|
135
137
|
const peer1 = testBuilder.createPeer();
|
|
136
138
|
const peer2 = testBuilder.createPeer();
|
|
137
139
|
await openAndCloseAfterTest([peer1, peer2]);
|
|
@@ -156,31 +158,28 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
156
158
|
await peerLeft;
|
|
157
159
|
|
|
158
160
|
// Wait for peer to be removed from the swarm.
|
|
159
|
-
await
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
.toBe(false);
|
|
161
|
+
await waitForExpect(() => {
|
|
162
|
+
expect(!!peer2._networkManager.getSwarm(topic)!._peers.get({ peerKey: peer1.peerId.toHex() })?.advertizing).to.be
|
|
163
|
+
.false;
|
|
164
|
+
}, 1_000);
|
|
164
165
|
|
|
165
166
|
await peer1.goOnline();
|
|
166
167
|
|
|
167
|
-
await
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
.poll(() => peer2._networkManager.getSwarm(topic)?._peers.get({ peerKey: peer1.peerId.toHex() })?.advertizing, {
|
|
174
|
-
timeout: 2_000,
|
|
175
|
-
})
|
|
176
|
-
.toBe(true);
|
|
168
|
+
await waitForExpect(() => {
|
|
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;
|
|
173
|
+
}, 2_000);
|
|
177
174
|
|
|
178
175
|
await exchangeMessages(swarm1, swarm2);
|
|
179
176
|
await leaveSwarm([peer1, peer2], topic);
|
|
180
|
-
})
|
|
177
|
+
})
|
|
178
|
+
.tag('flaky')
|
|
179
|
+
.timeout(2_000);
|
|
181
180
|
|
|
182
181
|
// TODO(mykola): Fails with large amount of peers ~10.
|
|
183
|
-
test
|
|
182
|
+
test('many peers and connections', async () => {
|
|
184
183
|
const numTopics = 2;
|
|
185
184
|
const peersPerTopic = 3;
|
|
186
185
|
const swarmsAllPeersConnected: Promise<any>[] = [];
|
|
@@ -208,5 +207,5 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
208
207
|
);
|
|
209
208
|
|
|
210
209
|
await asyncTimeout(Promise.all(swarmsAllPeersConnected), 2_000);
|
|
211
|
-
});
|
|
210
|
+
}).tag('stress');
|
|
212
211
|
};
|