@streamr/dht 0.0.1-tatum.4 → 0.0.1-tatum.5
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/ConnectivityChecker.js +27 -17
- package/dist/src/connection/ConnectivityChecker.js.map +1 -1
- package/dist/src/connection/Handshaker.js +18 -13
- package/dist/src/connection/Handshaker.js.map +1 -1
- package/dist/src/connection/WebSocket/ServerWebSocket.js +0 -1
- package/dist/src/connection/WebSocket/ServerWebSocket.js.map +1 -1
- package/dist/src/dht/DhtNode.d.ts +1 -0
- package/dist/src/dht/DhtNode.js +12 -31
- package/dist/src/dht/DhtNode.js.map +1 -1
- package/dist/src/dht/DhtPeer.d.ts +0 -1
- package/dist/src/dht/DhtPeer.js +15 -26
- package/dist/src/dht/DhtPeer.js.map +1 -1
- package/dist/src/dht/RemoteExternalApi.d.ts +3 -1
- package/dist/src/dht/RemoteExternalApi.js +20 -6
- package/dist/src/dht/RemoteExternalApi.js.map +1 -1
- package/dist/src/dht/contact/ContactList.d.ts +16 -0
- package/dist/src/dht/contact/ContactList.js +36 -0
- package/dist/src/dht/contact/ContactList.js.map +1 -0
- package/dist/src/dht/contact/RandomContactList.d.ts +7 -16
- package/dist/src/dht/contact/RandomContactList.js +7 -31
- package/dist/src/dht/contact/RandomContactList.js.map +1 -1
- package/dist/src/dht/contact/Remote.d.ts +10 -6
- package/dist/src/dht/contact/Remote.js +19 -6
- package/dist/src/dht/contact/Remote.js.map +1 -1
- package/dist/src/dht/contact/SortedContactList.d.ts +10 -20
- package/dist/src/dht/contact/SortedContactList.js +10 -31
- package/dist/src/dht/contact/SortedContactList.js.map +1 -1
- package/dist/src/dht/find/RecursiveFinder.js +1 -1
- package/dist/src/dht/find/RecursiveFinder.js.map +1 -1
- package/dist/src/dht/find/RemoteRecursiveFindSession.js +1 -5
- package/dist/src/dht/find/RemoteRecursiveFindSession.js.map +1 -1
- package/dist/src/dht/registerExternalApiRpcMethods.d.ts +2 -0
- package/dist/src/dht/{registerExternalApiRpcMethod.js → registerExternalApiRpcMethods.js} +13 -5
- package/dist/src/dht/registerExternalApiRpcMethods.js.map +1 -0
- package/dist/src/dht/routing/RemoteRouter.js +13 -19
- package/dist/src/dht/routing/RemoteRouter.js.map +1 -1
- package/dist/src/dht/routing/RoutingSession.js +1 -1
- package/dist/src/dht/routing/RoutingSession.js.map +1 -1
- package/dist/src/dht/store/DataStore.js +3 -3
- package/dist/src/dht/store/DataStore.js.map +1 -1
- package/dist/src/dht/store/RemoteStore.js +13 -17
- package/dist/src/dht/store/RemoteStore.js.map +1 -1
- package/dist/src/exports.d.ts +1 -0
- package/dist/src/exports.js +3 -1
- package/dist/src/exports.js.map +1 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.client.d.ts +10 -0
- package/dist/src/proto/packages/dht/protos/DhtRpc.client.js +7 -0
- package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +1 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +36 -0
- package/dist/src/proto/packages/dht/protos/DhtRpc.js +29 -2
- package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.server.d.ts +6 -0
- package/package.json +6 -6
- package/protos/DhtRpc.proto +10 -0
- package/src/connection/ConnectionManager.ts +1 -1
- package/src/connection/ConnectivityChecker.ts +26 -17
- package/src/connection/Handshaker.ts +18 -13
- package/src/connection/WebSocket/ServerWebSocket.ts +0 -1
- package/src/dht/DhtNode.ts +19 -9
- package/src/dht/DhtPeer.ts +17 -29
- package/src/dht/RemoteExternalApi.ts +22 -8
- package/src/dht/contact/ContactList.ts +45 -0
- package/src/dht/contact/RandomContactList.ts +16 -41
- package/src/dht/contact/Remote.ts +30 -14
- package/src/dht/contact/SortedContactList.ts +25 -53
- package/src/dht/find/RecursiveFinder.ts +2 -2
- package/src/dht/find/RemoteRecursiveFindSession.ts +1 -8
- package/src/dht/registerExternalApiRpcMethods.ts +41 -0
- package/src/dht/routing/RemoteRouter.ts +13 -20
- package/src/dht/routing/RoutingSession.ts +2 -2
- package/src/dht/store/DataStore.ts +6 -6
- package/src/dht/store/RemoteStore.ts +13 -20
- package/src/exports.ts +1 -0
- package/src/proto/packages/dht/protos/DhtRpc.client.ts +13 -0
- package/src/proto/packages/dht/protos/DhtRpc.server.ts +6 -0
- package/src/proto/packages/dht/protos/DhtRpc.ts +49 -1
- package/test/integration/DhtNodeExternalAPI.test.ts +9 -0
- package/test/integration/RemoteRouter.test.ts +1 -1
- package/test/integration/RemoteStore.test.ts +1 -1
- package/test/unit/RandomContactList.test.ts +24 -17
- package/test/unit/SortedContactList.test.ts +56 -30
- package/dist/src/dht/registerExternalApiRpcMethod.d.ts +0 -2
- package/dist/src/dht/registerExternalApiRpcMethod.js.map +0 -1
- package/src/dht/registerExternalApiRpcMethod.ts +0 -26
|
@@ -69,14 +69,18 @@ export class ConnectivityChecker {
|
|
|
69
69
|
}, ConnectivityChecker.CONNECTIVITY_CHECKER_TIMEOUT)
|
|
70
70
|
const listener = (bytes: Uint8Array) => {
|
|
71
71
|
outgoingConnection.close('OTHER')
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
try {
|
|
73
|
+
const message: Message = Message.fromBinary(bytes)
|
|
74
|
+
if (message.body.oneofKind === 'connectivityResponse') {
|
|
75
|
+
const connectivityResponseMessage = message.body.connectivityResponse
|
|
76
|
+
outgoingConnection!.off('data', listener)
|
|
77
|
+
clearTimeout(timeoutId)
|
|
78
|
+
resolve(connectivityResponseMessage)
|
|
79
|
+
} else {
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
} catch (err) {
|
|
83
|
+
logger.trace(`Could not parse message: ${err}`)
|
|
80
84
|
}
|
|
81
85
|
}
|
|
82
86
|
outgoingConnection!.on('data', listener)
|
|
@@ -97,16 +101,21 @@ export class ConnectivityChecker {
|
|
|
97
101
|
public listenToIncomingConnectivityRequests(connectionToListenTo: ServerWebSocket): void {
|
|
98
102
|
connectionToListenTo.on('data', (data: Uint8Array) => {
|
|
99
103
|
logger.trace('server received data')
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
try {
|
|
105
|
+
const message = Message.fromBinary(data)
|
|
106
|
+
if (message.body.oneofKind === 'connectivityRequest') {
|
|
107
|
+
logger.trace('received connectivity request')
|
|
108
|
+
this.handleIncomingConnectivityRequest(connectionToListenTo, message.body.connectivityRequest).then(() => {
|
|
109
|
+
logger.trace('handleIncomingConnectivityRequest ok')
|
|
110
|
+
return
|
|
111
|
+
}).catch((e) => {
|
|
112
|
+
logger.error('handleIncomingConnectivityRequest' + e)
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
} catch (err) {
|
|
116
|
+
logger.trace(`Could not parse message: ${err}`)
|
|
109
117
|
}
|
|
118
|
+
|
|
110
119
|
})
|
|
111
120
|
}
|
|
112
121
|
|
|
@@ -32,21 +32,26 @@ export class Handshaker extends EventEmitter<HandshakerEvents> {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
private onData = (data: Uint8Array) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
35
|
+
try {
|
|
36
|
+
const message = Message.fromBinary(data)
|
|
37
|
+
if (message.body.oneofKind === 'handshakeRequest') {
|
|
38
|
+
logger.trace('handshake request received')
|
|
39
|
+
const handshake = message.body.handshakeRequest
|
|
40
|
+
this.emit('handshakeRequest', handshake.peerDescriptor!)
|
|
41
|
+
}
|
|
42
|
+
if (message.body.oneofKind === 'handshakeResponse') {
|
|
43
|
+
logger.trace('handshake response received')
|
|
44
|
+
const handshake = message.body.handshakeResponse
|
|
45
|
+
if (handshake.responseError) {
|
|
46
|
+
this.emit('handshakeFailed', handshake.responseError)
|
|
47
|
+
} else {
|
|
48
|
+
this.emit('handshakeCompleted', handshake.peerDescriptor!)
|
|
49
|
+
}
|
|
48
50
|
}
|
|
51
|
+
} catch (err) {
|
|
52
|
+
logger.error('error while parsing handshake message', err)
|
|
49
53
|
}
|
|
54
|
+
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
public sendHandshakeRequest(): void {
|
package/src/dht/DhtNode.ts
CHANGED
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
FindMode,
|
|
19
19
|
DataEntry,
|
|
20
20
|
} from '../proto/packages/dht/protos/DhtRpc'
|
|
21
|
-
import * as Err from '../helpers/errors'
|
|
22
21
|
import { DisconnectionType, ITransport, TransportEvents } from '../transport/ITransport'
|
|
23
22
|
import { ConnectionManager, ConnectionManagerConfig, PortRange, TlsCertificate } from '../connection/ConnectionManager'
|
|
24
23
|
import { DhtRpcServiceClient, ExternalApiServiceClient } from '../proto/packages/dht/protos/DhtRpc.client'
|
|
@@ -40,10 +39,11 @@ import { DataStore } from './store/DataStore'
|
|
|
40
39
|
import { PeerDiscovery } from './discovery/PeerDiscovery'
|
|
41
40
|
import { LocalDataStore } from './store/LocalDataStore'
|
|
42
41
|
import { IceServer } from '../connection/WebRTC/WebRtcConnector'
|
|
43
|
-
import {
|
|
42
|
+
import { registerExternalApiRpcMethods } from './registerExternalApiRpcMethods'
|
|
44
43
|
import { RemoteExternalApi } from './RemoteExternalApi'
|
|
45
44
|
import { UUID } from '../exports'
|
|
46
45
|
import { isNodeJS } from '../helpers/browser/isNodeJS'
|
|
46
|
+
import { sample } from 'lodash'
|
|
47
47
|
|
|
48
48
|
export interface DhtNodeEvents {
|
|
49
49
|
newContact: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
|
|
@@ -299,7 +299,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
|
|
|
299
299
|
return this.bucket!.closest(id, n)
|
|
300
300
|
}
|
|
301
301
|
})
|
|
302
|
-
|
|
302
|
+
registerExternalApiRpcMethods(this)
|
|
303
303
|
if (this.connectionManager! && this.config.entryPoints && this.config.entryPoints.length > 0
|
|
304
304
|
&& !isSamePeerDescriptor(this.config.entryPoints[0], this.ownPeerDescriptor!)) {
|
|
305
305
|
this.connectToEntryPoint(this.config.entryPoints[0])
|
|
@@ -640,9 +640,22 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
|
|
|
640
640
|
}
|
|
641
641
|
|
|
642
642
|
public async storeDataToDht(key: Uint8Array, data: Any): Promise<PeerDescriptor[]> {
|
|
643
|
+
if (this.isJoinOngoing() && this.config.entryPoints && this.config.entryPoints.length > 0) {
|
|
644
|
+
return this.storeDataViaPeer(key, data, sample(this.config.entryPoints)!)
|
|
645
|
+
}
|
|
643
646
|
return this.dataStore!.storeDataToDht(key, data)
|
|
644
647
|
}
|
|
645
648
|
|
|
649
|
+
public async storeDataViaPeer(key: Uint8Array, data: Any, peer: PeerDescriptor): Promise<PeerDescriptor[]> {
|
|
650
|
+
const target = new RemoteExternalApi(
|
|
651
|
+
this.ownPeerDescriptor!,
|
|
652
|
+
peer,
|
|
653
|
+
this.config.serviceId,
|
|
654
|
+
toProtoRpcClient(new ExternalApiServiceClient(this.rpcCommunicator!.getRpcClientTransport()))
|
|
655
|
+
)
|
|
656
|
+
return await target.storeData(key, data)
|
|
657
|
+
}
|
|
658
|
+
|
|
646
659
|
public async getDataFromDht(idToFind: Uint8Array): Promise<RecursiveFindResult> {
|
|
647
660
|
return this.recursiveFinder!.startRecursiveFind(idToFind, FindMode.DATA)
|
|
648
661
|
}
|
|
@@ -657,8 +670,8 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
|
|
|
657
670
|
const target = new RemoteExternalApi(
|
|
658
671
|
this.ownPeerDescriptor!,
|
|
659
672
|
peer,
|
|
660
|
-
|
|
661
|
-
this.
|
|
673
|
+
this.config.serviceId,
|
|
674
|
+
toProtoRpcClient(new ExternalApiServiceClient(this.rpcCommunicator!.getRpcClientTransport()))
|
|
662
675
|
)
|
|
663
676
|
return await target.findData(idToFind)
|
|
664
677
|
}
|
|
@@ -720,13 +733,10 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
|
|
|
720
733
|
}
|
|
721
734
|
|
|
722
735
|
public async stop(): Promise<void> {
|
|
723
|
-
if (this.stopped) {
|
|
736
|
+
if (this.stopped || !this.started) {
|
|
724
737
|
return
|
|
725
738
|
}
|
|
726
739
|
logger.trace('stop()')
|
|
727
|
-
if (!this.started) {
|
|
728
|
-
throw new Err.CouldNotStop('Cannot not stop() before start()')
|
|
729
|
-
}
|
|
730
740
|
this.stopped = true
|
|
731
741
|
|
|
732
742
|
if (this.entryPointDisconnectTimeout) {
|
package/src/dht/DhtPeer.ts
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
PingRequest
|
|
7
7
|
} from '../proto/packages/dht/protos/DhtRpc'
|
|
8
8
|
import { v4 } from 'uuid'
|
|
9
|
-
import { DhtRpcOptions } from '../rpc-protocol/DhtRpcOptions'
|
|
10
9
|
import { Logger } from '@streamr/utils'
|
|
11
10
|
import { ProtoRpcClient } from '@streamr/proto-rpc'
|
|
12
11
|
import { Remote } from './contact/Remote'
|
|
@@ -20,77 +19,66 @@ export interface KBucketContact {
|
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
export class DhtPeer extends Remote<IDhtRpcServiceClient> implements KBucketContact {
|
|
22
|
+
|
|
23
23
|
private static counter = 0
|
|
24
24
|
public vectorClock: number
|
|
25
25
|
public readonly id: Uint8Array
|
|
26
|
+
|
|
26
27
|
constructor(
|
|
27
28
|
ownPeerDescriptor: PeerDescriptor,
|
|
28
29
|
peerDescriptor: PeerDescriptor,
|
|
29
30
|
client: ProtoRpcClient<IDhtRpcServiceClient>,
|
|
30
31
|
serviceId: string
|
|
31
32
|
) {
|
|
32
|
-
super(ownPeerDescriptor, peerDescriptor,
|
|
33
|
-
this.id = this.
|
|
33
|
+
super(ownPeerDescriptor, peerDescriptor, serviceId, client)
|
|
34
|
+
this.id = this.getPeerId().value
|
|
34
35
|
this.vectorClock = DhtPeer.counter++
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
async getClosestPeers(kademliaId: Uint8Array): Promise<PeerDescriptor[]> {
|
|
38
|
-
logger.trace(`Requesting getClosestPeers on ${this.
|
|
39
|
+
logger.trace(`Requesting getClosestPeers on ${this.getServiceId()} from ${this.getPeerId().toKey()}`)
|
|
39
40
|
const request: ClosestPeersRequest = {
|
|
40
41
|
kademliaId,
|
|
41
42
|
requestId: v4()
|
|
42
43
|
}
|
|
43
|
-
const options: DhtRpcOptions = {
|
|
44
|
-
sourceDescriptor: this.ownPeerDescriptor,
|
|
45
|
-
targetDescriptor: this.peerDescriptor
|
|
46
|
-
}
|
|
47
44
|
try {
|
|
48
|
-
const peers = await this.
|
|
45
|
+
const peers = await this.getClient().getClosestPeers(request, this.formDhtRpcOptions())
|
|
49
46
|
return peers.peers
|
|
50
47
|
} catch (err) {
|
|
51
|
-
logger.trace(`getClosestPeers error ${this.
|
|
48
|
+
logger.trace(`getClosestPeers error ${this.getServiceId()}`, { err })
|
|
52
49
|
throw err
|
|
53
50
|
}
|
|
54
51
|
}
|
|
55
52
|
|
|
56
53
|
async ping(): Promise<boolean> {
|
|
57
|
-
logger.trace(`Requesting ping on ${this.
|
|
54
|
+
logger.trace(`Requesting ping on ${this.getServiceId()} from ${this.getPeerId().toKey()}`)
|
|
58
55
|
const request: PingRequest = {
|
|
59
56
|
requestId: v4()
|
|
60
57
|
}
|
|
61
|
-
const options
|
|
62
|
-
sourceDescriptor: this.ownPeerDescriptor,
|
|
63
|
-
targetDescriptor: this.peerDescriptor,
|
|
58
|
+
const options = this.formDhtRpcOptions({
|
|
64
59
|
timeout: 10000
|
|
65
|
-
}
|
|
60
|
+
})
|
|
66
61
|
try {
|
|
67
|
-
const pong = await this.
|
|
62
|
+
const pong = await this.getClient().ping(request, options)
|
|
68
63
|
if (pong.requestId === request.requestId) {
|
|
69
64
|
return true
|
|
70
65
|
}
|
|
71
66
|
} catch (err) {
|
|
72
|
-
logger.trace(`ping failed on ${this.
|
|
67
|
+
logger.trace(`ping failed on ${this.getServiceId()} to ${this.getPeerId().toKey()}: ${err}`)
|
|
73
68
|
}
|
|
74
69
|
return false
|
|
75
70
|
}
|
|
76
71
|
|
|
77
72
|
leaveNotice(): void {
|
|
78
|
-
logger.trace(`Sending leaveNotice on ${this.
|
|
73
|
+
logger.trace(`Sending leaveNotice on ${this.getServiceId()} from ${this.getPeerId().toKey()}`)
|
|
79
74
|
const request: LeaveNotice = {
|
|
80
|
-
serviceId: this.
|
|
75
|
+
serviceId: this.getServiceId()
|
|
81
76
|
}
|
|
82
|
-
const options
|
|
83
|
-
sourceDescriptor: this.ownPeerDescriptor,
|
|
84
|
-
targetDescriptor: this.peerDescriptor,
|
|
77
|
+
const options = this.formDhtRpcOptions({
|
|
85
78
|
notification: true
|
|
86
|
-
}
|
|
87
|
-
this.
|
|
79
|
+
})
|
|
80
|
+
this.getClient().leaveNotice(request, options).catch((e) => {
|
|
88
81
|
logger.trace('Failed to send leaveNotice' + e)
|
|
89
82
|
})
|
|
90
83
|
}
|
|
91
|
-
|
|
92
|
-
getPeerDescriptor(): PeerDescriptor {
|
|
93
|
-
return this.peerDescriptor
|
|
94
|
-
}
|
|
95
|
-
|
|
96
84
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { DataEntry, FindDataRequest } from '../proto/packages/dht/protos/DhtRpc'
|
|
1
|
+
import { Any } from '../proto/google/protobuf/any'
|
|
2
|
+
import { DataEntry, ExternalStoreDataRequest, FindDataRequest, PeerDescriptor } from '../proto/packages/dht/protos/DhtRpc'
|
|
3
3
|
import { IExternalApiServiceClient } from '../proto/packages/dht/protos/DhtRpc.client'
|
|
4
4
|
import { Remote } from './contact/Remote'
|
|
5
5
|
|
|
@@ -8,18 +8,32 @@ export class RemoteExternalApi extends Remote<IExternalApiServiceClient> {
|
|
|
8
8
|
async findData(idToFind: Uint8Array): Promise<DataEntry[]> {
|
|
9
9
|
const request: FindDataRequest = {
|
|
10
10
|
kademliaId: idToFind,
|
|
11
|
-
requestor: this.
|
|
11
|
+
requestor: this.getLocalPeerDescriptor(),
|
|
12
12
|
}
|
|
13
|
-
const options
|
|
14
|
-
sourceDescriptor: this.ownPeerDescriptor,
|
|
15
|
-
targetDescriptor: this.peerDescriptor,
|
|
13
|
+
const options = this.formDhtRpcOptions({
|
|
16
14
|
timeout: 10000
|
|
17
|
-
}
|
|
15
|
+
})
|
|
18
16
|
try {
|
|
19
|
-
const data = await this.
|
|
17
|
+
const data = await this.getClient().findData(request, options)
|
|
20
18
|
return data.dataEntries
|
|
21
19
|
} catch (err) {
|
|
22
20
|
return []
|
|
23
21
|
}
|
|
24
22
|
}
|
|
23
|
+
|
|
24
|
+
async storeData(key: Uint8Array, data: Any): Promise<PeerDescriptor[]> {
|
|
25
|
+
const request: ExternalStoreDataRequest = {
|
|
26
|
+
key,
|
|
27
|
+
data
|
|
28
|
+
}
|
|
29
|
+
const options = this.formDhtRpcOptions({
|
|
30
|
+
timeout: 10000
|
|
31
|
+
})
|
|
32
|
+
try {
|
|
33
|
+
const response = await this.getClient().externalStoreData(request, options)
|
|
34
|
+
return response.storers
|
|
35
|
+
} catch (err) {
|
|
36
|
+
return []
|
|
37
|
+
}
|
|
38
|
+
}
|
|
25
39
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { PeerID, PeerIDKey } from '../../helpers/PeerID'
|
|
2
|
+
import EventEmitter from 'eventemitter3'
|
|
3
|
+
import { Events, IContact, ContactState } from './Contact'
|
|
4
|
+
|
|
5
|
+
export class ContactList<C extends IContact> extends EventEmitter<Events> {
|
|
6
|
+
|
|
7
|
+
protected contactsById: Map<PeerIDKey, ContactState<C>> = new Map()
|
|
8
|
+
protected contactIds: PeerID[] = []
|
|
9
|
+
protected ownId: PeerID
|
|
10
|
+
protected maxSize: number
|
|
11
|
+
protected defaultContactQueryLimit
|
|
12
|
+
|
|
13
|
+
constructor(
|
|
14
|
+
ownId: PeerID,
|
|
15
|
+
maxSize: number,
|
|
16
|
+
defaultContactQueryLimit = 20
|
|
17
|
+
) {
|
|
18
|
+
super()
|
|
19
|
+
this.ownId = ownId
|
|
20
|
+
this.maxSize = maxSize
|
|
21
|
+
this.defaultContactQueryLimit = defaultContactQueryLimit
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public getContact(id: PeerID): ContactState<C> {
|
|
25
|
+
return this.contactsById.get(id.toKey())!
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public hasContact(id: PeerID): boolean {
|
|
29
|
+
return this.contactsById.has(id.toKey())
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public getSize(): number {
|
|
33
|
+
return this.contactIds.length
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public clear(): void {
|
|
37
|
+
this.contactsById.clear()
|
|
38
|
+
this.contactIds = []
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public stop(): void {
|
|
42
|
+
this.removeAllListeners()
|
|
43
|
+
this.clear()
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -1,29 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PeerID } from '../../helpers/PeerID'
|
|
2
|
+
import { ContactState, IContact } from './Contact'
|
|
3
|
+
import { ContactList } from './ContactList'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
private contactsById: Map<PeerIDKey, ContactState<Contact>> = new Map()
|
|
7
|
-
private contactIds: PeerID[] = []
|
|
8
|
-
private ownId: PeerID
|
|
9
|
-
private maxSize: number
|
|
10
|
-
private randomness = 0.20
|
|
11
|
-
private getContactsLimit = 20
|
|
5
|
+
export class RandomContactList<C extends IContact> extends ContactList<C> {
|
|
6
|
+
|
|
7
|
+
private randomness: number
|
|
12
8
|
|
|
13
9
|
constructor(
|
|
14
10
|
ownId: PeerID,
|
|
15
11
|
maxSize: number,
|
|
16
12
|
randomness = 0.20,
|
|
17
|
-
|
|
13
|
+
defaultContactQueryLimit?: number
|
|
18
14
|
) {
|
|
19
|
-
super()
|
|
20
|
-
this.ownId = ownId
|
|
21
|
-
this.maxSize = maxSize
|
|
15
|
+
super(ownId, maxSize, defaultContactQueryLimit)
|
|
22
16
|
this.randomness = randomness
|
|
23
|
-
this.getContactsLimit = getContactsLimit
|
|
24
17
|
}
|
|
25
18
|
|
|
26
|
-
addContact(contact:
|
|
19
|
+
addContact(contact: C): void {
|
|
27
20
|
if (this.ownId.equals(contact.getPeerId())) {
|
|
28
21
|
return
|
|
29
22
|
}
|
|
@@ -39,54 +32,36 @@ export class RandomContactList<Contact extends IContact> extends EventEmitter<Ev
|
|
|
39
32
|
this.emit(
|
|
40
33
|
'newContact',
|
|
41
34
|
contact.getPeerDescriptor(),
|
|
42
|
-
this.getContacts().map((contact:
|
|
35
|
+
this.getContacts().map((contact: C) => contact.getPeerDescriptor())
|
|
43
36
|
)
|
|
44
37
|
}
|
|
45
38
|
}
|
|
46
39
|
}
|
|
47
40
|
|
|
48
|
-
addContacts(contacts:
|
|
41
|
+
addContacts(contacts: C[]): void {
|
|
49
42
|
contacts.forEach((contact) => this.addContact(contact))
|
|
50
43
|
}
|
|
51
44
|
|
|
52
45
|
removeContact(id: PeerID): boolean {
|
|
53
46
|
if (this.contactsById.has(id.toKey())) {
|
|
54
47
|
const removedDescriptor = this.contactsById.get(id.toKey())!.contact.getPeerDescriptor()
|
|
55
|
-
const index = this.contactIds.
|
|
48
|
+
const index = this.contactIds.findIndex((element) => element.equals(id))
|
|
56
49
|
this.contactIds.splice(index, 1)
|
|
57
50
|
this.contactsById.delete(id.toKey())
|
|
58
|
-
this.emit('contactRemoved', removedDescriptor, this.getContacts().map((contact:
|
|
51
|
+
this.emit('contactRemoved', removedDescriptor, this.getContacts().map((contact: C) => contact.getPeerDescriptor()))
|
|
59
52
|
return true
|
|
60
53
|
}
|
|
61
54
|
return false
|
|
62
55
|
}
|
|
63
56
|
|
|
64
|
-
public
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
public getContact(id: PeerID): ContactState<Contact> {
|
|
69
|
-
return this.contactsById.get(id.toKey())!
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
public getContacts(limit = this.getContactsLimit): Contact[] {
|
|
73
|
-
const ret: Contact[] = []
|
|
57
|
+
public getContacts(limit = this.defaultContactQueryLimit): C[] {
|
|
58
|
+
const ret: C[] = []
|
|
74
59
|
this.contactIds.forEach((contactId) => {
|
|
75
60
|
const contact = this.contactsById.get(contactId.toKey())
|
|
76
61
|
if (contact) {
|
|
77
62
|
ret.push(contact.contact)
|
|
78
63
|
}
|
|
79
64
|
})
|
|
80
|
-
return ret.
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
public clear(): void {
|
|
84
|
-
this.contactsById.clear()
|
|
85
|
-
this.contactIds = []
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
public stop(): void {
|
|
89
|
-
this.removeAllListeners()
|
|
90
|
-
this.clear()
|
|
65
|
+
return ret.slice(0, limit)
|
|
91
66
|
}
|
|
92
67
|
}
|
|
@@ -3,38 +3,54 @@ import { ProtoRpcClient } from '@streamr/proto-rpc'
|
|
|
3
3
|
import { peerIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
|
|
4
4
|
import { PeerID } from '../../helpers/PeerID'
|
|
5
5
|
import { IContact } from './Contact'
|
|
6
|
+
import { DhtRpcOptions } from '../../rpc-protocol/DhtRpcOptions'
|
|
6
7
|
|
|
7
8
|
export abstract class Remote<T> implements IContact {
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
private readonly localPeerDescriptor: PeerDescriptor
|
|
11
|
+
private readonly remotePeerId: PeerID
|
|
12
|
+
private readonly remotePeerDescriptor: PeerDescriptor
|
|
13
|
+
private readonly serviceId: string
|
|
14
|
+
private readonly client: ProtoRpcClient<T>
|
|
14
15
|
|
|
15
16
|
constructor(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
localPeerDescriptor: PeerDescriptor,
|
|
18
|
+
remotePeerDescriptor: PeerDescriptor,
|
|
19
|
+
serviceId: string,
|
|
20
|
+
client: ProtoRpcClient<T>
|
|
20
21
|
) {
|
|
21
|
-
this.
|
|
22
|
-
this.
|
|
23
|
-
this.
|
|
22
|
+
this.localPeerDescriptor = localPeerDescriptor
|
|
23
|
+
this.remotePeerId = peerIdFromPeerDescriptor(remotePeerDescriptor)
|
|
24
|
+
this.remotePeerDescriptor = remotePeerDescriptor
|
|
24
25
|
this.client = client
|
|
25
26
|
this.serviceId = serviceId
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
getPeerId(): PeerID {
|
|
29
|
-
return this.
|
|
30
|
+
return this.remotePeerId
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
getPeerDescriptor(): PeerDescriptor {
|
|
33
|
-
return this.
|
|
34
|
+
return this.remotePeerDescriptor
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getLocalPeerDescriptor(): PeerDescriptor {
|
|
38
|
+
return this.localPeerDescriptor
|
|
34
39
|
}
|
|
35
40
|
|
|
36
41
|
getServiceId(): string {
|
|
37
42
|
return this.serviceId
|
|
38
43
|
}
|
|
39
44
|
|
|
45
|
+
getClient(): ProtoRpcClient<T> {
|
|
46
|
+
return this.client
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
formDhtRpcOptions(opts?: Omit<DhtRpcOptions, 'sourceDescriptor' | 'targetDescriptor'>): DhtRpcOptions {
|
|
50
|
+
return {
|
|
51
|
+
sourceDescriptor: this.localPeerDescriptor,
|
|
52
|
+
targetDescriptor: this.remotePeerDescriptor,
|
|
53
|
+
...opts
|
|
54
|
+
}
|
|
55
|
+
}
|
|
40
56
|
}
|