@dxos/network-manager 0.1.56-main.c787da3 → 0.1.56-main.e47dfd1
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-MIYEP22D.mjs → chunk-5R7TDXUU.mjs} +323 -229
- package/dist/lib/browser/chunk-5R7TDXUU.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +5 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +1 -1
- package/dist/lib/node/index.cjs +318 -222
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +314 -222
- package/dist/lib/node/testing/index.cjs.map +4 -4
- package/dist/types/src/network-manager.d.ts +1 -1
- package/dist/types/src/network-manager.d.ts.map +1 -1
- package/dist/types/src/swarm/connection-limiter.d.ts +28 -0
- package/dist/types/src/swarm/connection-limiter.d.ts.map +1 -0
- package/dist/types/src/swarm/connection-limiter.test.d.ts +2 -0
- package/dist/types/src/swarm/connection-limiter.test.d.ts.map +1 -0
- package/dist/types/src/swarm/connection.d.ts +1 -1
- package/dist/types/src/swarm/connection.d.ts.map +1 -1
- package/dist/types/src/swarm/connection.test.d.ts +2 -0
- package/dist/types/src/swarm/connection.test.d.ts.map +1 -0
- package/dist/types/src/swarm/index.d.ts +1 -0
- package/dist/types/src/swarm/index.d.ts.map +1 -1
- package/dist/types/src/swarm/peer.d.ts +3 -1
- package/dist/types/src/swarm/peer.d.ts.map +1 -1
- package/dist/types/src/swarm/swarm.d.ts +3 -1
- package/dist/types/src/swarm/swarm.d.ts.map +1 -1
- package/package.json +17 -17
- package/src/network-manager.ts +18 -4
- package/src/swarm/connection-limiter.test.ts +44 -0
- package/src/swarm/connection-limiter.ts +71 -0
- package/src/swarm/connection.test.ts +72 -0
- package/src/swarm/connection.ts +1 -2
- package/src/swarm/index.ts +1 -0
- package/src/swarm/peer.ts +22 -7
- package/src/swarm/swarm.test.ts +140 -90
- package/src/swarm/swarm.ts +3 -1
- package/dist/lib/browser/chunk-MIYEP22D.mjs.map +0 -7
|
@@ -45,12 +45,12 @@ export type NetworkManagerOptions = {
|
|
|
45
45
|
* Manages connection to the swarm.
|
|
46
46
|
*/
|
|
47
47
|
export declare class NetworkManager {
|
|
48
|
-
private readonly _swarms;
|
|
49
48
|
private readonly _mappers;
|
|
50
49
|
private readonly _transportFactory;
|
|
51
50
|
private readonly _signalManager;
|
|
52
51
|
private readonly _messenger;
|
|
53
52
|
private readonly _signalConnection;
|
|
53
|
+
private readonly _connectionLimiter;
|
|
54
54
|
private _connectionState;
|
|
55
55
|
readonly connectionStateChanged: Event<ConnectionState>;
|
|
56
56
|
private readonly _connectionLog?;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network-manager.d.ts","sourceRoot":"","sources":["../../../src/network-manager.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAa,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAG7E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,KAAK,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"network-manager.d.ts","sourceRoot":"","sources":["../../../src/network-manager.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAa,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAG7E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAqB,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAGF,MAAM,MAAM,YAAY,GAAG;IACzB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,MAAM,EAAE,SAAS,CAAC;IAElB;;OAEG;IACH,gBAAgB,EAAE,oBAAoB,CAAC;IAEvC;;OAEG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAEpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAEF;;GAEG;AAEH,qBAAa,cAAc;IAKzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0D;IAEnF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAoB;IAEvD,OAAO,CAAC,gBAAgB,CAA0B;IAClD,SAAgB,sBAAsB,yBAAgC;IAEtE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAgB;IAEhD,SAAgB,aAAa,cAAqB;IAElD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;gBAE9C,EAAE,gBAAgB,EAAE,aAAa,EAAE,GAAG,EAAE,EAAE,qBAAqB;IAoB3E,IAAI,aAAa,8BAEhB;IAED,IAAI,eAAe,oBAElB;IAGD,IAAI,MAAM,gBAET;IAED,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS;IAItD,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,GAAG,SAAS;IAIvC,IAAI;IAOJ,KAAK;IAWX;;OAEG;IACG,SAAS,CAAC,EACd,KAAK,EACL,MAAM,EACN,QAAQ,EACR,gBAAgB,EAAE,QAAQ,EAC1B,KAAK,GACN,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC;IA0C1C;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,SAAS;IAuB3B,kBAAkB,CAAC,KAAK,EAAE,eAAe;CA0BhD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DeferredTask } from '@dxos/async';
|
|
2
|
+
import { PublicKey } from '@dxos/keys';
|
|
3
|
+
export declare const MAX_CONCURRENT_INITIATING_CONNECTIONS = 3;
|
|
4
|
+
export type ConnectionLimiterOptions = {
|
|
5
|
+
maxConcurrentInitConnections?: number;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Limits the amount of concurrent connections with 'CONNECTING' state.
|
|
9
|
+
*/
|
|
10
|
+
export declare class ConnectionLimiter {
|
|
11
|
+
private readonly _ctx;
|
|
12
|
+
private readonly _maxConcurrentInitConnections;
|
|
13
|
+
/**
|
|
14
|
+
* Queue of promises to resolve when initiating connections amount is below the limit.
|
|
15
|
+
*/
|
|
16
|
+
private readonly _waitingPromises;
|
|
17
|
+
resolveWaitingPromises: DeferredTask;
|
|
18
|
+
constructor({ maxConcurrentInitConnections }?: ConnectionLimiterOptions);
|
|
19
|
+
/**
|
|
20
|
+
* @returns Promise that resolves in queue when connections amount with 'CONNECTING' state is below the limit.
|
|
21
|
+
*/
|
|
22
|
+
connecting(sessionId: PublicKey): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Rejects promise returned by `connecting` method.
|
|
25
|
+
*/
|
|
26
|
+
doneConnecting(sessionId: PublicKey): void;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=connection-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-limiter.d.ts","sourceRoot":"","sources":["../../../../src/swarm/connection-limiter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIvC,eAAO,MAAM,qCAAqC,IAAI,CAAC;AAEvD,MAAM,MAAM,wBAAwB,GAAG;IACrC,4BAA4B,CAAC,EAAE,MAAM,CAAC;CACvC,CAAC;AAEF;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;IACtC,OAAO,CAAC,QAAQ,CAAC,6BAA6B,CAAC;IAC/C;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAE/B;IAEF,sBAAsB,eAMnB;gBAES,EAAE,4BAAoE,EAAE,GAAE,wBAA6B;IAInH;;OAEG;IACG,UAAU,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAarD;;OAEG;IACH,cAAc,CAAC,SAAS,EAAE,SAAS;CASpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-limiter.test.d.ts","sourceRoot":"","sources":["../../../../src/swarm/connection-limiter.test.ts"],"names":[],"mappings":""}
|
|
@@ -61,7 +61,7 @@ export declare class Connection {
|
|
|
61
61
|
/**
|
|
62
62
|
* Create an underlying transport and prepares it for the connection.
|
|
63
63
|
*/
|
|
64
|
-
openConnection(): void
|
|
64
|
+
openConnection(): Promise<void>;
|
|
65
65
|
close(): Promise<void>;
|
|
66
66
|
private _sendSignal;
|
|
67
67
|
private _flushSignalBuffer;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../../src/swarm/connection.ts"],"names":[],"mappings":"AAMA,OAAO,EAAgB,KAAK,EAAuB,MAAM,aAAa,CAAC;AAEvE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAKvC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAahD;;GAEG;AACH,oBAAY,eAAe;IACzB;;;OAGG;IACH,OAAO,YAAY;IAEnB;;OAEG;IACH,UAAU,eAAe;IAEzB;;OAEG;IACH,SAAS,cAAc;IAEvB;;OAEG;IACH,OAAO,YAAY;IAEnB;;OAEG;IACH,MAAM,WAAW;CAClB;AAED;;;GAGG;AACH,qBAAa,UAAU;aAqBH,KAAK,EAAE,SAAS;aAChB,KAAK,EAAE,SAAS;aAChB,QAAQ,EAAE,SAAS;aACnB,SAAS,EAAE,SAAS;aACpB,SAAS,EAAE,OAAO;IAClC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IA3BpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;IAEtC,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,UAAU,CAAwB;IAE1C,OAAO,CAAC,qBAAqB,CAAgB;IAC7C,OAAO,CAAC,qBAAqB,CAAgB;IAE7C,QAAQ,CAAC,YAAY,yBAAgC;IACrD,QAAQ,CAAC,MAAM,cAAqB;IAE7B,WAAW,SAA8B;IAEhD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAE7B;IAEH,OAAO,CAAC,gBAAgB,CAA6B;gBAGnC,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,SAAS,EAAE,wBAAwB;IAC1C,QAAQ,EAAE,SAAS,EACnB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,OAAO,EACjB,gBAAgB,EAAE,eAAe,EACjC,SAAS,EAAE,YAAY,EACvB,iBAAiB,EAAE,gBAAgB;IAGtD,IAAI,KAAK,oBAER;IAED,IAAI,SAAS,0BAEZ;IAED,IAAI,QAAQ,iBAEX;IAED;;OAEG;
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../../src/swarm/connection.ts"],"names":[],"mappings":"AAMA,OAAO,EAAgB,KAAK,EAAuB,MAAM,aAAa,CAAC;AAEvE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAKvC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAahD;;GAEG;AACH,oBAAY,eAAe;IACzB;;;OAGG;IACH,OAAO,YAAY;IAEnB;;OAEG;IACH,UAAU,eAAe;IAEzB;;OAEG;IACH,SAAS,cAAc;IAEvB;;OAEG;IACH,OAAO,YAAY;IAEnB;;OAEG;IACH,MAAM,WAAW;CAClB;AAED;;;GAGG;AACH,qBAAa,UAAU;aAqBH,KAAK,EAAE,SAAS;aAChB,KAAK,EAAE,SAAS;aAChB,QAAQ,EAAE,SAAS;aACnB,SAAS,EAAE,SAAS;aACpB,SAAS,EAAE,OAAO;IAClC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IA3BpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;IAEtC,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,UAAU,CAAwB;IAE1C,OAAO,CAAC,qBAAqB,CAAgB;IAC7C,OAAO,CAAC,qBAAqB,CAAgB;IAE7C,QAAQ,CAAC,YAAY,yBAAgC;IACrD,QAAQ,CAAC,MAAM,cAAqB;IAE7B,WAAW,SAA8B;IAEhD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAE7B;IAEH,OAAO,CAAC,gBAAgB,CAA6B;gBAGnC,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,SAAS,EAAE,wBAAwB;IAC1C,QAAQ,EAAE,SAAS,EACnB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,OAAO,EACjB,gBAAgB,EAAE,eAAe,EACjC,SAAS,EAAE,YAAY,EACvB,iBAAiB,EAAE,gBAAgB;IAGtD,IAAI,KAAK,oBAER;IAED,IAAI,SAAS,0BAEZ;IAED,IAAI,QAAQ,iBAEX;IAED;;OAEG;IACG,cAAc;IAkDd,KAAK;IA4BX,OAAO,CAAC,WAAW;YAKL,kBAAkB;IA8BhC;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,aAAa;IA2B/B,OAAO,CAAC,YAAY;CAMrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.test.d.ts","sourceRoot":"","sources":["../../../../src/swarm/connection.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/swarm/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/swarm/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC"}
|
|
@@ -4,6 +4,7 @@ import { OfferMessage, SignalMessage, SignalMessenger } from '../signal';
|
|
|
4
4
|
import { TransportFactory } from '../transport';
|
|
5
5
|
import { WireProtocolProvider } from '../wire-protocol';
|
|
6
6
|
import { Connection } from './connection';
|
|
7
|
+
import { ConnectionLimiter } from './connection-limiter';
|
|
7
8
|
interface PeerCallbacks {
|
|
8
9
|
/**
|
|
9
10
|
* Connection attempt initiated.
|
|
@@ -45,6 +46,7 @@ export declare class Peer {
|
|
|
45
46
|
private readonly _signalMessaging;
|
|
46
47
|
private readonly _protocolProvider;
|
|
47
48
|
private readonly _transportFactory;
|
|
49
|
+
private readonly _connectionLimiter;
|
|
48
50
|
private readonly _callbacks;
|
|
49
51
|
/**
|
|
50
52
|
* Will be available to connect after this time.
|
|
@@ -60,7 +62,7 @@ export declare class Peer {
|
|
|
60
62
|
*/
|
|
61
63
|
advertizing: boolean;
|
|
62
64
|
initiating: boolean;
|
|
63
|
-
constructor(id: PublicKey, topic: PublicKey, localPeerId: PublicKey, _signalMessaging: SignalMessenger, _protocolProvider: WireProtocolProvider, _transportFactory: TransportFactory, _callbacks: PeerCallbacks);
|
|
65
|
+
constructor(id: PublicKey, topic: PublicKey, localPeerId: PublicKey, _signalMessaging: SignalMessenger, _protocolProvider: WireProtocolProvider, _transportFactory: TransportFactory, _connectionLimiter: ConnectionLimiter, _callbacks: PeerCallbacks);
|
|
64
66
|
/**
|
|
65
67
|
* Respond to remote offer.
|
|
66
68
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"peer.d.ts","sourceRoot":"","sources":["../../../../src/swarm/peer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"peer.d.ts","sourceRoot":"","sources":["../../../../src/swarm/peer.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAE/D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAmB,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,UAAU,aAAa;IACrB;;OAEG;IACH,WAAW,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAE9C;;OAEG;IACH,WAAW,EAAE,MAAM,IAAI,CAAC;IAExB;;OAEG;IACH,cAAc,EAAE,MAAM,IAAI,CAAC;IAE3B;;OAEG;IACH,UAAU,EAAE,MAAM,IAAI,CAAC;IAEvB;;OAEG;IACH,UAAU,EAAE,MAAM,IAAI,CAAC;IAEvB;;OAEG;IACH,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAEnD;;OAEG;IACH,eAAe,EAAE,MAAM,IAAI,CAAC;CAC7B;AAOD;;;GAGG;AACH,qBAAa,IAAI;aAoBG,EAAE,EAAE,SAAS;aACb,KAAK,EAAE,SAAS;aAChB,WAAW,EAAE,SAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU;IA1B7B;;OAEG;IACH,OAAO,CAAC,eAAe,CAAK;IACrB,kBAAkB,UAAQ;IACjC,OAAO,CAAC,mBAAmB,CAAC,CAAS;IAErC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;IACtC,OAAO,CAAC,cAAc,CAAC,CAAU;IAE1B,UAAU,CAAC,EAAE,UAAU,CAAC;IAE/B;;OAEG;IACI,WAAW,UAAS;IAEpB,UAAU,UAAS;gBAER,EAAE,EAAE,SAAS,EACb,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,SAAS,EACrB,gBAAgB,EAAE,eAAe,EACjC,iBAAiB,EAAE,oBAAoB,EACvC,iBAAiB,EAAE,gBAAgB,EACnC,kBAAkB,EAAE,iBAAiB,EACrC,UAAU,EAAE,aAAa;IAG5C;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAiDrD;;OAEG;IACG,kBAAkB;IAyCxB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IA8EnB,eAAe;IAcf,QAAQ,CAAC,OAAO,EAAE,aAAa;IAU/B,OAAO;CAOd"}
|
|
@@ -9,6 +9,7 @@ import { TransportFactory } from '../transport';
|
|
|
9
9
|
import { Topic } from '../types';
|
|
10
10
|
import { WireProtocolProvider } from '../wire-protocol';
|
|
11
11
|
import { Connection } from './connection';
|
|
12
|
+
import { ConnectionLimiter } from './connection-limiter';
|
|
12
13
|
/**
|
|
13
14
|
* A single peer's view of the swarm.
|
|
14
15
|
* Manages a set of connections implemented by simple-peer instances.
|
|
@@ -22,6 +23,7 @@ export declare class Swarm {
|
|
|
22
23
|
private readonly _messenger;
|
|
23
24
|
private readonly _transportFactory;
|
|
24
25
|
private readonly _label;
|
|
26
|
+
private readonly _connectionLimiter;
|
|
25
27
|
private readonly _swarmMessenger;
|
|
26
28
|
private _ctx;
|
|
27
29
|
private _listeningHandle?;
|
|
@@ -30,7 +32,7 @@ export declare class Swarm {
|
|
|
30
32
|
*/
|
|
31
33
|
readonly _instanceId: string;
|
|
32
34
|
readonly errors: ErrorStream;
|
|
33
|
-
constructor(_topic: PublicKey, _ownPeerId: PublicKey, _topology: Topology, _protocolProvider: WireProtocolProvider, _messenger: Messenger, _transportFactory: TransportFactory, _label: string | undefined);
|
|
35
|
+
constructor(_topic: PublicKey, _ownPeerId: PublicKey, _topology: Topology, _protocolProvider: WireProtocolProvider, _messenger: Messenger, _transportFactory: TransportFactory, _label: string | undefined, _connectionLimiter: ConnectionLimiter);
|
|
34
36
|
get connections(): Connection[];
|
|
35
37
|
get ownPeerId(): PublicKey;
|
|
36
38
|
/**
|
|
@@ -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,EAAmB,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAG/D,OAAO,EAAkB,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACxE,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;
|
|
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,EAAmB,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAG/D,OAAO,EAAkB,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACxE,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;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAQzD;;;;GAIG;AACH,qBAAa,KAAK;IA0Cd,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;IACvB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IA3CrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IAEjD,OAAO,CAAC,IAAI,CAAiB;IAE7B,OAAO,CAAC,gBAAgB,CAAC,CAA8B;IAEvD;;OAEG;IAEH,QAAQ,CAAC,WAAW,SAA8B;IAoBlD,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,EAC1B,kBAAkB,EAAE,iBAAiB;IAkBxD,IAAI,WAAW,iBAId;IAED,IACI,SAAS,cAEZ;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAE9B;IAED,IACI,KAAK,IAAI,KAAK,CAEjB;IAEK,IAAI;IAaJ,OAAO;IAWP,WAAW,CAAC,QAAQ,EAAE,QAAQ;IAiBpC,YAAY,CAAC,UAAU,EAAE,UAAU;IA8B7B,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAwB/C,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB/C,SAAS;IAOT,QAAQ;IAId,OAAO,CAAC,gBAAgB;YAkDV,YAAY;IAM1B,OAAO,CAAC,mBAAmB;IAuC3B;;OAEG;YACW,mBAAmB;YA0BnB,gBAAgB;CAQ/B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/network-manager",
|
|
3
|
-
"version": "0.1.56-main.
|
|
3
|
+
"version": "0.1.56-main.e47dfd1",
|
|
4
4
|
"description": "Network Manager",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -26,21 +26,21 @@
|
|
|
26
26
|
"tiny-invariant": "^1.3.1",
|
|
27
27
|
"ws": "^7.4.4",
|
|
28
28
|
"xor-distance": "^2.0.0",
|
|
29
|
-
"@dxos/async": "0.1.56-main.
|
|
30
|
-
"@dxos/codec-protobuf": "0.1.56-main.
|
|
31
|
-
"@dxos/context": "0.1.56-main.
|
|
32
|
-
"@dxos/credentials": "0.1.56-main.
|
|
33
|
-
"@dxos/crypto": "0.1.56-main.
|
|
34
|
-
"@dxos/debug": "0.1.56-main.
|
|
35
|
-
"@dxos/errors": "0.1.56-main.
|
|
36
|
-
"@dxos/keys": "0.1.56-main.
|
|
37
|
-
"@dxos/log": "0.1.56-main.
|
|
38
|
-
"@dxos/messaging": "0.1.56-main.
|
|
39
|
-
"@dxos/node-std": "0.1.56-main.
|
|
40
|
-
"@dxos/protocols": "0.1.56-main.
|
|
41
|
-
"@dxos/rpc": "0.1.56-main.
|
|
42
|
-
"@dxos/teleport": "0.1.56-main.
|
|
43
|
-
"@dxos/util": "0.1.56-main.
|
|
29
|
+
"@dxos/async": "0.1.56-main.e47dfd1",
|
|
30
|
+
"@dxos/codec-protobuf": "0.1.56-main.e47dfd1",
|
|
31
|
+
"@dxos/context": "0.1.56-main.e47dfd1",
|
|
32
|
+
"@dxos/credentials": "0.1.56-main.e47dfd1",
|
|
33
|
+
"@dxos/crypto": "0.1.56-main.e47dfd1",
|
|
34
|
+
"@dxos/debug": "0.1.56-main.e47dfd1",
|
|
35
|
+
"@dxos/errors": "0.1.56-main.e47dfd1",
|
|
36
|
+
"@dxos/keys": "0.1.56-main.e47dfd1",
|
|
37
|
+
"@dxos/log": "0.1.56-main.e47dfd1",
|
|
38
|
+
"@dxos/messaging": "0.1.56-main.e47dfd1",
|
|
39
|
+
"@dxos/node-std": "0.1.56-main.e47dfd1",
|
|
40
|
+
"@dxos/protocols": "0.1.56-main.e47dfd1",
|
|
41
|
+
"@dxos/rpc": "0.1.56-main.e47dfd1",
|
|
42
|
+
"@dxos/teleport": "0.1.56-main.e47dfd1",
|
|
43
|
+
"@dxos/util": "0.1.56-main.e47dfd1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@swc-node/register": "1.5.4",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"earljs": "~0.1.10",
|
|
51
51
|
"fast-check": "~3.3.0",
|
|
52
52
|
"typescript": "^5.0.4",
|
|
53
|
-
"@dxos/signal": "0.1.56-main.
|
|
53
|
+
"@dxos/signal": "0.1.56-main.e47dfd1"
|
|
54
54
|
},
|
|
55
55
|
"publishConfig": {
|
|
56
56
|
"access": "public"
|
package/src/network-manager.ts
CHANGED
|
@@ -14,11 +14,10 @@ import { ComplexMap } from '@dxos/util';
|
|
|
14
14
|
|
|
15
15
|
import { ConnectionLog } from './connection-log';
|
|
16
16
|
import { SignalConnection } from './signal';
|
|
17
|
-
import { Swarm, SwarmMapper } from './swarm';
|
|
17
|
+
import { Swarm, SwarmMapper, ConnectionLimiter } from './swarm';
|
|
18
18
|
import { Topology } from './topology';
|
|
19
19
|
import { TransportFactory } from './transport';
|
|
20
20
|
import { WireProtocolProvider } from './wire-protocol';
|
|
21
|
-
|
|
22
21
|
/**
|
|
23
22
|
* Represents a single connection to a remote peer.
|
|
24
23
|
*/
|
|
@@ -66,13 +65,17 @@ export type NetworkManagerOptions = {
|
|
|
66
65
|
*/
|
|
67
66
|
// TODO(dmaretskyi): Rename SwarmManager.
|
|
68
67
|
export class NetworkManager {
|
|
69
|
-
|
|
68
|
+
/**
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
readonly _swarms = new ComplexMap<PublicKey, Swarm>(PublicKey.hash);
|
|
70
72
|
private readonly _mappers = new ComplexMap<PublicKey, SwarmMapper>(PublicKey.hash);
|
|
71
73
|
|
|
72
74
|
private readonly _transportFactory: TransportFactory;
|
|
73
75
|
private readonly _signalManager: SignalManager;
|
|
74
76
|
private readonly _messenger: Messenger;
|
|
75
77
|
private readonly _signalConnection: SignalConnection;
|
|
78
|
+
private readonly _connectionLimiter: ConnectionLimiter;
|
|
76
79
|
|
|
77
80
|
private _connectionState = ConnectionState.ONLINE;
|
|
78
81
|
public readonly connectionStateChanged = new Event<ConnectionState>();
|
|
@@ -95,6 +98,7 @@ export class NetworkManager {
|
|
|
95
98
|
leave: (opts) => this._signalManager.leave(opts),
|
|
96
99
|
};
|
|
97
100
|
|
|
101
|
+
this._connectionLimiter = new ConnectionLimiter();
|
|
98
102
|
// TODO(burdon): Inject listener (generic pattern).
|
|
99
103
|
if (log) {
|
|
100
104
|
this._connectionLog = new ConnectionLog();
|
|
@@ -160,7 +164,17 @@ export class NetworkManager {
|
|
|
160
164
|
}
|
|
161
165
|
|
|
162
166
|
log('joining', { topic: PublicKey.from(topic), peerId, topology: topology.toString() }); // TODO(burdon): Log peerId.
|
|
163
|
-
const swarm = new Swarm(
|
|
167
|
+
const swarm = new Swarm(
|
|
168
|
+
topic,
|
|
169
|
+
peerId,
|
|
170
|
+
topology,
|
|
171
|
+
protocol,
|
|
172
|
+
this._messenger,
|
|
173
|
+
this._transportFactory,
|
|
174
|
+
label,
|
|
175
|
+
this._connectionLimiter,
|
|
176
|
+
);
|
|
177
|
+
|
|
164
178
|
swarm.errors.handle((error) => {
|
|
165
179
|
log('swarm error', { error });
|
|
166
180
|
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
import chai, { expect } from 'chai';
|
|
5
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
6
|
+
|
|
7
|
+
import { asyncTimeout } from '@dxos/async';
|
|
8
|
+
import { PublicKey } from '@dxos/keys';
|
|
9
|
+
import { describe, test } from '@dxos/test';
|
|
10
|
+
|
|
11
|
+
import { ConnectionLimiter } from './connection-limiter';
|
|
12
|
+
|
|
13
|
+
chai.use(chaiAsPromised);
|
|
14
|
+
|
|
15
|
+
describe('ConnectionLimiter', () => {
|
|
16
|
+
function* setupPeers(
|
|
17
|
+
limiter: ConnectionLimiter,
|
|
18
|
+
): Generator<{ sessionId: PublicKey; connecting: () => Promise<void>; doneConnecting: () => void }> {
|
|
19
|
+
while (true) {
|
|
20
|
+
const sessionId = PublicKey.random();
|
|
21
|
+
yield {
|
|
22
|
+
sessionId,
|
|
23
|
+
connecting: () => asyncTimeout(limiter.connecting(sessionId), 500),
|
|
24
|
+
doneConnecting: () => limiter.doneConnecting(sessionId),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
test('resolves immediately when limit is not reached', async () => {
|
|
30
|
+
const limiter = new ConnectionLimiter({ maxConcurrentInitConnections: 2 });
|
|
31
|
+
const [first, second, third] = setupPeers(limiter);
|
|
32
|
+
await Promise.all([first.connecting(), second.connecting()]);
|
|
33
|
+
first.doneConnecting();
|
|
34
|
+
await third.connecting();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('rejects if done is called', async () => {
|
|
38
|
+
const limiter = new ConnectionLimiter({ maxConcurrentInitConnections: 1 });
|
|
39
|
+
const [first] = setupPeers(limiter);
|
|
40
|
+
const testPromise = expect(first.connecting()).to.be.rejected;
|
|
41
|
+
first.doneConnecting();
|
|
42
|
+
await testPromise;
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { DeferredTask } from '@dxos/async';
|
|
6
|
+
import { Context } from '@dxos/context';
|
|
7
|
+
import { CancelledError } from '@dxos/errors';
|
|
8
|
+
import { PublicKey } from '@dxos/keys';
|
|
9
|
+
import { invariant, log } from '@dxos/log';
|
|
10
|
+
import { ComplexMap } from '@dxos/util';
|
|
11
|
+
|
|
12
|
+
export const MAX_CONCURRENT_INITIATING_CONNECTIONS = 3;
|
|
13
|
+
|
|
14
|
+
export type ConnectionLimiterOptions = {
|
|
15
|
+
maxConcurrentInitConnections?: number;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Limits the amount of concurrent connections with 'CONNECTING' state.
|
|
20
|
+
*/
|
|
21
|
+
export class ConnectionLimiter {
|
|
22
|
+
private readonly _ctx = new Context();
|
|
23
|
+
private readonly _maxConcurrentInitConnections;
|
|
24
|
+
/**
|
|
25
|
+
* Queue of promises to resolve when initiating connections amount is below the limit.
|
|
26
|
+
*/
|
|
27
|
+
private readonly _waitingPromises = new ComplexMap<PublicKey, { resolve: () => void; reject: (err: Error) => void }>(
|
|
28
|
+
PublicKey.hash,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
resolveWaitingPromises = new DeferredTask(this._ctx, async () => {
|
|
32
|
+
Array.from(this._waitingPromises.values())
|
|
33
|
+
.slice(0, this._maxConcurrentInitConnections)
|
|
34
|
+
.forEach(({ resolve }) => {
|
|
35
|
+
resolve();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
constructor({ maxConcurrentInitConnections = MAX_CONCURRENT_INITIATING_CONNECTIONS }: ConnectionLimiterOptions = {}) {
|
|
40
|
+
this._maxConcurrentInitConnections = maxConcurrentInitConnections;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @returns Promise that resolves in queue when connections amount with 'CONNECTING' state is below the limit.
|
|
45
|
+
*/
|
|
46
|
+
async connecting(sessionId: PublicKey): Promise<void> {
|
|
47
|
+
invariant(!this._waitingPromises.has(sessionId), 'Peer is already waiting for connection');
|
|
48
|
+
log('waiting', { sessionId });
|
|
49
|
+
await new Promise<void>((resolve, reject) => {
|
|
50
|
+
this._waitingPromises.set(sessionId, {
|
|
51
|
+
resolve,
|
|
52
|
+
reject,
|
|
53
|
+
});
|
|
54
|
+
this.resolveWaitingPromises.schedule();
|
|
55
|
+
});
|
|
56
|
+
log('allow', { sessionId });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Rejects promise returned by `connecting` method.
|
|
61
|
+
*/
|
|
62
|
+
doneConnecting(sessionId: PublicKey) {
|
|
63
|
+
log('done', { sessionId });
|
|
64
|
+
if (!this._waitingPromises.has(sessionId)) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
this._waitingPromises.get(sessionId)!.reject(new CancelledError());
|
|
68
|
+
this._waitingPromises.delete(sessionId);
|
|
69
|
+
this.resolveWaitingPromises.schedule();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { sleep } from '@dxos/async';
|
|
6
|
+
import { PublicKey } from '@dxos/keys';
|
|
7
|
+
import { log } from '@dxos/log';
|
|
8
|
+
import { describe, test } from '@dxos/test';
|
|
9
|
+
|
|
10
|
+
import { TestWireProtocol } from '../testing/test-wire-protocol';
|
|
11
|
+
import { createWebRTCTransportFactory } from '../transport';
|
|
12
|
+
import { Connection } from './connection';
|
|
13
|
+
|
|
14
|
+
describe('Connection', () => {
|
|
15
|
+
test('initiator opens after responder', async () => {
|
|
16
|
+
const [topic, peerId1, peerId2, sessionId] = PublicKey.randomSequence();
|
|
17
|
+
const protocol1 = new TestWireProtocol(peerId1);
|
|
18
|
+
const connection1 = new Connection(
|
|
19
|
+
topic,
|
|
20
|
+
peerId1,
|
|
21
|
+
peerId2,
|
|
22
|
+
sessionId,
|
|
23
|
+
true,
|
|
24
|
+
{
|
|
25
|
+
offer: async (msg) => {
|
|
26
|
+
log('offer', { msg });
|
|
27
|
+
|
|
28
|
+
return { accept: true };
|
|
29
|
+
},
|
|
30
|
+
signal: async (msg) => {
|
|
31
|
+
await connection2.signal(msg);
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
protocol1.factory({
|
|
35
|
+
initiator: true,
|
|
36
|
+
localPeerId: peerId1,
|
|
37
|
+
remotePeerId: peerId2,
|
|
38
|
+
topic,
|
|
39
|
+
}),
|
|
40
|
+
createWebRTCTransportFactory(),
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const protocol2 = new TestWireProtocol(peerId2);
|
|
44
|
+
const connection2 = new Connection(
|
|
45
|
+
topic,
|
|
46
|
+
peerId2,
|
|
47
|
+
peerId1,
|
|
48
|
+
sessionId,
|
|
49
|
+
false,
|
|
50
|
+
{
|
|
51
|
+
offer: async (msg) => {
|
|
52
|
+
log('offer', { msg });
|
|
53
|
+
|
|
54
|
+
return { accept: true };
|
|
55
|
+
},
|
|
56
|
+
signal: async (msg) => {
|
|
57
|
+
await connection1.signal(msg);
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
protocol2.factory({ initiator: false, localPeerId: peerId2, remotePeerId: peerId1, topic }),
|
|
61
|
+
createWebRTCTransportFactory(),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
await connection2.openConnection();
|
|
65
|
+
await sleep(100);
|
|
66
|
+
await connection1.openConnection();
|
|
67
|
+
await Promise.all([
|
|
68
|
+
protocol1.testConnection(peerId2, 'test message 1'),
|
|
69
|
+
protocol2.testConnection(peerId1, 'test message 2'),
|
|
70
|
+
]);
|
|
71
|
+
});
|
|
72
|
+
});
|
package/src/swarm/connection.ts
CHANGED
|
@@ -109,8 +109,7 @@ export class Connection {
|
|
|
109
109
|
/**
|
|
110
110
|
* Create an underlying transport and prepares it for the connection.
|
|
111
111
|
*/
|
|
112
|
-
|
|
113
|
-
openConnection() {
|
|
112
|
+
async openConnection() {
|
|
114
113
|
invariant(this._state === ConnectionState.INITIAL, 'Invalid state.');
|
|
115
114
|
log.trace('dxos.mesh.connection.open-connection', trace.begin({ id: this._instanceId }));
|
|
116
115
|
|
package/src/swarm/index.ts
CHANGED
package/src/swarm/peer.ts
CHANGED
|
@@ -6,6 +6,7 @@ import invariant from 'tiny-invariant';
|
|
|
6
6
|
|
|
7
7
|
import { scheduleTask, synchronized } from '@dxos/async';
|
|
8
8
|
import { Context } from '@dxos/context';
|
|
9
|
+
import { CancelledError } from '@dxos/errors';
|
|
9
10
|
import { PublicKey } from '@dxos/keys';
|
|
10
11
|
import { log } from '@dxos/log';
|
|
11
12
|
import { Answer } from '@dxos/protocols/proto/dxos/mesh/swarm';
|
|
@@ -14,6 +15,7 @@ import { OfferMessage, SignalMessage, SignalMessenger } from '../signal';
|
|
|
14
15
|
import { TransportFactory } from '../transport';
|
|
15
16
|
import { WireProtocolProvider } from '../wire-protocol';
|
|
16
17
|
import { Connection, ConnectionState } from './connection';
|
|
18
|
+
import { ConnectionLimiter } from './connection-limiter';
|
|
17
19
|
|
|
18
20
|
interface PeerCallbacks {
|
|
19
21
|
/**
|
|
@@ -80,7 +82,6 @@ export class Peer {
|
|
|
80
82
|
public advertizing = false;
|
|
81
83
|
|
|
82
84
|
public initiating = false;
|
|
83
|
-
|
|
84
85
|
constructor(
|
|
85
86
|
public readonly id: PublicKey,
|
|
86
87
|
public readonly topic: PublicKey,
|
|
@@ -88,6 +89,7 @@ export class Peer {
|
|
|
88
89
|
private readonly _signalMessaging: SignalMessenger,
|
|
89
90
|
private readonly _protocolProvider: WireProtocolProvider,
|
|
90
91
|
private readonly _transportFactory: TransportFactory,
|
|
92
|
+
private readonly _connectionLimiter: ConnectionLimiter,
|
|
91
93
|
private readonly _callbacks: PeerCallbacks,
|
|
92
94
|
) {}
|
|
93
95
|
|
|
@@ -102,10 +104,11 @@ export class Peer {
|
|
|
102
104
|
// Peer with the highest Id closes its connection, and accepts remote peer's offer.
|
|
103
105
|
if (remoteId.toHex() < this.localPeerId.toHex()) {
|
|
104
106
|
// TODO(burdon): Too verbose.
|
|
105
|
-
log(
|
|
106
|
-
|
|
107
|
+
log('close local connection', {
|
|
108
|
+
localPeerId: this.id,
|
|
107
109
|
topic: this.topic,
|
|
108
|
-
|
|
110
|
+
remotePeerId: this.localPeerId,
|
|
111
|
+
sessionId: this.connection?.sessionId,
|
|
109
112
|
});
|
|
110
113
|
|
|
111
114
|
if (this.connection) {
|
|
@@ -123,10 +126,15 @@ export class Peer {
|
|
|
123
126
|
// Connection might have been already established.
|
|
124
127
|
invariant(message.sessionId);
|
|
125
128
|
const connection = this._createConnection(false, message.sessionId);
|
|
129
|
+
|
|
126
130
|
try {
|
|
127
|
-
|
|
131
|
+
await this._connectionLimiter.connecting(message.sessionId);
|
|
132
|
+
await connection.openConnection();
|
|
128
133
|
} catch (err: any) {
|
|
129
|
-
|
|
134
|
+
if (!(err instanceof CancelledError)) {
|
|
135
|
+
log.warn('connection error', { topic: this.topic, peerId: this.localPeerId, remoteId: this.id, err });
|
|
136
|
+
}
|
|
137
|
+
|
|
130
138
|
// Calls `onStateChange` with CLOSED state.
|
|
131
139
|
await this.closeConnection();
|
|
132
140
|
}
|
|
@@ -145,10 +153,13 @@ export class Peer {
|
|
|
145
153
|
invariant(!this.connection, 'Already connected.');
|
|
146
154
|
const sessionId = PublicKey.random();
|
|
147
155
|
log('initiating...', { id: this.id, topic: this.topic, peerId: this.id, sessionId });
|
|
156
|
+
|
|
148
157
|
const connection = this._createConnection(true, sessionId);
|
|
149
158
|
this.initiating = true;
|
|
150
159
|
|
|
151
160
|
try {
|
|
161
|
+
await this._connectionLimiter.connecting(sessionId);
|
|
162
|
+
|
|
152
163
|
const answer = await this._signalMessaging.offer({
|
|
153
164
|
author: this.localPeerId,
|
|
154
165
|
recipient: this.id,
|
|
@@ -166,7 +177,7 @@ export class Peer {
|
|
|
166
177
|
this._callbacks.onRejected();
|
|
167
178
|
return;
|
|
168
179
|
}
|
|
169
|
-
connection.openConnection();
|
|
180
|
+
await connection.openConnection();
|
|
170
181
|
this._callbacks.onAccepted();
|
|
171
182
|
} catch (err: any) {
|
|
172
183
|
log('initiation error', { err, topic: this.topic, peerId: this.localPeerId, remoteId: this.id });
|
|
@@ -214,6 +225,8 @@ export class Peer {
|
|
|
214
225
|
this.availableToConnect = true;
|
|
215
226
|
this._lastConnectionTime = Date.now();
|
|
216
227
|
this._callbacks.onConnected();
|
|
228
|
+
|
|
229
|
+
this._connectionLimiter.doneConnecting(sessionId);
|
|
217
230
|
break;
|
|
218
231
|
}
|
|
219
232
|
|
|
@@ -231,6 +244,7 @@ export class Peer {
|
|
|
231
244
|
|
|
232
245
|
this.connection = undefined;
|
|
233
246
|
this._callbacks.onDisconnected();
|
|
247
|
+
this._connectionLimiter.doneConnecting(sessionId);
|
|
234
248
|
|
|
235
249
|
scheduleTask(
|
|
236
250
|
this._connectionCtx!,
|
|
@@ -276,6 +290,7 @@ export class Peer {
|
|
|
276
290
|
log('dropping signal message for non-existent connection', { message });
|
|
277
291
|
return;
|
|
278
292
|
}
|
|
293
|
+
|
|
279
294
|
await this.connection.signal(message);
|
|
280
295
|
}
|
|
281
296
|
|