@dxos/network-manager 0.6.14-staging.e15392e → 0.7.0
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-RUNQZNCV.mjs → chunk-MAR4A5JK.mjs} +144 -85
- package/dist/lib/browser/chunk-MAR4A5JK.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 +15 -9
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-D6P7ACEM.cjs → chunk-J5PWZKEH.cjs} +147 -88
- package/dist/lib/node/chunk-J5PWZKEH.cjs.map +7 -0
- package/dist/lib/node/index.cjs +23 -23
- package/dist/lib/node/index.cjs.map +1 -1
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +28 -22
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/lib/node-esm/{chunk-22DA2US6.mjs → chunk-XHE7MQ7U.mjs} +144 -85
- package/dist/lib/node-esm/chunk-XHE7MQ7U.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1 -1
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +15 -9
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/types/src/swarm/peer.d.ts.map +1 -1
- package/dist/types/src/swarm/swarm.d.ts +1 -0
- package/dist/types/src/swarm/swarm.d.ts.map +1 -1
- package/dist/types/src/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/testing/test-wire-protocol.d.ts.map +1 -1
- package/dist/types/src/transport/webrtc/rtc-peer-connection.d.ts +4 -0
- package/dist/types/src/transport/webrtc/rtc-peer-connection.d.ts.map +1 -1
- package/dist/types/src/transport/webrtc/rtc-transport-channel.d.ts.map +1 -1
- package/dist/types/src/transport/webrtc/rtc-transport-factory.d.ts.map +1 -1
- package/dist/types/src/transport/webrtc/rtc-transport-service.d.ts.map +1 -1
- package/package.json +18 -18
- package/src/swarm/connection.ts +2 -2
- package/src/swarm/peer.ts +4 -1
- package/src/swarm/swarm.ts +15 -2
- package/src/testing/test-builder.ts +1 -0
- package/src/testing/test-wire-protocol.ts +6 -4
- package/src/tests/basic-test-suite.ts +13 -13
- package/src/tests/webrtc-transport.test.ts +1 -1
- package/src/transport/webrtc/rtc-peer-connection.ts +21 -7
- package/src/transport/webrtc/rtc-transport-channel.ts +7 -1
- package/src/transport/webrtc/rtc-transport-factory.ts +1 -0
- package/src/transport/webrtc/rtc-transport-service.ts +4 -2
- package/src/transport/webrtc/rtc-transport.test.ts +18 -6
- package/dist/lib/browser/chunk-RUNQZNCV.mjs.map +0 -7
- package/dist/lib/node/chunk-D6P7ACEM.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-22DA2US6.mjs.map +0 -7
package/src/swarm/connection.ts
CHANGED
|
@@ -234,10 +234,10 @@ export class Connection {
|
|
|
234
234
|
// TODO(nf): fix ErrorStream so instanceof works here
|
|
235
235
|
if (err instanceof ConnectionResetError) {
|
|
236
236
|
log.info('aborting due to transport ConnectionResetError');
|
|
237
|
-
this.abort().catch((err) => this.errors.raise(err));
|
|
237
|
+
this.abort(err).catch((err) => this.errors.raise(err));
|
|
238
238
|
} else if (err instanceof ConnectivityError) {
|
|
239
239
|
log.info('aborting due to transport ConnectivityError');
|
|
240
|
-
this.abort().catch((err) => this.errors.raise(err));
|
|
240
|
+
this.abort(err).catch((err) => this.errors.raise(err));
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
if (this._state !== ConnectionState.CLOSED && this._state !== ConnectionState.CLOSING) {
|
package/src/swarm/peer.ts
CHANGED
|
@@ -285,7 +285,8 @@ export class Peer {
|
|
|
285
285
|
});
|
|
286
286
|
},
|
|
287
287
|
onClosed: (err) => {
|
|
288
|
-
|
|
288
|
+
const logMeta = { topic: this.topic, peerId: this.localInfo, remoteId: this.remoteInfo, initiator };
|
|
289
|
+
log('connection closed', logMeta);
|
|
289
290
|
|
|
290
291
|
// Make sure none of the connections are stuck in the limiter.
|
|
291
292
|
this._connectionLimiter.doneConnecting(sessionId);
|
|
@@ -310,11 +311,13 @@ export class Peer {
|
|
|
310
311
|
this.availableToConnect = false;
|
|
311
312
|
this._availableAfter = increaseInterval(this._availableAfter);
|
|
312
313
|
}
|
|
314
|
+
|
|
313
315
|
this._callbacks.onDisconnected();
|
|
314
316
|
|
|
315
317
|
scheduleTask(
|
|
316
318
|
this._connectionCtx!,
|
|
317
319
|
() => {
|
|
320
|
+
log('peer became available', logMeta);
|
|
318
321
|
this.availableToConnect = true;
|
|
319
322
|
this._callbacks.onPeerAvailable();
|
|
320
323
|
},
|
package/src/swarm/swarm.ts
CHANGED
|
@@ -189,8 +189,10 @@ export class Swarm {
|
|
|
189
189
|
const peer = this._peers.get(swarmEvent.peerLeft.peer);
|
|
190
190
|
if (peer) {
|
|
191
191
|
peer.advertizing = false;
|
|
192
|
-
if
|
|
193
|
-
|
|
192
|
+
// Destroy peer only if there is no p2p-connection established. Otherwise, let peers go through
|
|
193
|
+
// the graceful shutdown protocol.
|
|
194
|
+
if (this._isConnectionEstablishmentInProgress(peer)) {
|
|
195
|
+
log(`destroying peer, state: ${peer.connection?.state}`);
|
|
194
196
|
void this._destroyPeer(swarmEvent.peerLeft.peer, 'peer left').catch((err) => log.catch(err));
|
|
195
197
|
}
|
|
196
198
|
} else {
|
|
@@ -277,6 +279,7 @@ export class Swarm {
|
|
|
277
279
|
},
|
|
278
280
|
onDisconnected: async () => {
|
|
279
281
|
if (this._isUnregistered(peer)) {
|
|
282
|
+
log.verbose('ignored onDisconnected for unregistered peer');
|
|
280
283
|
return;
|
|
281
284
|
}
|
|
282
285
|
if (!peer!.advertizing) {
|
|
@@ -312,6 +315,7 @@ export class Swarm {
|
|
|
312
315
|
}
|
|
313
316
|
|
|
314
317
|
private async _destroyPeer(peerInfo: PeerInfo, reason?: string) {
|
|
318
|
+
log('destroy peer', { peerKey: peerInfo.peerKey, reason });
|
|
315
319
|
const peer = this._peers.get(peerInfo);
|
|
316
320
|
invariant(peer);
|
|
317
321
|
this._peers.delete(peerInfo);
|
|
@@ -399,6 +403,15 @@ export class Swarm {
|
|
|
399
403
|
await peer.closeConnection();
|
|
400
404
|
}
|
|
401
405
|
|
|
406
|
+
private _isConnectionEstablishmentInProgress(peer: Peer) {
|
|
407
|
+
if (!peer.connection) {
|
|
408
|
+
return true;
|
|
409
|
+
}
|
|
410
|
+
return [ConnectionState.INITIAL, ConnectionState.CREATED, ConnectionState.CONNECTING].includes(
|
|
411
|
+
peer.connection.state,
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
|
|
402
415
|
private _isUnregistered(peer?: Peer): boolean {
|
|
403
416
|
return !peer || this._peers.get(peer.remoteInfo) !== peer;
|
|
404
417
|
}
|
|
@@ -84,6 +84,7 @@ export class TestPeer {
|
|
|
84
84
|
) {
|
|
85
85
|
this._signalManager = this.testBuilder.createSignalManager();
|
|
86
86
|
this._networkManager = this.createNetworkManager(this.transport);
|
|
87
|
+
this._networkManager.setPeerInfo({ identityKey: peerId.toHex(), peerKey: peerId.toHex() });
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
// TODO(burdon): Move to TestBuilder.
|
|
@@ -33,11 +33,13 @@ export class TestWireProtocol {
|
|
|
33
33
|
|
|
34
34
|
readonly factory = createTeleportProtocolFactory(async (teleport) => {
|
|
35
35
|
log('create', { remotePeerId: teleport.remotePeerId });
|
|
36
|
+
const handleDisconnect = () => {
|
|
37
|
+
this.connections.delete(teleport.remotePeerId);
|
|
38
|
+
this.disconnected.emit(teleport.remotePeerId);
|
|
39
|
+
};
|
|
36
40
|
const extension = new TestExtension({
|
|
37
|
-
onClose: async () =>
|
|
38
|
-
|
|
39
|
-
this.disconnected.emit(teleport.remotePeerId);
|
|
40
|
-
},
|
|
41
|
+
onClose: async () => handleDisconnect(),
|
|
42
|
+
onAbort: async () => handleDisconnect(),
|
|
41
43
|
});
|
|
42
44
|
this.connections.set(teleport.remotePeerId, extension);
|
|
43
45
|
teleport.addExtension('test', extension);
|
|
@@ -23,7 +23,7 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
test
|
|
26
|
+
test('joins swarm, sends messages, and cleanly exits', async () => {
|
|
27
27
|
const peer1 = testBuilder.createPeer();
|
|
28
28
|
const peer2 = testBuilder.createPeer();
|
|
29
29
|
await openAndCloseAfterTest([peer1, peer2]);
|
|
@@ -35,7 +35,7 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
// TODO(burdon): Test with more peers (configure and test messaging).
|
|
38
|
-
test
|
|
38
|
+
test('joins swarm with star topology', async () => {
|
|
39
39
|
const peer1 = testBuilder.createPeer();
|
|
40
40
|
onTestFinished(() => peer1.close());
|
|
41
41
|
const peer2 = testBuilder.createPeer();
|
|
@@ -49,7 +49,7 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
// TODO(burdon): Fails when trying to reconnect to same topic.
|
|
52
|
-
test
|
|
52
|
+
test('joins swarm multiple times', async () => {
|
|
53
53
|
const peer1 = testBuilder.createPeer();
|
|
54
54
|
const peer2 = testBuilder.createPeer();
|
|
55
55
|
await openAndCloseAfterTest([peer1, peer2]);
|
|
@@ -75,7 +75,7 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
-
test
|
|
78
|
+
test('joins multiple swarms', async () => {
|
|
79
79
|
// TODO(burdon): N peers.
|
|
80
80
|
// TODO(burdon): Merge with test below.
|
|
81
81
|
const peer1 = testBuilder.createPeer();
|
|
@@ -87,7 +87,7 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
87
87
|
expect(topics).to.have.length(numSwarms);
|
|
88
88
|
});
|
|
89
89
|
|
|
90
|
-
test
|
|
90
|
+
test('joins multiple swarms concurrently', async () => {
|
|
91
91
|
const createSwarm = async () => {
|
|
92
92
|
const topicA = PublicKey.random();
|
|
93
93
|
const peer1a = testBuilder.createPeer();
|
|
@@ -109,7 +109,7 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
109
109
|
]);
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
-
test
|
|
112
|
+
test('peers reconnect after and error in connection', async () => {
|
|
113
113
|
const peer1 = testBuilder.createPeer();
|
|
114
114
|
const peer2 = testBuilder.createPeer();
|
|
115
115
|
await openAndCloseAfterTest([peer1, peer2]);
|
|
@@ -118,20 +118,20 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
118
118
|
const [swarm1, swarm2] = await joinSwarm([peer1, peer2], topic, () => new FullyConnectedTopology());
|
|
119
119
|
await exchangeMessages(swarm1, swarm2);
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
const disconnectedKeys = new Set();
|
|
122
|
+
swarm1.protocol.disconnected.on((peerInfo) => disconnectedKeys.add(peerInfo.toHex()));
|
|
123
|
+
swarm2.protocol.disconnected.on((peerInfo) => disconnectedKeys.add(peerInfo.toHex()));
|
|
122
124
|
|
|
125
|
+
void swarm1.protocol.connections.get(swarm2.peer.peerId)!.closeConnection(new Error('test error'));
|
|
123
126
|
// Wait until both peers are disconnected.
|
|
124
|
-
await
|
|
125
|
-
swarm1.protocol.disconnected.waitForCondition(() => swarm1.protocol.connections.size === 0),
|
|
126
|
-
swarm2.protocol.disconnected.waitForCondition(() => swarm2.protocol.connections.size === 0),
|
|
127
|
-
]);
|
|
127
|
+
await expect.poll(() => disconnectedKeys.size).toEqual(2);
|
|
128
128
|
|
|
129
129
|
await exchangeMessages(swarm1, swarm2);
|
|
130
130
|
|
|
131
131
|
await leaveSwarm([peer1, peer2], topic);
|
|
132
132
|
});
|
|
133
133
|
|
|
134
|
-
test
|
|
134
|
+
test('going offline and back online', { timeout: 2_000 }, async () => {
|
|
135
135
|
const peer1 = testBuilder.createPeer();
|
|
136
136
|
const peer2 = testBuilder.createPeer();
|
|
137
137
|
await openAndCloseAfterTest([peer1, peer2]);
|
|
@@ -180,7 +180,7 @@ export const basicTestSuite = (testBuilder: TestBuilder, runTests = true) => {
|
|
|
180
180
|
});
|
|
181
181
|
|
|
182
182
|
// TODO(mykola): Fails with large amount of peers ~10.
|
|
183
|
-
test
|
|
183
|
+
test('many peers and connections', async () => {
|
|
184
184
|
const numTopics = 2;
|
|
185
185
|
const peersPerTopic = 3;
|
|
186
186
|
const swarmsAllPeersConnected: Promise<any>[] = [];
|
|
@@ -17,7 +17,7 @@ describe('WebRTC transport proxy', { timeout: 10_000 }, () => {
|
|
|
17
17
|
basicTestSuite(testBuilder);
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
describe('test with signal server', () => {
|
|
20
|
+
describe.skip('test with signal server', () => {
|
|
21
21
|
describe('WebRTC transport', { timeout: 10_000 }, () => {
|
|
22
22
|
const testBuilder = new TestBuilder({ signalHosts: TEST_SIGNAL_HOSTS });
|
|
23
23
|
basicTestSuite(testBuilder);
|
|
@@ -26,8 +26,18 @@ export type RtcPeerChannelFactoryOptions = {
|
|
|
26
26
|
// https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection#iceservers
|
|
27
27
|
webrtcConfig?: RTCConfiguration;
|
|
28
28
|
iceProvider?: IceProvider;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* TODO: remove after the new rtc code rollout. Used for staging interop with older version running in prod.
|
|
32
|
+
*/
|
|
33
|
+
legacyInitiator?: boolean;
|
|
29
34
|
};
|
|
30
35
|
|
|
36
|
+
/**
|
|
37
|
+
* TODO: remove after the new rtc code rollout. Used for staging interop with older version running in prod.
|
|
38
|
+
*/
|
|
39
|
+
const isLegacyInteropEnabled = () => Boolean((globalThis as any)?.DEVICE_INVITE_INTEROP);
|
|
40
|
+
|
|
31
41
|
/**
|
|
32
42
|
* A factory for rtc Transport implementations for a particular peer.
|
|
33
43
|
* Contains WebRTC connection establishment logic.
|
|
@@ -59,7 +69,9 @@ export class RtcPeerConnection {
|
|
|
59
69
|
private readonly _factory: RtcConnectionFactory,
|
|
60
70
|
private readonly _options: RtcPeerChannelFactoryOptions,
|
|
61
71
|
) {
|
|
62
|
-
this._initiator =
|
|
72
|
+
this._initiator = isLegacyInteropEnabled()
|
|
73
|
+
? Boolean(this._options.legacyInitiator)
|
|
74
|
+
: chooseInitiatorPeer(_options.ownPeerKey, _options.remotePeerKey) === _options.ownPeerKey;
|
|
63
75
|
}
|
|
64
76
|
|
|
65
77
|
public get transportChannelCount() {
|
|
@@ -71,25 +83,27 @@ export class RtcPeerConnection {
|
|
|
71
83
|
}
|
|
72
84
|
|
|
73
85
|
public async createDataChannel(topic: string): Promise<RTCDataChannel> {
|
|
86
|
+
const channelKey = isLegacyInteropEnabled() ? 'dxos.mesh.transport' : topic;
|
|
87
|
+
|
|
74
88
|
const connection = await this._openConnection();
|
|
75
|
-
if (!this._transportChannels.has(
|
|
89
|
+
if (isLegacyInteropEnabled() ? this._transportChannels.size === 0 : !this._transportChannels.has(channelKey)) {
|
|
76
90
|
if (!this._transportChannels.size) {
|
|
77
91
|
this._lockAndCloseConnection();
|
|
78
92
|
}
|
|
79
93
|
throw new Error('Transport closed while connection was being open');
|
|
80
94
|
}
|
|
81
95
|
if (this._initiator) {
|
|
82
|
-
const channel = connection.createDataChannel(
|
|
83
|
-
this._dataChannels.set(
|
|
96
|
+
const channel = connection.createDataChannel(channelKey);
|
|
97
|
+
this._dataChannels.set(channelKey, channel);
|
|
84
98
|
return channel;
|
|
85
99
|
} else {
|
|
86
|
-
const existingChannel = this._dataChannels.get(
|
|
100
|
+
const existingChannel = this._dataChannels.get(channelKey);
|
|
87
101
|
if (existingChannel) {
|
|
88
102
|
return existingChannel;
|
|
89
103
|
}
|
|
90
104
|
log('waiting for initiator-peer to open a data channel');
|
|
91
105
|
return new Promise((resolve, reject) => {
|
|
92
|
-
this._channelCreatedCallbacks.set(
|
|
106
|
+
this._channelCreatedCallbacks.set(channelKey, { resolve, reject });
|
|
93
107
|
});
|
|
94
108
|
}
|
|
95
109
|
}
|
|
@@ -327,7 +341,7 @@ export class RtcPeerConnection {
|
|
|
327
341
|
break;
|
|
328
342
|
}
|
|
329
343
|
|
|
330
|
-
log('signal processed');
|
|
344
|
+
log('signal processed', { type: data.type });
|
|
331
345
|
}
|
|
332
346
|
|
|
333
347
|
private async _processIceCandidate(connection: RTCPeerConnection, candidate: RTCIceCandidate) {
|
|
@@ -67,7 +67,13 @@ export class RtcTransportChannel extends Resource implements Transport {
|
|
|
67
67
|
})
|
|
68
68
|
.catch((err) => {
|
|
69
69
|
if (this.isOpen) {
|
|
70
|
-
|
|
70
|
+
const error =
|
|
71
|
+
err instanceof Error
|
|
72
|
+
? err
|
|
73
|
+
: new ConnectivityError(`Failed to create a channel: ${JSON.stringify(err?.message)}`);
|
|
74
|
+
this.errors.raise(error);
|
|
75
|
+
} else {
|
|
76
|
+
log.verbose('connection establishment failed after transport was closed', { err });
|
|
71
77
|
}
|
|
72
78
|
})
|
|
73
79
|
.finally(() => {
|
|
@@ -88,8 +88,6 @@ export class RtcTransportService implements BridgeService {
|
|
|
88
88
|
writeProcessedCallbacks: [],
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
-
pushNewState(ConnectionState.CONNECTING);
|
|
92
|
-
|
|
93
91
|
transport.connected.on(() => pushNewState(ConnectionState.CONNECTED));
|
|
94
92
|
|
|
95
93
|
transport.errors.handle(async (err) => {
|
|
@@ -113,6 +111,10 @@ export class RtcTransportService implements BridgeService {
|
|
|
113
111
|
});
|
|
114
112
|
|
|
115
113
|
ready();
|
|
114
|
+
|
|
115
|
+
log('stream ready');
|
|
116
|
+
|
|
117
|
+
pushNewState(ConnectionState.CONNECTING);
|
|
116
118
|
});
|
|
117
119
|
}
|
|
118
120
|
|
|
@@ -126,12 +126,20 @@ describe('RtcTransport', () => {
|
|
|
126
126
|
|
|
127
127
|
const createSignalSender = (options?: { duplicateSignals?: boolean }) => {
|
|
128
128
|
const deliverSignal = (channel: RtcTransportChannel, signal: any) => {
|
|
129
|
+
// There's a race in libdatachannel between ice candidate gathering, connectivity checks and dtls connection
|
|
130
|
+
// establishment, which seems to be 100% reproducible when there are only host candidates.
|
|
131
|
+
// When there are no iceServers the first pair attempt starts too fast and gets interrupted by an arriving
|
|
132
|
+
// remote candidate. Dtls has a retry backoff which starts with 1 second delay, so all tests finish in 1s+.
|
|
133
|
+
if (signal.payload.data.type === 'candidate' && !isInitiator) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
129
136
|
void channel.onSignal(signal);
|
|
130
137
|
if (options?.duplicateSignals) {
|
|
131
138
|
void channel.onSignal(signal);
|
|
132
139
|
}
|
|
133
140
|
};
|
|
134
141
|
let remoteChannel: RtcTransportChannel | undefined;
|
|
142
|
+
let isInitiator = false;
|
|
135
143
|
const signalBuffer: any[] = [];
|
|
136
144
|
const sendSignal = async (signal: any) => {
|
|
137
145
|
await sleep(10);
|
|
@@ -141,7 +149,8 @@ describe('RtcTransport', () => {
|
|
|
141
149
|
signalBuffer.push(signal);
|
|
142
150
|
}
|
|
143
151
|
};
|
|
144
|
-
const onChannelCreated = (channel: RtcTransportChannel
|
|
152
|
+
const onChannelCreated = (channel: RtcTransportChannel, initiator: boolean) => {
|
|
153
|
+
isInitiator = initiator;
|
|
145
154
|
remoteChannel = channel;
|
|
146
155
|
for (const signal of signalBuffer) {
|
|
147
156
|
deliverSignal(channel, signal);
|
|
@@ -152,20 +161,23 @@ describe('RtcTransport', () => {
|
|
|
152
161
|
|
|
153
162
|
const createConnection = async (
|
|
154
163
|
optionOverrides?: Partial<TransportOptions>,
|
|
155
|
-
onChannelCreated: (channel: RtcTransportChannel) => void = () => {},
|
|
164
|
+
onChannelCreated: (channel: RtcTransportChannel, initiator: boolean) => void = () => {},
|
|
156
165
|
): Promise<TestSetup> => {
|
|
166
|
+
const remotePeerKey = optionOverrides?.remotePeerKey ?? PublicKey.random().toHex();
|
|
167
|
+
const ownPeerKey = optionOverrides?.ownPeerKey ?? PublicKey.random().toHex();
|
|
168
|
+
const initiator = chooseInitiatorPeer(remotePeerKey, ownPeerKey) === ownPeerKey;
|
|
157
169
|
const stream = new TestStream();
|
|
158
170
|
const options: TransportOptions = {
|
|
159
|
-
initiator
|
|
171
|
+
initiator,
|
|
160
172
|
stream,
|
|
161
173
|
sendSignal: async () => {},
|
|
162
|
-
remotePeerKey
|
|
163
|
-
ownPeerKey
|
|
174
|
+
remotePeerKey,
|
|
175
|
+
ownPeerKey,
|
|
164
176
|
topic: PublicKey.random().toHex(),
|
|
165
177
|
...optionOverrides,
|
|
166
178
|
};
|
|
167
179
|
const connection = new RtcPeerConnection(connectionFactory, options);
|
|
168
|
-
return { options, connection, stream, onChannelOpen: onChannelCreated };
|
|
180
|
+
return { options, connection, stream, onChannelOpen: (channel) => onChannelCreated(channel, initiator) };
|
|
169
181
|
};
|
|
170
182
|
|
|
171
183
|
const chooseInitiator = (peer1: TestSetup, peer2: TestSetup) => {
|