@streamr/dht 100.0.0-pretestnet.6 → 100.0.0-testnet-one.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/src/connection/ConnectionLockHandler.js +2 -2
- package/dist/src/connection/ConnectionLockHandler.js.map +1 -1
- package/dist/src/connection/ConnectionLockRpcRemote.d.ts +2 -2
- package/dist/src/connection/ConnectionLockRpcRemote.js +2 -2
- package/dist/src/connection/ConnectionLockRpcRemote.js.map +1 -1
- package/dist/src/connection/ConnectionManager.js +4 -1
- package/dist/src/connection/ConnectionManager.js.map +1 -1
- package/dist/src/connection/ConnectorFacade.js.map +1 -1
- package/dist/src/connection/ManagedConnection.js +1 -0
- package/dist/src/connection/ManagedConnection.js.map +1 -1
- package/dist/src/connection/connectivityChecker.d.ts +9 -0
- package/dist/src/connection/connectivityChecker.js +121 -0
- package/dist/src/connection/connectivityChecker.js.map +1 -0
- package/dist/src/connection/connectivityRequestHandler.d.ts +2 -0
- package/dist/src/connection/connectivityRequestHandler.js +79 -0
- package/dist/src/connection/connectivityRequestHandler.js.map +1 -0
- package/dist/src/connection/simulator/Simulator.js +3 -2
- package/dist/src/connection/simulator/Simulator.js.map +1 -1
- package/dist/src/connection/simulator/SimulatorConnection.js +1 -1
- package/dist/src/connection/simulator/SimulatorConnection.js.map +1 -1
- package/dist/src/connection/webrtc/NodeWebrtcConnection.js +1 -1
- package/dist/src/connection/webrtc/NodeWebrtcConnection.js.map +1 -1
- package/dist/src/connection/webrtc/WebrtcConnector.js +1 -1
- package/dist/src/connection/webrtc/WebrtcConnector.js.map +1 -1
- package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js +1 -1
- package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js.map +1 -1
- package/dist/src/connection/webrtc/WebrtcConnectorRpcRemote.d.ts +2 -2
- package/dist/src/connection/webrtc/WebrtcConnectorRpcRemote.js +2 -2
- package/dist/src/connection/webrtc/WebrtcConnectorRpcRemote.js.map +1 -1
- package/dist/src/connection/webrtc/iceServerAsString.js +1 -1
- package/dist/src/connection/webrtc/iceServerAsString.js.map +1 -1
- package/dist/src/connection/websocket/ClientWebsocket.js +1 -0
- package/dist/src/connection/websocket/ClientWebsocket.js.map +1 -1
- package/dist/src/connection/websocket/WebsocketConnector.d.ts +0 -1
- package/dist/src/connection/websocket/WebsocketConnector.js +41 -7
- package/dist/src/connection/websocket/WebsocketConnector.js.map +1 -1
- package/dist/src/connection/websocket/WebsocketConnectorRpcRemote.d.ts +2 -2
- package/dist/src/connection/websocket/WebsocketConnectorRpcRemote.js +2 -2
- package/dist/src/connection/websocket/WebsocketConnectorRpcRemote.js.map +1 -1
- package/dist/src/dht/DhtNode.d.ts +9 -19
- package/dist/src/dht/DhtNode.js +76 -216
- package/dist/src/dht/DhtNode.js.map +1 -1
- package/dist/src/dht/DhtNodeRpcLocal.js +3 -3
- package/dist/src/dht/DhtNodeRpcLocal.js.map +1 -1
- package/dist/src/dht/DhtNodeRpcRemote.d.ts +3 -3
- package/dist/src/dht/DhtNodeRpcRemote.js +4 -4
- package/dist/src/dht/DhtNodeRpcRemote.js.map +1 -1
- package/dist/src/dht/ExternalApiRpcLocal.d.ts +4 -4
- package/dist/src/dht/ExternalApiRpcLocal.js +5 -12
- package/dist/src/dht/ExternalApiRpcLocal.js.map +1 -1
- package/dist/src/dht/ExternalApiRpcRemote.d.ts +3 -3
- package/dist/src/dht/ExternalApiRpcRemote.js +5 -5
- package/dist/src/dht/ExternalApiRpcRemote.js.map +1 -1
- package/dist/src/dht/PeerManager.d.ts +48 -0
- package/dist/src/dht/PeerManager.js +208 -0
- package/dist/src/dht/PeerManager.js.map +1 -0
- package/dist/src/dht/contact/ContactList.d.ts +1 -1
- package/dist/src/dht/contact/ContactList.js +1 -0
- package/dist/src/dht/contact/ContactList.js.map +1 -1
- package/dist/src/dht/contact/{Remote.d.ts → RpcRemote.d.ts} +3 -3
- package/dist/src/dht/contact/{Remote.js → RpcRemote.js} +8 -8
- package/dist/src/dht/contact/RpcRemote.js.map +1 -0
- package/dist/src/dht/discovery/DiscoverySession.d.ts +2 -9
- package/dist/src/dht/discovery/DiscoverySession.js +12 -26
- package/dist/src/dht/discovery/DiscoverySession.js.map +1 -1
- package/dist/src/dht/discovery/PeerDiscovery.d.ts +2 -9
- package/dist/src/dht/discovery/PeerDiscovery.js +13 -15
- package/dist/src/dht/discovery/PeerDiscovery.js.map +1 -1
- package/dist/src/dht/find/FindRpcLocal.js +2 -1
- package/dist/src/dht/find/FindRpcLocal.js.map +1 -1
- package/dist/src/dht/find/FindSession.d.ts +6 -6
- package/dist/src/dht/find/FindSession.js +13 -13
- package/dist/src/dht/find/FindSession.js.map +1 -1
- package/dist/src/dht/find/FindSessionRpcLocal.d.ts +1 -1
- package/dist/src/dht/find/FindSessionRpcRemote.d.ts +2 -2
- package/dist/src/dht/find/FindSessionRpcRemote.js +2 -2
- package/dist/src/dht/find/FindSessionRpcRemote.js.map +1 -1
- package/dist/src/dht/find/Finder.d.ts +4 -4
- package/dist/src/dht/find/Finder.js +50 -42
- package/dist/src/dht/find/Finder.js.map +1 -1
- package/dist/src/dht/routing/FindRpcRemote.d.ts +2 -2
- package/dist/src/dht/routing/FindRpcRemote.js +7 -5
- package/dist/src/dht/routing/FindRpcRemote.js.map +1 -1
- package/dist/src/dht/routing/Router.d.ts +2 -6
- package/dist/src/dht/routing/Router.js +21 -18
- package/dist/src/dht/routing/Router.js.map +1 -1
- package/dist/src/dht/routing/RouterRpcLocal.d.ts +2 -2
- package/dist/src/dht/routing/RouterRpcLocal.js +4 -3
- package/dist/src/dht/routing/RouterRpcLocal.js.map +1 -1
- package/dist/src/dht/routing/RouterRpcRemote.d.ts +2 -2
- package/dist/src/dht/routing/RouterRpcRemote.js +13 -8
- package/dist/src/dht/routing/RouterRpcRemote.js.map +1 -1
- package/dist/src/dht/routing/RoutingSession.d.ts +1 -1
- package/dist/src/dht/routing/RoutingSession.js +16 -11
- package/dist/src/dht/routing/RoutingSession.js.map +1 -1
- package/dist/src/dht/routing/getPreviousPeer.js.map +1 -1
- package/dist/src/dht/store/LocalDataStore.d.ts +3 -3
- package/dist/src/dht/store/LocalDataStore.js +18 -17
- package/dist/src/dht/store/LocalDataStore.js.map +1 -1
- package/dist/src/dht/store/StoreRpcLocal.d.ts +10 -9
- package/dist/src/dht/store/StoreRpcLocal.js +91 -99
- package/dist/src/dht/store/StoreRpcLocal.js.map +1 -1
- package/dist/src/dht/store/StoreRpcRemote.d.ts +4 -5
- package/dist/src/dht/store/StoreRpcRemote.js +6 -15
- package/dist/src/dht/store/StoreRpcRemote.js.map +1 -1
- package/dist/src/exports.d.ts +1 -1
- package/dist/src/exports.js +4 -4
- package/dist/src/exports.js.map +1 -1
- package/dist/src/helpers/PeerID.js +2 -2
- package/dist/src/helpers/PeerID.js.map +1 -1
- package/dist/src/helpers/UUID.js +1 -1
- package/dist/src/helpers/UUID.js.map +1 -1
- package/dist/src/helpers/nodeId.d.ts +1 -0
- package/dist/src/helpers/{kademliaId.js → nodeId.js} +4 -4
- package/dist/src/helpers/nodeId.js.map +1 -0
- package/dist/src/helpers/peerIdFromPeerDescriptor.js +3 -3
- package/dist/src/helpers/peerIdFromPeerDescriptor.js.map +1 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.client.d.ts +5 -16
- package/dist/src/proto/packages/dht/protos/DhtRpc.client.js +2 -9
- package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +1 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +80 -95
- package/dist/src/proto/packages/dht/protos/DhtRpc.js +67 -66
- package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.server.d.ts +3 -10
- package/dist/src/transport/RoutingRpcCommunicator.js +2 -0
- package/dist/src/transport/RoutingRpcCommunicator.js.map +1 -1
- package/karma.config.js +2 -2
- package/package.json +5 -5
- package/protos/DhtRpc.proto +36 -36
- package/src/connection/ConnectionLockHandler.ts +2 -2
- package/src/connection/ConnectionLockRpcRemote.ts +2 -2
- package/src/connection/ConnectionManager.ts +4 -1
- package/src/connection/ConnectorFacade.ts +5 -4
- package/src/connection/ManagedConnection.ts +1 -0
- package/src/connection/connectivityChecker.ts +101 -0
- package/src/connection/connectivityRequestHandler.ts +79 -0
- package/src/connection/simulator/Simulator.ts +3 -2
- package/src/connection/simulator/SimulatorConnection.ts +1 -1
- package/src/connection/webrtc/BrowserWebrtcConnection.ts +10 -10
- package/src/connection/webrtc/NodeWebrtcConnection.ts +1 -1
- package/src/connection/webrtc/WebrtcConnector.ts +1 -1
- package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +1 -1
- package/src/connection/webrtc/WebrtcConnectorRpcRemote.ts +2 -2
- package/src/connection/webrtc/iceServerAsString.ts +1 -1
- package/src/connection/websocket/ClientWebsocket.ts +1 -0
- package/src/connection/websocket/WebsocketConnector.ts +22 -12
- package/src/connection/websocket/WebsocketConnectorRpcRemote.ts +2 -2
- package/src/dht/DhtNode.ts +102 -269
- package/src/dht/DhtNodeRpcLocal.ts +3 -3
- package/src/dht/DhtNodeRpcRemote.ts +4 -4
- package/src/dht/ExternalApiRpcLocal.ts +8 -13
- package/src/dht/ExternalApiRpcRemote.ts +5 -5
- package/src/dht/PeerManager.ts +256 -0
- package/src/dht/contact/ContactList.ts +3 -2
- package/src/dht/contact/{Remote.ts → RpcRemote.ts} +7 -6
- package/src/dht/discovery/DiscoverySession.ts +15 -40
- package/src/dht/discovery/PeerDiscovery.ts +18 -23
- package/src/dht/find/FindRpcLocal.ts +2 -2
- package/src/dht/find/FindSession.ts +20 -20
- package/src/dht/find/FindSessionRpcLocal.ts +1 -1
- package/src/dht/find/FindSessionRpcRemote.ts +2 -2
- package/src/dht/find/Finder.ts +79 -58
- package/src/dht/routing/FindRpcRemote.ts +7 -5
- package/src/dht/routing/Router.ts +22 -21
- package/src/dht/routing/RouterRpcLocal.ts +5 -5
- package/src/dht/routing/RouterRpcRemote.ts +13 -10
- package/src/dht/routing/RoutingSession.ts +15 -10
- package/src/dht/routing/getPreviousPeer.ts +1 -1
- package/src/dht/store/LocalDataStore.ts +18 -17
- package/src/dht/store/StoreRpcLocal.ts +101 -108
- package/src/dht/store/StoreRpcRemote.ts +7 -23
- package/src/exports.ts +1 -1
- package/src/helpers/PeerID.ts +2 -2
- package/src/helpers/UUID.ts +1 -1
- package/src/helpers/{kademliaId.ts → nodeId.ts} +1 -1
- package/src/helpers/peerIdFromPeerDescriptor.ts +3 -3
- package/src/proto/packages/dht/protos/DhtRpc.client.ts +6 -20
- package/src/proto/packages/dht/protos/DhtRpc.server.ts +3 -10
- package/src/proto/packages/dht/protos/DhtRpc.ts +103 -135
- package/src/transport/RoutingRpcCommunicator.ts +2 -0
- package/test/benchmark/Find.test.ts +4 -4
- package/test/benchmark/KademliaCorrectness.test.ts +2 -2
- package/test/benchmark/kademlia-simulation/Contact.ts +1 -1
- package/test/benchmark/kademlia-simulation/KademliaSimulation.ts +1 -1
- package/test/end-to-end/Layer0-Layer1.test.ts +1 -1
- package/test/end-to-end/Layer0MixedConnectionTypes.test.ts +1 -1
- package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +2 -2
- package/test/end-to-end/Layer0Webrtc.test.ts +2 -2
- package/test/end-to-end/Layer1-Scale-WebSocket.test.ts +1 -1
- package/test/end-to-end/Layer1-Scale-Webrtc.test.ts +1 -1
- package/test/end-to-end/WebsocketConnectionRequest.test.ts +1 -1
- package/test/end-to-end/memory-leak.test.ts +8 -12
- package/test/integration/ConnectionLocking.test.ts +2 -2
- package/test/integration/ConnectionManager.test.ts +14 -14
- package/test/integration/DhtJoinPeerDiscovery.test.ts +1 -1
- package/test/integration/DhtNodeExternalAPI.test.ts +10 -7
- package/test/integration/DhtNodeRpcRemote.test.ts +4 -4
- package/test/integration/DhtRpc.test.ts +6 -6
- package/test/integration/Find.test.ts +3 -3
- package/test/integration/Layer1-scale.test.ts +2 -2
- package/test/integration/Mock-Layer1-Layer0.test.ts +1 -1
- package/test/integration/{MigrateData.test.ts → ReplicateData.test.ts} +9 -9
- package/test/integration/RouteMessage.test.ts +2 -2
- package/test/integration/RouterRpcRemote.test.ts +2 -2
- package/test/integration/RpcErrors.test.ts +2 -2
- package/test/integration/ScaleDownDht.test.ts +4 -2
- package/test/integration/SimultaneousConnections.test.ts +8 -8
- package/test/integration/Store.test.ts +33 -13
- package/test/integration/StoreAndDelete.test.ts +19 -17
- package/test/integration/StoreOnDhtWithTwoNodes.test.ts +20 -20
- package/test/integration/StoreRpcRemote.test.ts +3 -3
- package/test/integration/WebrtcConnectionManagement.test.ts +2 -2
- package/test/integration/WebrtcConnectorRpc.test.ts +1 -1
- package/test/integration/WebsocketConnectionManagement.test.ts +2 -2
- package/test/integration/WebsocketConnectorRpc.test.ts +2 -2
- package/test/unit/ConnectivityHelpers.test.ts +4 -4
- package/test/unit/Finder.test.ts +69 -23
- package/test/unit/LocalDataStore.test.ts +60 -43
- package/test/unit/RandomContactList.test.ts +2 -2
- package/test/unit/Router.test.ts +19 -11
- package/test/unit/RoutingSession.test.ts +76 -0
- package/test/unit/SortedContactList.test.ts +2 -2
- package/test/unit/WebsocketConnector.test.ts +1 -1
- package/test/unit/connectivityRequestHandler.test.ts +71 -0
- package/test/utils/mock/Router.ts +1 -1
- package/test/utils/utils.ts +24 -22
- package/dist/src/connection/ConnectivityChecker.d.ts +0 -17
- package/dist/src/connection/ConnectivityChecker.js +0 -208
- package/dist/src/connection/ConnectivityChecker.js.map +0 -1
- package/dist/src/dht/contact/Remote.js.map +0 -1
- package/dist/src/helpers/kademliaId.d.ts +0 -1
- package/dist/src/helpers/kademliaId.js.map +0 -1
- package/src/connection/ConnectivityChecker.ts +0 -199
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { v4 } from 'uuid'
|
|
9
9
|
import { Logger } from '@streamr/utils'
|
|
10
10
|
import { ProtoRpcClient } from '@streamr/proto-rpc'
|
|
11
|
-
import {
|
|
11
|
+
import { RpcRemote } from './contact/RpcRemote'
|
|
12
12
|
import { PeerID } from '../helpers/PeerID'
|
|
13
13
|
import { getNodeIdFromPeerDescriptor, peerIdFromPeerDescriptor } from '../helpers/peerIdFromPeerDescriptor'
|
|
14
14
|
import { ServiceID } from '../types/ServiceID'
|
|
@@ -21,7 +21,7 @@ export interface KBucketContact {
|
|
|
21
21
|
vectorClock: number
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export class DhtNodeRpcRemote extends
|
|
24
|
+
export class DhtNodeRpcRemote extends RpcRemote<IDhtNodeRpcClient> implements KBucketContact {
|
|
25
25
|
|
|
26
26
|
private static counter = 0
|
|
27
27
|
public vectorClock: number
|
|
@@ -39,10 +39,10 @@ export class DhtNodeRpcRemote extends Remote<IDhtNodeRpcClient> implements KBuck
|
|
|
39
39
|
this.vectorClock = DhtNodeRpcRemote.counter++
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
async getClosestPeers(
|
|
42
|
+
async getClosestPeers(nodeId: Uint8Array): Promise<PeerDescriptor[]> {
|
|
43
43
|
logger.trace(`Requesting getClosestPeers on ${this.getServiceId()} from ${getNodeIdFromPeerDescriptor(this.getPeerDescriptor())}`)
|
|
44
44
|
const request: ClosestPeersRequest = {
|
|
45
|
-
|
|
45
|
+
nodeId,
|
|
46
46
|
requestId: v4()
|
|
47
47
|
}
|
|
48
48
|
try {
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ExternalFindDataResponse,
|
|
5
5
|
ExternalStoreDataRequest,
|
|
6
6
|
ExternalStoreDataResponse,
|
|
7
|
+
FindAction,
|
|
7
8
|
PeerDescriptor
|
|
8
9
|
} from '../proto/packages/dht/protos/DhtRpc'
|
|
9
10
|
import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
|
|
@@ -12,8 +13,8 @@ import { FindResult } from './find/Finder'
|
|
|
12
13
|
import { Any } from '../proto/google/protobuf/any'
|
|
13
14
|
|
|
14
15
|
interface ExternalApiRpcLocalConfig {
|
|
15
|
-
startFind: (idToFind: Uint8Array,
|
|
16
|
-
storeDataToDht: (key: Uint8Array, data: Any) => Promise<PeerDescriptor[]>
|
|
16
|
+
startFind: (idToFind: Uint8Array, action: FindAction, excludedPeer: PeerDescriptor) => Promise<FindResult>
|
|
17
|
+
storeDataToDht: (key: Uint8Array, data: Any, creator: PeerDescriptor) => Promise<PeerDescriptor[]>
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export class ExternalApiRpcLocal implements IExternalApiRpc {
|
|
@@ -26,19 +27,13 @@ export class ExternalApiRpcLocal implements IExternalApiRpc {
|
|
|
26
27
|
|
|
27
28
|
async externalFindData(findDataRequest: ExternalFindDataRequest, context: ServerCallContext): Promise<ExternalFindDataResponse> {
|
|
28
29
|
const senderPeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
|
|
29
|
-
const result = await this.config.startFind(findDataRequest.
|
|
30
|
-
|
|
31
|
-
return ExternalFindDataResponse.create({ dataEntries: result.dataEntries })
|
|
32
|
-
} else {
|
|
33
|
-
return ExternalFindDataResponse.create({
|
|
34
|
-
dataEntries: [],
|
|
35
|
-
error: 'Could not find data with the given key'
|
|
36
|
-
})
|
|
37
|
-
}
|
|
30
|
+
const result = await this.config.startFind(findDataRequest.key, FindAction.FETCH_DATA, senderPeerDescriptor)
|
|
31
|
+
return ExternalFindDataResponse.create({ entries: result.dataEntries ?? [] })
|
|
38
32
|
}
|
|
39
33
|
|
|
40
|
-
async externalStoreData(request: ExternalStoreDataRequest): Promise<ExternalStoreDataResponse> {
|
|
41
|
-
const
|
|
34
|
+
async externalStoreData(request: ExternalStoreDataRequest, context: ServerCallContext): Promise<ExternalStoreDataResponse> {
|
|
35
|
+
const senderPeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
|
|
36
|
+
const result = await this.config.storeDataToDht(request.key, request.data!, senderPeerDescriptor)
|
|
42
37
|
return ExternalStoreDataResponse.create({
|
|
43
38
|
storers: result
|
|
44
39
|
})
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { Any } from '../proto/google/protobuf/any'
|
|
2
2
|
import { DataEntry, ExternalStoreDataRequest, ExternalFindDataRequest, PeerDescriptor } from '../proto/packages/dht/protos/DhtRpc'
|
|
3
3
|
import { IExternalApiRpcClient } from '../proto/packages/dht/protos/DhtRpc.client'
|
|
4
|
-
import {
|
|
4
|
+
import { RpcRemote } from './contact/RpcRemote'
|
|
5
5
|
|
|
6
|
-
export class ExternalApiRpcRemote extends
|
|
6
|
+
export class ExternalApiRpcRemote extends RpcRemote<IExternalApiRpcClient> {
|
|
7
7
|
|
|
8
|
-
async externalFindData(
|
|
8
|
+
async externalFindData(key: Uint8Array): Promise<DataEntry[]> {
|
|
9
9
|
const request: ExternalFindDataRequest = {
|
|
10
|
-
|
|
10
|
+
key
|
|
11
11
|
}
|
|
12
12
|
const options = this.formDhtRpcOptions({
|
|
13
13
|
timeout: 10000
|
|
14
14
|
})
|
|
15
15
|
try {
|
|
16
16
|
const data = await this.getClient().externalFindData(request, options)
|
|
17
|
-
return data.
|
|
17
|
+
return data.entries
|
|
18
18
|
} catch (err) {
|
|
19
19
|
return []
|
|
20
20
|
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Logger
|
|
3
|
+
} from '@streamr/utils'
|
|
4
|
+
import KBucket from 'k-bucket'
|
|
5
|
+
import { PeerID, PeerIDKey } from '../helpers/PeerID'
|
|
6
|
+
import {
|
|
7
|
+
getNodeIdFromPeerDescriptor,
|
|
8
|
+
keyFromPeerDescriptor,
|
|
9
|
+
peerIdFromPeerDescriptor
|
|
10
|
+
} from '../helpers/peerIdFromPeerDescriptor'
|
|
11
|
+
import {
|
|
12
|
+
PeerDescriptor
|
|
13
|
+
} from '../proto/packages/dht/protos/DhtRpc'
|
|
14
|
+
import { DhtNodeRpcRemote } from './DhtNodeRpcRemote'
|
|
15
|
+
import { RandomContactList } from './contact/RandomContactList'
|
|
16
|
+
import { SortedContactList } from './contact/SortedContactList'
|
|
17
|
+
import { ConnectionManager } from '../connection/ConnectionManager'
|
|
18
|
+
import EventEmitter from 'eventemitter3'
|
|
19
|
+
|
|
20
|
+
const logger = new Logger(module)
|
|
21
|
+
|
|
22
|
+
interface PeerManagerConfig {
|
|
23
|
+
numberOfNodesPerKBucket: number
|
|
24
|
+
maxNeighborListSize: number
|
|
25
|
+
peerDiscoveryQueryBatchSize: number
|
|
26
|
+
ownPeerId: PeerID
|
|
27
|
+
connectionManager: ConnectionManager
|
|
28
|
+
isLayer0: boolean
|
|
29
|
+
createDhtNodeRpcRemote: (peerDescriptor: PeerDescriptor) => DhtNodeRpcRemote
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface PeerManagerEvents {
|
|
33
|
+
newContact: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
|
|
34
|
+
contactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
|
|
35
|
+
newRandomContact: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
|
|
36
|
+
randomContactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
|
|
37
|
+
kBucketEmpty: () => void
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class PeerManager extends EventEmitter<PeerManagerEvents> {
|
|
41
|
+
|
|
42
|
+
// TODO make private
|
|
43
|
+
public bucket?: KBucket<DhtNodeRpcRemote>
|
|
44
|
+
// TODO make private
|
|
45
|
+
public readonly connections: Map<PeerIDKey, DhtNodeRpcRemote> = new Map()
|
|
46
|
+
// TODO make private
|
|
47
|
+
public neighborList?: SortedContactList<DhtNodeRpcRemote>
|
|
48
|
+
private randomPeers?: RandomContactList<DhtNodeRpcRemote>
|
|
49
|
+
private readonly config: PeerManagerConfig
|
|
50
|
+
private stopped: boolean = false
|
|
51
|
+
|
|
52
|
+
constructor(config: PeerManagerConfig) {
|
|
53
|
+
super()
|
|
54
|
+
this.config = config
|
|
55
|
+
this.initKBuckets()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private initKBuckets() {
|
|
59
|
+
this.bucket = new KBucket<DhtNodeRpcRemote>({
|
|
60
|
+
localNodeId: this.config.ownPeerId.value,
|
|
61
|
+
numberOfNodesPerKBucket: this.config.numberOfNodesPerKBucket,
|
|
62
|
+
numberOfNodesToPing: this.config.numberOfNodesPerKBucket
|
|
63
|
+
})
|
|
64
|
+
this.bucket.on('ping', (oldContacts: DhtNodeRpcRemote[], newContact: DhtNodeRpcRemote) => this.onKBucketPing(oldContacts, newContact))
|
|
65
|
+
this.bucket.on('removed', (contact: DhtNodeRpcRemote) => this.onKBucketRemoved(contact))
|
|
66
|
+
this.bucket.on('added', (contact: DhtNodeRpcRemote) => this.onKBucketAdded(contact))
|
|
67
|
+
this.bucket.on('updated', () => {
|
|
68
|
+
// TODO: Update contact info to the connection manager and reconnect
|
|
69
|
+
})
|
|
70
|
+
this.neighborList = new SortedContactList(this.config.ownPeerId, this.config.maxNeighborListSize)
|
|
71
|
+
this.neighborList.on('contactRemoved', (removedContact: DhtNodeRpcRemote, activeContacts: DhtNodeRpcRemote[]) => {
|
|
72
|
+
if (this.stopped) {
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
this.emit('contactRemoved', removedContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
|
|
76
|
+
this.randomPeers!.addContact(this.config.createDhtNodeRpcRemote(removedContact.getPeerDescriptor()))
|
|
77
|
+
})
|
|
78
|
+
this.neighborList.on('newContact', (newContact: DhtNodeRpcRemote, activeContacts: DhtNodeRpcRemote[]) =>
|
|
79
|
+
this.emit('newContact', newContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
|
|
80
|
+
)
|
|
81
|
+
this.randomPeers = new RandomContactList(this.config.ownPeerId, this.config.maxNeighborListSize)
|
|
82
|
+
this.randomPeers.on('contactRemoved', (removedContact: DhtNodeRpcRemote, activeContacts: DhtNodeRpcRemote[]) =>
|
|
83
|
+
this.emit('randomContactRemoved', removedContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
|
|
84
|
+
)
|
|
85
|
+
this.randomPeers.on('newContact', (newContact: DhtNodeRpcRemote, activeContacts: DhtNodeRpcRemote[]) =>
|
|
86
|
+
this.emit('newRandomContact', newContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private onKBucketPing(oldContacts: DhtNodeRpcRemote[], newContact: DhtNodeRpcRemote): void {
|
|
91
|
+
if (this.stopped) {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
const sortingList: SortedContactList<DhtNodeRpcRemote> = new SortedContactList(this.config.ownPeerId, 100)
|
|
95
|
+
sortingList.addContacts(oldContacts)
|
|
96
|
+
const sortedContacts = sortingList.getAllContacts()
|
|
97
|
+
this.config.connectionManager?.weakUnlockConnection(sortedContacts[sortedContacts.length - 1].getPeerDescriptor())
|
|
98
|
+
this.bucket?.remove(sortedContacts[sortedContacts.length - 1].getPeerId().value)
|
|
99
|
+
this.bucket!.add(newContact)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private onKBucketRemoved(contact: DhtNodeRpcRemote): void {
|
|
103
|
+
if (this.stopped) {
|
|
104
|
+
return
|
|
105
|
+
}
|
|
106
|
+
this.config.connectionManager?.weakUnlockConnection(contact.getPeerDescriptor())
|
|
107
|
+
logger.trace(`Removed contact ${getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())}`)
|
|
108
|
+
if (this.bucket!.count() === 0) {
|
|
109
|
+
this.emit('kBucketEmpty')
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private onKBucketAdded(contact: DhtNodeRpcRemote): void {
|
|
114
|
+
if (this.stopped) {
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
if (!contact.getPeerId().equals(this.config.ownPeerId)) {
|
|
118
|
+
// Important to lock here, before the ping result is known
|
|
119
|
+
this.config.connectionManager?.weakLockConnection(contact.getPeerDescriptor())
|
|
120
|
+
if (this.connections.has(contact.getPeerId().toKey())) {
|
|
121
|
+
logger.trace(`Added new contact ${getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())}`)
|
|
122
|
+
} else { // open connection by pinging
|
|
123
|
+
logger.trace('starting ping ' + getNodeIdFromPeerDescriptor(contact.getPeerDescriptor()))
|
|
124
|
+
contact.ping().then((result) => {
|
|
125
|
+
if (result) {
|
|
126
|
+
logger.trace(`Added new contact ${getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())}`)
|
|
127
|
+
} else {
|
|
128
|
+
logger.trace('ping failed ' + getNodeIdFromPeerDescriptor(contact.getPeerDescriptor()))
|
|
129
|
+
this.config.connectionManager?.weakUnlockConnection(contact.getPeerDescriptor())
|
|
130
|
+
this.removeContact(contact.getPeerDescriptor())
|
|
131
|
+
this.addClosestContactToBucket()
|
|
132
|
+
}
|
|
133
|
+
return
|
|
134
|
+
}).catch((_e) => {
|
|
135
|
+
this.config.connectionManager?.weakUnlockConnection(contact.getPeerDescriptor())
|
|
136
|
+
this.removeContact(contact.getPeerDescriptor())
|
|
137
|
+
this.addClosestContactToBucket()
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private addClosestContactToBucket(): void {
|
|
144
|
+
if (this.stopped) {
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
const closest = this.getClosestActiveContactNotInBucket()
|
|
148
|
+
if (closest) {
|
|
149
|
+
this.handleNewPeers([closest.getPeerDescriptor()])
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private getClosestActiveContactNotInBucket(): DhtNodeRpcRemote | undefined {
|
|
154
|
+
for (const contactId of this.neighborList!.getContactIds()) {
|
|
155
|
+
if (!this.bucket!.get(contactId.value) && this.neighborList!.isActive(contactId)) {
|
|
156
|
+
return this.neighborList!.getContact(contactId)!.contact
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return undefined
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
handleConnected(peerDescriptor: PeerDescriptor): void {
|
|
163
|
+
if (PeerID.fromValue(peerDescriptor.nodeId).equals(this.config.ownPeerId)) {
|
|
164
|
+
logger.error('handleConnected() to self')
|
|
165
|
+
}
|
|
166
|
+
const rpcRemote = this.config.createDhtNodeRpcRemote(peerDescriptor)
|
|
167
|
+
if (!this.connections.has(PeerID.fromValue(rpcRemote.id).toKey())) {
|
|
168
|
+
this.connections.set(PeerID.fromValue(rpcRemote.id).toKey(), rpcRemote)
|
|
169
|
+
logger.trace('connectionschange add ' + this.connections.size)
|
|
170
|
+
} else {
|
|
171
|
+
logger.trace('new connection not set to connections, there is already a connection with the peer ID')
|
|
172
|
+
}
|
|
173
|
+
logger.trace('connected: ' + getNodeIdFromPeerDescriptor(peerDescriptor) + ' ' + this.connections.size)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
handleDisconnected(peerDescriptor: PeerDescriptor, gracefulLeave: boolean): void {
|
|
177
|
+
logger.trace('disconnected: ' + getNodeIdFromPeerDescriptor(peerDescriptor))
|
|
178
|
+
this.connections.delete(keyFromPeerDescriptor(peerDescriptor))
|
|
179
|
+
if (this.config.isLayer0) {
|
|
180
|
+
this.bucket!.remove(peerDescriptor.nodeId)
|
|
181
|
+
if (gracefulLeave === true) {
|
|
182
|
+
logger.trace(getNodeIdFromPeerDescriptor(peerDescriptor) + ' ' + 'onTransportDisconnected with gracefulLeave ' + gracefulLeave)
|
|
183
|
+
this.removeContact(peerDescriptor)
|
|
184
|
+
} else {
|
|
185
|
+
logger.trace(getNodeIdFromPeerDescriptor(peerDescriptor) + ' ' + 'onTransportDisconnected with gracefulLeave ' + gracefulLeave)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
handlePeerLeaving(peerDescriptor: PeerDescriptor): void {
|
|
191
|
+
this.removeContact(peerDescriptor)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
private removeContact(contact: PeerDescriptor): void {
|
|
195
|
+
if (this.stopped) {
|
|
196
|
+
return
|
|
197
|
+
}
|
|
198
|
+
logger.trace(`Removing contact ${getNodeIdFromPeerDescriptor(contact)}`)
|
|
199
|
+
const peerId = peerIdFromPeerDescriptor(contact)
|
|
200
|
+
this.bucket!.remove(peerId.value)
|
|
201
|
+
this.neighborList!.removeContact(peerId)
|
|
202
|
+
this.randomPeers!.removeContact(peerId)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
stop(): void {
|
|
206
|
+
this.stopped = true
|
|
207
|
+
this.bucket!.toArray().forEach((rpcRemote: DhtNodeRpcRemote) => {
|
|
208
|
+
rpcRemote.leaveNotice()
|
|
209
|
+
this.bucket!.remove(rpcRemote.id)
|
|
210
|
+
})
|
|
211
|
+
this.bucket!.removeAllListeners()
|
|
212
|
+
this.neighborList!.stop()
|
|
213
|
+
this.randomPeers!.stop()
|
|
214
|
+
this.connections.clear()
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
getNumberOfConnections(): number {
|
|
218
|
+
return this.connections.size
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
handlePeerActive(peerId: PeerID): void {
|
|
222
|
+
this.neighborList!.setActive(peerId)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
handlePeerUnresponsive(peerId: PeerID): void {
|
|
226
|
+
this.bucket!.remove(peerId.value)
|
|
227
|
+
this.neighborList!.removeContact(peerId)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
handleNewPeers(contacts: PeerDescriptor[], setActive = false): void {
|
|
231
|
+
if (this.stopped) {
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
contacts.forEach((contact) => {
|
|
235
|
+
if (!PeerID.fromValue(contact.nodeId).equals(this.config.ownPeerId)) {
|
|
236
|
+
logger.trace(`Adding new contact ${getNodeIdFromPeerDescriptor(contact)}`)
|
|
237
|
+
const rpcRemote = this.config.createDhtNodeRpcRemote(contact)
|
|
238
|
+
if ((this.bucket!.get(contact.nodeId) === null)
|
|
239
|
+
&& (this.neighborList!.getContact(peerIdFromPeerDescriptor(contact)) === undefined)
|
|
240
|
+
) {
|
|
241
|
+
this.neighborList!.addContact(rpcRemote)
|
|
242
|
+
if (setActive) {
|
|
243
|
+
const peerId = peerIdFromPeerDescriptor(contact)
|
|
244
|
+
this.neighborList!.setActive(peerId)
|
|
245
|
+
}
|
|
246
|
+
this.bucket!.add(rpcRemote)
|
|
247
|
+
} else {
|
|
248
|
+
this.randomPeers!.addContact(rpcRemote)
|
|
249
|
+
}
|
|
250
|
+
if (this.neighborList!.getContact(rpcRemote.getPeerId()) !== undefined) {
|
|
251
|
+
this.neighborList!.addContact(rpcRemote)
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
}
|
|
@@ -19,6 +19,7 @@ export interface Events<C> {
|
|
|
19
19
|
export class ContactList<C extends { getPeerId: () => PeerID }> extends EventEmitter<Events<C>> {
|
|
20
20
|
|
|
21
21
|
protected contactsById: Map<PeerIDKey, ContactState<C>> = new Map()
|
|
22
|
+
// TODO move this to SortedContactList
|
|
22
23
|
protected contactIds: PeerID[] = []
|
|
23
24
|
protected ownId: PeerID
|
|
24
25
|
protected maxSize: number
|
|
@@ -35,8 +36,8 @@ export class ContactList<C extends { getPeerId: () => PeerID }> extends EventEmi
|
|
|
35
36
|
this.defaultContactQueryLimit = defaultContactQueryLimit
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
public getContact(id: PeerID): ContactState<C> {
|
|
39
|
-
return this.contactsById.get(id.toKey())
|
|
39
|
+
public getContact(id: PeerID): ContactState<C> | undefined {
|
|
40
|
+
return this.contactsById.get(id.toKey())
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
public getSize(): number {
|
|
@@ -15,7 +15,7 @@ const WEBRTC_TIMEOUT = 15000
|
|
|
15
15
|
// default timeout for existing connections
|
|
16
16
|
export const EXISTING_CONNECTION_TIMEOUT = 5000
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const getTimeout = (localPeerDescriptor: PeerDescriptor, remotePeerDescriptor: PeerDescriptor): number => {
|
|
19
19
|
const connectionType = expectedConnectionType(localPeerDescriptor, remotePeerDescriptor)
|
|
20
20
|
if (connectionType === ConnectionType.WEBSOCKET_CLIENT) {
|
|
21
21
|
return WEBSOCKET_CLIENT_TIMEOUT
|
|
@@ -27,25 +27,26 @@ const getRpcTimeout = (localPeerDescriptor: PeerDescriptor, remotePeerDescriptor
|
|
|
27
27
|
return WEBRTC_TIMEOUT
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export abstract class
|
|
30
|
+
export abstract class RpcRemote<T> {
|
|
31
31
|
|
|
32
32
|
private readonly localPeerDescriptor: PeerDescriptor
|
|
33
33
|
private readonly remotePeerDescriptor: PeerDescriptor
|
|
34
34
|
private readonly serviceId: ServiceID
|
|
35
35
|
private readonly client: ProtoRpcClient<T>
|
|
36
|
-
private readonly
|
|
36
|
+
private readonly timeout?: number
|
|
37
|
+
|
|
37
38
|
constructor(
|
|
38
39
|
localPeerDescriptor: PeerDescriptor,
|
|
39
40
|
remotePeerDescriptor: PeerDescriptor,
|
|
40
41
|
serviceId: ServiceID,
|
|
41
42
|
client: ProtoRpcClient<T>,
|
|
42
|
-
|
|
43
|
+
timeout?: number
|
|
43
44
|
) {
|
|
44
45
|
this.localPeerDescriptor = localPeerDescriptor
|
|
45
46
|
this.remotePeerDescriptor = remotePeerDescriptor
|
|
46
47
|
this.client = client
|
|
47
48
|
this.serviceId = serviceId
|
|
48
|
-
this.
|
|
49
|
+
this.timeout = timeout
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
getPeerDescriptor(): PeerDescriptor {
|
|
@@ -68,7 +69,7 @@ export abstract class Remote<T> {
|
|
|
68
69
|
return {
|
|
69
70
|
sourceDescriptor: this.localPeerDescriptor,
|
|
70
71
|
targetDescriptor: this.remotePeerDescriptor,
|
|
71
|
-
timeout: this.
|
|
72
|
+
timeout: this.timeout ?? getTimeout(this.localPeerDescriptor, this.remotePeerDescriptor),
|
|
72
73
|
...opts
|
|
73
74
|
}
|
|
74
75
|
}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import { RpcCommunicator, toProtoRpcClient } from '@streamr/proto-rpc'
|
|
2
1
|
import { Logger, runAndWaitForEvents3 } from '@streamr/utils'
|
|
3
2
|
import EventEmitter from 'eventemitter3'
|
|
4
|
-
import KBucket from 'k-bucket'
|
|
5
3
|
import { v4 } from 'uuid'
|
|
6
4
|
import { PeerID } from '../../helpers/PeerID'
|
|
7
5
|
import { PeerDescriptor } from '../../proto/packages/dht/protos/DhtRpc'
|
|
8
|
-
import { DhtNodeRpcClient } from '../../proto/packages/dht/protos/DhtRpc.client'
|
|
9
6
|
import { SortedContactList } from '../contact/SortedContactList'
|
|
10
7
|
import { DhtNodeRpcRemote } from '../DhtNodeRpcRemote'
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
8
|
+
import { getNodeIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
|
|
9
|
+
import { PeerManager } from '../PeerManager'
|
|
13
10
|
|
|
14
11
|
const logger = new Logger(module)
|
|
15
12
|
|
|
@@ -18,16 +15,11 @@ interface DiscoverySessionEvents {
|
|
|
18
15
|
}
|
|
19
16
|
|
|
20
17
|
interface DiscoverySessionConfig {
|
|
21
|
-
bucket: KBucket<DhtNodeRpcRemote>
|
|
22
|
-
neighborList: SortedContactList<DhtNodeRpcRemote>
|
|
23
18
|
targetId: Uint8Array
|
|
24
19
|
localPeerDescriptor: PeerDescriptor
|
|
25
|
-
serviceId: ServiceID
|
|
26
|
-
rpcCommunicator: RpcCommunicator
|
|
27
20
|
parallelism: number
|
|
28
21
|
noProgressLimit: number
|
|
29
|
-
|
|
30
|
-
rpcRequestTimeout?: number
|
|
22
|
+
peerManager: PeerManager
|
|
31
23
|
}
|
|
32
24
|
|
|
33
25
|
export class DiscoverySession {
|
|
@@ -48,23 +40,7 @@ export class DiscoverySession {
|
|
|
48
40
|
if (this.stopped) {
|
|
49
41
|
return
|
|
50
42
|
}
|
|
51
|
-
|
|
52
|
-
if (!areEqualPeerDescriptors(contact, this.config.localPeerDescriptor)) {
|
|
53
|
-
const rpcRemote = new DhtNodeRpcRemote(
|
|
54
|
-
this.config.localPeerDescriptor,
|
|
55
|
-
contact,
|
|
56
|
-
toProtoRpcClient(new DhtNodeRpcClient(this.config.rpcCommunicator.getRpcClientTransport())),
|
|
57
|
-
this.config.serviceId,
|
|
58
|
-
this.config.rpcRequestTimeout
|
|
59
|
-
)
|
|
60
|
-
if (this.config.newContactListener) {
|
|
61
|
-
this.config.newContactListener(rpcRemote)
|
|
62
|
-
}
|
|
63
|
-
if (!this.config.neighborList.getContact(rpcRemote.getPeerId())) {
|
|
64
|
-
this.config.neighborList.addContact(rpcRemote)
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
})
|
|
43
|
+
this.config.peerManager.handleNewPeers(contacts)
|
|
68
44
|
}
|
|
69
45
|
|
|
70
46
|
private async getClosestPeersFromContact(contact: DhtNodeRpcRemote): Promise<PeerDescriptor[]> {
|
|
@@ -73,9 +49,9 @@ export class DiscoverySession {
|
|
|
73
49
|
}
|
|
74
50
|
logger.trace(`Getting closest peers from contact: ${getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())}`)
|
|
75
51
|
this.outgoingClosestPeersRequestsCounter++
|
|
76
|
-
this.config.neighborList
|
|
52
|
+
this.config.peerManager.neighborList!.setContacted(contact.getPeerId())
|
|
77
53
|
const returnedContacts = await contact.getClosestPeers(this.config.targetId)
|
|
78
|
-
this.config.
|
|
54
|
+
this.config.peerManager.handlePeerActive(contact.getPeerId())
|
|
79
55
|
return returnedContacts
|
|
80
56
|
}
|
|
81
57
|
|
|
@@ -84,9 +60,9 @@ export class DiscoverySession {
|
|
|
84
60
|
return
|
|
85
61
|
}
|
|
86
62
|
this.ongoingClosestPeersRequests.delete(peerId.toKey())
|
|
87
|
-
const oldClosestContact = this.config.neighborList
|
|
63
|
+
const oldClosestContact = this.config.peerManager.neighborList!.getClosestContactId()
|
|
88
64
|
this.addNewContacts(contacts)
|
|
89
|
-
if (this.config.neighborList
|
|
65
|
+
if (this.config.peerManager.neighborList!.getClosestContactId().equals(oldClosestContact)) {
|
|
90
66
|
this.noProgressCounter++
|
|
91
67
|
} else {
|
|
92
68
|
this.noProgressCounter = 0
|
|
@@ -98,15 +74,14 @@ export class DiscoverySession {
|
|
|
98
74
|
return
|
|
99
75
|
}
|
|
100
76
|
this.ongoingClosestPeersRequests.delete(peer.getPeerId().toKey())
|
|
101
|
-
this.config.
|
|
102
|
-
this.config.neighborList.removeContact(peer.getPeerId())
|
|
77
|
+
this.config.peerManager.handlePeerUnresponsive(peer.getPeerId())
|
|
103
78
|
}
|
|
104
79
|
|
|
105
80
|
private findMoreContacts(): void {
|
|
106
81
|
if (this.stopped) {
|
|
107
82
|
return
|
|
108
83
|
}
|
|
109
|
-
const uncontacted = this.config.neighborList
|
|
84
|
+
const uncontacted = this.config.peerManager.neighborList!.getUncontactedContacts(this.config.parallelism)
|
|
110
85
|
if (uncontacted.length === 0 || this.noProgressCounter >= this.config.noProgressLimit) {
|
|
111
86
|
this.emitter.emit('discoveryCompleted')
|
|
112
87
|
this.stopped = true
|
|
@@ -129,17 +104,17 @@ export class DiscoverySession {
|
|
|
129
104
|
}
|
|
130
105
|
|
|
131
106
|
public async findClosestNodes(timeout: number): Promise<SortedContactList<DhtNodeRpcRemote>> {
|
|
132
|
-
if (this.config.neighborList
|
|
133
|
-
logger.trace('getUncontactedContacts length was 0 in beginning of discovery,
|
|
134
|
-
+ this.config.neighborList
|
|
135
|
-
return this.config.neighborList
|
|
107
|
+
if (this.config.peerManager.neighborList!.getUncontactedContacts(this.config.parallelism).length === 0) {
|
|
108
|
+
logger.trace('getUncontactedContacts length was 0 in beginning of discovery, neighborList.size: '
|
|
109
|
+
+ this.config.peerManager.neighborList!.getSize())
|
|
110
|
+
return this.config.peerManager.neighborList!
|
|
136
111
|
}
|
|
137
112
|
await runAndWaitForEvents3<DiscoverySessionEvents>(
|
|
138
113
|
[this.findMoreContacts.bind(this)],
|
|
139
114
|
[[this.emitter, 'discoveryCompleted']],
|
|
140
115
|
timeout
|
|
141
116
|
)
|
|
142
|
-
return this.config.neighborList
|
|
117
|
+
return this.config.peerManager.neighborList!
|
|
143
118
|
}
|
|
144
119
|
|
|
145
120
|
public stop(): void {
|
|
@@ -3,26 +3,20 @@ import { DhtNodeRpcRemote } from '../DhtNodeRpcRemote'
|
|
|
3
3
|
import { areEqualPeerDescriptors, getNodeIdFromPeerDescriptor, peerIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
|
|
4
4
|
import { PeerDescriptor } from '../../proto/packages/dht/protos/DhtRpc'
|
|
5
5
|
import { Logger, scheduleAtInterval, setAbortableTimeout } from '@streamr/utils'
|
|
6
|
-
import KBucket from 'k-bucket'
|
|
7
|
-
import { SortedContactList } from '../contact/SortedContactList'
|
|
8
6
|
import { ConnectionManager } from '../../connection/ConnectionManager'
|
|
9
|
-
import {
|
|
10
|
-
import { createRandomKademliaId } from '../../helpers/kademliaId'
|
|
7
|
+
import { createRandomNodeId } from '../../helpers/nodeId'
|
|
11
8
|
import { ServiceID } from '../../types/ServiceID'
|
|
9
|
+
import { PeerManager } from '../PeerManager'
|
|
12
10
|
|
|
13
11
|
interface PeerDiscoveryConfig {
|
|
14
|
-
rpcCommunicator: RoutingRpcCommunicator
|
|
15
12
|
localPeerDescriptor: PeerDescriptor
|
|
16
|
-
bucket: KBucket<DhtNodeRpcRemote>
|
|
17
|
-
neighborList: SortedContactList<DhtNodeRpcRemote>
|
|
18
13
|
joinNoProgressLimit: number
|
|
19
14
|
peerDiscoveryQueryBatchSize: number
|
|
20
15
|
serviceId: ServiceID
|
|
21
16
|
parallelism: number
|
|
22
17
|
joinTimeout: number
|
|
23
|
-
addContact: (contact: PeerDescriptor, setActive?: boolean) => void
|
|
24
18
|
connectionManager?: ConnectionManager
|
|
25
|
-
|
|
19
|
+
peerManager: PeerManager
|
|
26
20
|
}
|
|
27
21
|
|
|
28
22
|
const logger = new Logger(module)
|
|
@@ -55,13 +49,13 @@ export class PeerDiscovery {
|
|
|
55
49
|
return
|
|
56
50
|
}
|
|
57
51
|
this.config.connectionManager?.lockConnection(entryPointDescriptor, `${this.config.serviceId}::joinDht`)
|
|
58
|
-
this.config.
|
|
52
|
+
this.config.peerManager.handleNewPeers([entryPointDescriptor])
|
|
59
53
|
const targetId = peerIdFromPeerDescriptor(this.config.localPeerDescriptor).value
|
|
60
|
-
const closest = this.config.bucket
|
|
61
|
-
this.config.neighborList
|
|
54
|
+
const closest = this.config.peerManager.bucket!.closest(targetId, this.config.peerDiscoveryQueryBatchSize)
|
|
55
|
+
this.config.peerManager.neighborList!.addContacts(closest)
|
|
62
56
|
const sessions = [this.createSession(targetId)]
|
|
63
57
|
if (doAdditionalRandomPeerDiscovery) {
|
|
64
|
-
sessions.push(this.createSession(
|
|
58
|
+
sessions.push(this.createSession(createRandomNodeId()))
|
|
65
59
|
}
|
|
66
60
|
await this.runSessions(sessions, entryPointDescriptor, retry)
|
|
67
61
|
this.config.connectionManager?.unlockConnection(entryPointDescriptor, `${this.config.serviceId}::joinDht`)
|
|
@@ -70,15 +64,11 @@ export class PeerDiscovery {
|
|
|
70
64
|
|
|
71
65
|
private createSession(targetId: Uint8Array): DiscoverySession {
|
|
72
66
|
const sessionOptions = {
|
|
73
|
-
bucket: this.config.bucket,
|
|
74
|
-
neighborList: this.config.neighborList,
|
|
75
67
|
targetId,
|
|
76
68
|
localPeerDescriptor: this.config.localPeerDescriptor,
|
|
77
|
-
serviceId: this.config.serviceId,
|
|
78
|
-
rpcCommunicator: this.config.rpcCommunicator,
|
|
79
69
|
parallelism: this.config.parallelism,
|
|
80
70
|
noProgressLimit: this.config.joinNoProgressLimit,
|
|
81
|
-
|
|
71
|
+
peerManager: this.config.peerManager
|
|
82
72
|
}
|
|
83
73
|
return new DiscoverySession(sessionOptions)
|
|
84
74
|
}
|
|
@@ -93,8 +83,9 @@ export class PeerDiscovery {
|
|
|
93
83
|
logger.debug(`DHT join on ${this.config.serviceId} timed out`)
|
|
94
84
|
} finally {
|
|
95
85
|
if (!this.isStopped()) {
|
|
96
|
-
if (this.config.bucket
|
|
86
|
+
if (this.config.peerManager.bucket!.count() === 0) {
|
|
97
87
|
if (retry) {
|
|
88
|
+
// TODO should we catch possible promise rejection?
|
|
98
89
|
setAbortableTimeout(() => this.rejoinDht(entryPointDescriptor), 1000, this.abortController.signal)
|
|
99
90
|
}
|
|
100
91
|
} else {
|
|
@@ -112,12 +103,13 @@ export class PeerDiscovery {
|
|
|
112
103
|
logger.debug(`Rejoining DHT ${this.config.serviceId}`)
|
|
113
104
|
this.rejoinOngoing = true
|
|
114
105
|
try {
|
|
115
|
-
this.config.neighborList
|
|
106
|
+
this.config.peerManager.neighborList!.clear()
|
|
116
107
|
await this.joinDht(entryPoint)
|
|
117
108
|
logger.debug(`Rejoined DHT successfully ${this.config.serviceId}!`)
|
|
118
109
|
} catch (err) {
|
|
119
110
|
logger.warn(`Rejoining DHT ${this.config.serviceId} failed`)
|
|
120
111
|
if (!this.isStopped()) {
|
|
112
|
+
// TODO should we catch possible promise rejection?
|
|
121
113
|
setAbortableTimeout(() => this.rejoinDht(entryPoint), 5000, this.abortController.signal)
|
|
122
114
|
}
|
|
123
115
|
} finally {
|
|
@@ -136,11 +128,14 @@ export class PeerDiscovery {
|
|
|
136
128
|
if (this.isStopped()) {
|
|
137
129
|
return
|
|
138
130
|
}
|
|
139
|
-
const nodes = this.config.bucket
|
|
131
|
+
const nodes = this.config.peerManager.bucket!.closest(
|
|
132
|
+
peerIdFromPeerDescriptor(this.config.localPeerDescriptor).value,
|
|
133
|
+
this.config.parallelism
|
|
134
|
+
)
|
|
140
135
|
await Promise.allSettled(nodes.map(async (peer: DhtNodeRpcRemote) => {
|
|
141
|
-
const contacts = await peer.getClosestPeers(this.config.localPeerDescriptor.
|
|
136
|
+
const contacts = await peer.getClosestPeers(this.config.localPeerDescriptor.nodeId)
|
|
142
137
|
contacts.forEach((contact) => {
|
|
143
|
-
this.config.
|
|
138
|
+
this.config.peerManager.handleNewPeers([contact])
|
|
144
139
|
})
|
|
145
140
|
}))
|
|
146
141
|
}
|