@streamr/dht 102.0.0-beta.1 → 102.0.0-beta.3
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/generated/google/protobuf/any.d.ts +180 -0
- package/dist/generated/google/protobuf/any.js +155 -0
- package/dist/generated/google/protobuf/any.js.map +1 -0
- package/dist/generated/google/protobuf/empty.d.ts +31 -0
- package/dist/generated/google/protobuf/empty.js +32 -0
- package/dist/generated/google/protobuf/empty.js.map +1 -0
- package/dist/generated/google/protobuf/timestamp.d.ts +155 -0
- package/dist/generated/google/protobuf/timestamp.js +136 -0
- package/dist/generated/google/protobuf/timestamp.js.map +1 -0
- package/dist/generated/packages/dht/protos/DhtRpc.client.d.ts +361 -0
- package/dist/generated/packages/dht/protos/DhtRpc.client.js +285 -0
- package/dist/generated/packages/dht/protos/DhtRpc.client.js.map +1 -0
- package/dist/generated/packages/dht/protos/DhtRpc.d.ts +999 -0
- package/dist/generated/packages/dht/protos/DhtRpc.js +677 -0
- package/dist/generated/packages/dht/protos/DhtRpc.js.map +1 -0
- package/dist/generated/packages/dht/protos/DhtRpc.server.d.ts +162 -0
- package/dist/generated/packages/dht/protos/DhtRpc.server.js +3 -0
- package/dist/generated/packages/dht/protos/DhtRpc.server.js.map +1 -0
- package/dist/generated/packages/proto-rpc/protos/ProtoRpc.d.ts +87 -0
- package/dist/generated/packages/proto-rpc/protos/ProtoRpc.js +66 -0
- package/dist/generated/packages/proto-rpc/protos/ProtoRpc.js.map +1 -0
- package/dist/package.json +7 -7
- package/package.json +7 -7
- package/eslint.config.mjs +0 -12
- package/src/connection/Connection.ts +0 -28
- package/src/connection/ConnectionLockRpcLocal.ts +0 -78
- package/src/connection/ConnectionLockRpcRemote.ts +0 -64
- package/src/connection/ConnectionLockStates.ts +0 -131
- package/src/connection/ConnectionManager.ts +0 -661
- package/src/connection/ConnectionsView.ts +0 -8
- package/src/connection/ConnectorFacade.ts +0 -217
- package/src/connection/Handshaker.ts +0 -209
- package/src/connection/IConnection.ts +0 -40
- package/src/connection/ManagedConnection.ts +0 -113
- package/src/connection/OutputBuffer.ts +0 -28
- package/src/connection/PendingConnection.ts +0 -68
- package/src/connection/connectivityChecker.ts +0 -108
- package/src/connection/connectivityRequestHandler.ts +0 -116
- package/src/connection/simulator/Simulator.ts +0 -369
- package/src/connection/simulator/SimulatorConnection.ts +0 -137
- package/src/connection/simulator/SimulatorConnector.ts +0 -98
- package/src/connection/simulator/SimulatorTransport.ts +0 -15
- package/src/connection/simulator/pings.ts +0 -42
- package/src/connection/webrtc/BrowserWebrtcConnection.ts +0 -242
- package/src/connection/webrtc/IWebrtcConnection.ts +0 -24
- package/src/connection/webrtc/NodeWebrtcConnection.ts +0 -245
- package/src/connection/webrtc/WebrtcConnector.ts +0 -234
- package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +0 -108
- package/src/connection/webrtc/WebrtcConnectorRpcRemote.ts +0 -60
- package/src/connection/webrtc/iceServerAsString.ts +0 -15
- package/src/connection/websocket/AbstractWebsocketClientConnection.ts +0 -122
- package/src/connection/websocket/AutoCertifierClientFacade.ts +0 -89
- package/src/connection/websocket/BrowserWebsocketClientConnection.ts +0 -44
- package/src/connection/websocket/NodeWebsocketClientConnection.ts +0 -39
- package/src/connection/websocket/WebsocketClientConnector.ts +0 -119
- package/src/connection/websocket/WebsocketClientConnectorRpcLocal.ts +0 -38
- package/src/connection/websocket/WebsocketClientConnectorRpcRemote.ts +0 -19
- package/src/connection/websocket/WebsocketServer.ts +0 -164
- package/src/connection/websocket/WebsocketServerConnection.ts +0 -109
- package/src/connection/websocket/WebsocketServerConnector.ts +0 -290
- package/src/dht/DhtNode.ts +0 -683
- package/src/dht/DhtNodeRpcLocal.ts +0 -84
- package/src/dht/DhtNodeRpcRemote.ts +0 -107
- package/src/dht/ExternalApiRpcLocal.ts +0 -58
- package/src/dht/ExternalApiRpcRemote.ts +0 -41
- package/src/dht/PeerManager.ts +0 -305
- package/src/dht/contact/Contact.ts +0 -19
- package/src/dht/contact/ContactList.ts +0 -43
- package/src/dht/contact/RandomContactList.ts +0 -56
- package/src/dht/contact/RingContactList.ts +0 -143
- package/src/dht/contact/RpcRemote.ts +0 -72
- package/src/dht/contact/SortedContactList.ts +0 -173
- package/src/dht/contact/getClosestNodes.ts +0 -24
- package/src/dht/contact/ringIdentifiers.ts +0 -62
- package/src/dht/discovery/DiscoverySession.ts +0 -129
- package/src/dht/discovery/PeerDiscovery.ts +0 -244
- package/src/dht/discovery/RingDiscoverySession.ts +0 -148
- package/src/dht/recursive-operation/RecursiveOperationManager.ts +0 -251
- package/src/dht/recursive-operation/RecursiveOperationRpcLocal.ts +0 -34
- package/src/dht/recursive-operation/RecursiveOperationRpcRemote.ts +0 -43
- package/src/dht/recursive-operation/RecursiveOperationSession.ts +0 -231
- package/src/dht/recursive-operation/RecursiveOperationSessionRpcLocal.ts +0 -35
- package/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.ts +0 -30
- package/src/dht/routing/DuplicateDetector.ts +0 -34
- package/src/dht/routing/Router.ts +0 -246
- package/src/dht/routing/RouterRpcLocal.ts +0 -78
- package/src/dht/routing/RouterRpcRemote.ts +0 -80
- package/src/dht/routing/RoutingSession.ts +0 -243
- package/src/dht/routing/RoutingTablesCache.ts +0 -60
- package/src/dht/routing/getPreviousPeer.ts +0 -6
- package/src/dht/store/LocalDataStore.ts +0 -84
- package/src/dht/store/StoreManager.ts +0 -170
- package/src/dht/store/StoreRpcLocal.ts +0 -89
- package/src/dht/store/StoreRpcRemote.ts +0 -32
- package/src/exports.ts +0 -33
- package/src/helpers/AddressTools.ts +0 -28
- package/src/helpers/Connectivity.ts +0 -19
- package/src/helpers/browser/isBrowserEnvironment.ts +0 -1
- package/src/helpers/browser/isBrowserEnvironment_override.ts +0 -3
- package/src/helpers/createPeerDescriptor.ts +0 -57
- package/src/helpers/createPeerDescriptorSignaturePayload.ts +0 -28
- package/src/helpers/debugHelpers.ts +0 -9
- package/src/helpers/errors.ts +0 -49
- package/src/helpers/offering.ts +0 -15
- package/src/helpers/protoClasses.ts +0 -57
- package/src/helpers/protoToString.ts +0 -21
- package/src/helpers/version.ts +0 -32
- package/src/identifiers.ts +0 -29
- package/src/rpc-protocol/DhtCallContext.ts +0 -14
- package/src/rpc-protocol/DhtRpcOptions.ts +0 -10
- package/src/transport/ITransport.ts +0 -37
- package/src/transport/ListeningRpcCommunicator.ts +0 -32
- package/src/transport/RoutingRpcCommunicator.ts +0 -66
- package/src/types/ServiceID.ts +0 -1
- package/src/types/textencoding.d.ts +0 -6
- package/test/benchmark/Find.test.ts +0 -72
- package/test/benchmark/KademliaCorrectness.test.ts +0 -114
- package/test/benchmark/RingCorrectness.test.ts +0 -157
- package/test/benchmark/SortedContactListBenchmark.test.ts +0 -108
- package/test/benchmark/WebsocketServerMemoryLeak.test.ts +0 -41
- package/test/benchmark/hybrid-network-simulation/RingContactList.test.ts +0 -71
- package/test/end-to-end/GeoIpLayer0.test.ts +0 -55
- package/test/end-to-end/Layer0-Layer1.test.ts +0 -93
- package/test/end-to-end/Layer0.test.ts +0 -76
- package/test/end-to-end/Layer0MixedConnectionTypes.test.ts +0 -110
- package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +0 -137
- package/test/end-to-end/Layer0Webrtc.test.ts +0 -85
- package/test/end-to-end/Layer1-Scale-WebSocket.test.ts +0 -82
- package/test/end-to-end/Layer1-Scale-Webrtc.test.ts +0 -76
- package/test/end-to-end/RecoveryFromFailedAutoCertification.test.ts +0 -52
- package/test/end-to-end/WebsocketConnectionRequest.test.ts +0 -69
- package/test/end-to-end/memory-leak.test.ts +0 -80
- package/test/integration/ConnectionLocking.test.ts +0 -192
- package/test/integration/ConnectionManager.test.ts +0 -528
- package/test/integration/ConnectivityChecking.test.ts +0 -53
- package/test/integration/DhtJoinPeerDiscovery.test.ts +0 -49
- package/test/integration/DhtNode.test.ts +0 -66
- package/test/integration/DhtNodeExternalAPI.test.ts +0 -48
- package/test/integration/DhtNodeRpcRemote.test.ts +0 -66
- package/test/integration/DhtRpc.test.ts +0 -121
- package/test/integration/Find.test.ts +0 -45
- package/test/integration/GeoIpConnectivityChecking.test.ts +0 -72
- package/test/integration/Layer1-scale.test.ts +0 -189
- package/test/integration/Mock-Layer1-Layer0.test.ts +0 -85
- package/test/integration/MultipleEntryPointJoining.test.ts +0 -105
- package/test/integration/ReplicateData.test.ts +0 -104
- package/test/integration/RouteMessage.test.ts +0 -230
- package/test/integration/RouterRpcRemote.test.ts +0 -77
- package/test/integration/SimultaneousConnections.test.ts +0 -316
- package/test/integration/Store.test.ts +0 -85
- package/test/integration/StoreAndDelete.test.ts +0 -77
- package/test/integration/StoreOnDhtWithThreeNodes.test.ts +0 -59
- package/test/integration/StoreOnDhtWithTwoNodes.test.ts +0 -51
- package/test/integration/StoreRpcRemote.test.ts +0 -54
- package/test/integration/WebrtcConnectionManagement.test.ts +0 -191
- package/test/integration/WebrtcConnectorRpc.test.ts +0 -125
- package/test/integration/Websocket.test.ts +0 -65
- package/test/integration/WebsocketClientConnectorRpc.test.ts +0 -69
- package/test/integration/WebsocketConnectionManagement.test.ts +0 -191
- package/test/integration/rpc-connections-over-webrtc.test.ts +0 -123
- package/test/kademlia-simulation/data/nodeids.json +0 -13002
- package/test/kademlia-simulation/data/orderedneighbors.json +0 -1001
- package/test/types/global.d.ts +0 -1
- package/test/unit/AddressTools.test.ts +0 -44
- package/test/unit/AutoCertifierClientFacade.test.ts +0 -58
- package/test/unit/ConnectionManager.test.ts +0 -65
- package/test/unit/ConnectivityHelpers.test.ts +0 -61
- package/test/unit/DiscoverySession.test.ts +0 -87
- package/test/unit/DuplicateDetector.test.ts +0 -31
- package/test/unit/Handshaker.test.ts +0 -169
- package/test/unit/ListeningRpcCommunicator.test.ts +0 -52
- package/test/unit/LocalDataStore.test.ts +0 -108
- package/test/unit/ManagedConnection.test.ts +0 -58
- package/test/unit/PeerManager.test.ts +0 -93
- package/test/unit/PendingConnection.test.ts +0 -57
- package/test/unit/ProtobufMessage.test.ts +0 -21
- package/test/unit/RandomContactList.test.ts +0 -58
- package/test/unit/RecursiveOperationManager.test.ts +0 -161
- package/test/unit/RecursiveOperationSession.test.ts +0 -68
- package/test/unit/Router.test.ts +0 -137
- package/test/unit/RoutingSession.test.ts +0 -86
- package/test/unit/SortedContactList.test.ts +0 -115
- package/test/unit/StoreManager.test.ts +0 -146
- package/test/unit/StoreRpcLocal.test.ts +0 -167
- package/test/unit/WebrtcConnection.test.ts +0 -29
- package/test/unit/WebrtcConnector.test.ts +0 -56
- package/test/unit/WebsocketClientConnector.test.ts +0 -101
- package/test/unit/WebsocketServer.test.ts +0 -66
- package/test/unit/WebsocketServerConnector.test.ts +0 -102
- package/test/unit/connectivityRequestHandler.test.ts +0 -104
- package/test/unit/createPeerDescriptor.test.ts +0 -69
- package/test/unit/customMatchers.test.ts +0 -34
- package/test/unit/getClosestNodes.test.ts +0 -30
- package/test/unit/version.test.ts +0 -18
- package/test/unit/webrtcReplaceInternalIpWithExternalIp.test.ts +0 -18
- package/test/utils/FakeConnectorFacade.ts +0 -41
- package/test/utils/FakeRpcCommunicator.ts +0 -23
- package/test/utils/FakeTransport.ts +0 -79
- package/test/utils/customMatchers.ts +0 -71
- package/test/utils/mock/MockConnection.ts +0 -26
- package/test/utils/mock/MockConnectionsView.ts +0 -18
- package/test/utils/mock/MockRouter.ts +0 -62
- package/test/utils/mock/MockRpcCommunicator.ts +0 -7
- package/test/utils/mock/MockTransport.ts +0 -26
- package/test/utils/mock/mockDataEntry.ts +0 -38
- package/test/utils/topology.ts +0 -79
- package/test/utils/utils.ts +0 -268
- package/tsconfig.browser.json +0 -17
- package/tsconfig.jest.json +0 -25
- package/tsconfig.json +0 -3
- package/tsconfig.node.json +0 -24
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { Logger, areEqualBinaries } from '@streamr/utils'
|
|
2
|
-
import { Message, PeerDescriptor, RouteMessageAck, RouteMessageError, RouteMessageWrapper } from '../../../generated/packages/dht/protos/DhtRpc'
|
|
3
|
-
import { IRouterRpc } from '../../../generated/packages/dht/protos/DhtRpc.server'
|
|
4
|
-
import { DuplicateDetector } from './DuplicateDetector'
|
|
5
|
-
import { RoutingMode } from './RoutingSession'
|
|
6
|
-
import { areEqualPeerDescriptors, toDhtAddress, toNodeId } from '../../identifiers'
|
|
7
|
-
import { v4 } from 'uuid'
|
|
8
|
-
|
|
9
|
-
interface RouterRpcLocalOptions {
|
|
10
|
-
doRouteMessage: (routedMessage: RouteMessageWrapper, mode?: RoutingMode) => RouteMessageAck
|
|
11
|
-
setForwardingEntries: (routedMessage: RouteMessageWrapper) => void
|
|
12
|
-
handleMessage: (message: Message) => void
|
|
13
|
-
duplicateRequestDetector: DuplicateDetector
|
|
14
|
-
localPeerDescriptor: PeerDescriptor
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const logger = new Logger(module)
|
|
18
|
-
|
|
19
|
-
export const createRouteMessageAck = (routedMessage: RouteMessageWrapper, error?: RouteMessageError): RouteMessageAck => {
|
|
20
|
-
const ack: RouteMessageAck = {
|
|
21
|
-
requestId: routedMessage.requestId,
|
|
22
|
-
error
|
|
23
|
-
}
|
|
24
|
-
return ack
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class RouterRpcLocal implements IRouterRpc {
|
|
28
|
-
|
|
29
|
-
private readonly options: RouterRpcLocalOptions
|
|
30
|
-
|
|
31
|
-
constructor(options: RouterRpcLocalOptions) {
|
|
32
|
-
this.options = options
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async routeMessage(routedMessage: RouteMessageWrapper): Promise<RouteMessageAck> {
|
|
36
|
-
if (this.options.duplicateRequestDetector.isMostLikelyDuplicate(routedMessage.requestId)) {
|
|
37
|
-
logger.trace(`Routing message ${routedMessage.requestId} from ${toNodeId(routedMessage.sourcePeer!)} `
|
|
38
|
-
+ `to ${toDhtAddress(routedMessage.target)} is likely a duplicate`)
|
|
39
|
-
return createRouteMessageAck(routedMessage, RouteMessageError.DUPLICATE)
|
|
40
|
-
}
|
|
41
|
-
logger.trace(`Processing received routeMessage ${routedMessage.requestId}`)
|
|
42
|
-
this.options.duplicateRequestDetector.add(routedMessage.requestId)
|
|
43
|
-
if (areEqualBinaries(this.options.localPeerDescriptor.nodeId, routedMessage.target)) {
|
|
44
|
-
logger.trace(`routing message targeted to self ${routedMessage.requestId}`)
|
|
45
|
-
this.options.setForwardingEntries(routedMessage)
|
|
46
|
-
this.options.handleMessage(routedMessage.message!)
|
|
47
|
-
return createRouteMessageAck(routedMessage)
|
|
48
|
-
} else {
|
|
49
|
-
return this.options.doRouteMessage(routedMessage)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async forwardMessage(forwardMessage: RouteMessageWrapper): Promise<RouteMessageAck> {
|
|
54
|
-
if (this.options.duplicateRequestDetector.isMostLikelyDuplicate(forwardMessage.requestId)) {
|
|
55
|
-
logger.trace(`Forwarding message ${forwardMessage.requestId} from ${toNodeId(forwardMessage.sourcePeer!)} `
|
|
56
|
-
+ `to ${toDhtAddress(forwardMessage.target)} is likely a duplicate`)
|
|
57
|
-
return createRouteMessageAck(forwardMessage, RouteMessageError.DUPLICATE)
|
|
58
|
-
}
|
|
59
|
-
logger.trace(`Processing received forward routeMessage ${forwardMessage.requestId}`)
|
|
60
|
-
this.options.duplicateRequestDetector.add(forwardMessage.requestId)
|
|
61
|
-
if (areEqualBinaries(this.options.localPeerDescriptor.nodeId, forwardMessage.target)) {
|
|
62
|
-
return this.forwardToDestination(forwardMessage)
|
|
63
|
-
} else {
|
|
64
|
-
return this.options.doRouteMessage(forwardMessage, RoutingMode.FORWARD)
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
private forwardToDestination(routedMessage: RouteMessageWrapper): RouteMessageAck {
|
|
69
|
-
logger.trace(`Forwarding found message targeted to self ${routedMessage.requestId}`)
|
|
70
|
-
const forwardedMessage = routedMessage.message!
|
|
71
|
-
if (areEqualPeerDescriptors(this.options.localPeerDescriptor, forwardedMessage.targetDescriptor!)) {
|
|
72
|
-
this.options.handleMessage(forwardedMessage)
|
|
73
|
-
return createRouteMessageAck(routedMessage)
|
|
74
|
-
}
|
|
75
|
-
return this.options.doRouteMessage({ ...routedMessage, requestId: v4(), target: forwardedMessage.targetDescriptor!.nodeId })
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { Logger, areEqualBinaries } from '@streamr/utils'
|
|
2
|
-
import { v4 } from 'uuid'
|
|
3
|
-
import { RouteMessageError, RouteMessageWrapper } from '../../../generated/packages/dht/protos/DhtRpc'
|
|
4
|
-
import { RouterRpcClient } from '../../../generated/packages/dht/protos/DhtRpc.client'
|
|
5
|
-
import { RpcRemote } from '../contact/RpcRemote'
|
|
6
|
-
import { getPreviousPeer } from './getPreviousPeer'
|
|
7
|
-
import { toNodeId } from '../../identifiers'
|
|
8
|
-
|
|
9
|
-
const logger = new Logger(module)
|
|
10
|
-
|
|
11
|
-
// default timeout
|
|
12
|
-
export const ROUTING_TIMEOUT = 2000
|
|
13
|
-
|
|
14
|
-
export class RouterRpcRemote extends RpcRemote<RouterRpcClient> {
|
|
15
|
-
|
|
16
|
-
async routeMessage(params: RouteMessageWrapper): Promise<boolean> {
|
|
17
|
-
const message: RouteMessageWrapper = {
|
|
18
|
-
target: params.target,
|
|
19
|
-
sourcePeer: params.sourcePeer,
|
|
20
|
-
message: params.message,
|
|
21
|
-
requestId: params.requestId ?? v4(),
|
|
22
|
-
reachableThrough: params.reachableThrough ?? [],
|
|
23
|
-
routingPath: params.routingPath,
|
|
24
|
-
parallelRootNodeIds: params.parallelRootNodeIds
|
|
25
|
-
}
|
|
26
|
-
const options = this.formDhtRpcOptions({
|
|
27
|
-
connect: false
|
|
28
|
-
})
|
|
29
|
-
try {
|
|
30
|
-
const ack = await this.getClient().routeMessage(message, options)
|
|
31
|
-
// Success signal if sent to destination and error includes duplicate
|
|
32
|
-
if (ack.error === RouteMessageError.DUPLICATE
|
|
33
|
-
&& areEqualBinaries(params.target, this.getPeerDescriptor().nodeId)
|
|
34
|
-
) {
|
|
35
|
-
return true
|
|
36
|
-
} else if (ack.error !== undefined) {
|
|
37
|
-
return false
|
|
38
|
-
}
|
|
39
|
-
} catch (err) {
|
|
40
|
-
const previousPeer = getPreviousPeer(params)
|
|
41
|
-
const fromNode = previousPeer
|
|
42
|
-
? toNodeId(previousPeer)
|
|
43
|
-
: toNodeId(params.sourcePeer!)
|
|
44
|
-
const toNode = toNodeId(this.getPeerDescriptor())
|
|
45
|
-
logger.trace(`Failed to send routeMessage from ${fromNode} to ${toNode}`, { err })
|
|
46
|
-
return false
|
|
47
|
-
}
|
|
48
|
-
return true
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async forwardMessage(params: RouteMessageWrapper): Promise<boolean> {
|
|
52
|
-
const message: RouteMessageWrapper = {
|
|
53
|
-
target: params.target,
|
|
54
|
-
sourcePeer: params.sourcePeer,
|
|
55
|
-
message: params.message,
|
|
56
|
-
requestId: params.requestId ?? v4(),
|
|
57
|
-
reachableThrough: params.reachableThrough ?? [],
|
|
58
|
-
routingPath: params.routingPath,
|
|
59
|
-
parallelRootNodeIds: params.parallelRootNodeIds
|
|
60
|
-
}
|
|
61
|
-
const options = this.formDhtRpcOptions({
|
|
62
|
-
connect: false
|
|
63
|
-
})
|
|
64
|
-
try {
|
|
65
|
-
const ack = await this.getClient().forwardMessage(message, options)
|
|
66
|
-
if (ack.error !== undefined) {
|
|
67
|
-
return false
|
|
68
|
-
}
|
|
69
|
-
} catch (err) {
|
|
70
|
-
const previousPeer = getPreviousPeer(params)
|
|
71
|
-
const fromNode = previousPeer
|
|
72
|
-
? toNodeId(previousPeer)
|
|
73
|
-
: toNodeId(params.sourcePeer!)
|
|
74
|
-
const toNode = toNodeId(this.getPeerDescriptor())
|
|
75
|
-
logger.trace(`Failed to send forwardMessage from ${fromNode} to ${toNode}`, { err })
|
|
76
|
-
return false
|
|
77
|
-
}
|
|
78
|
-
return true
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import { SortedContactList } from '../contact/SortedContactList'
|
|
2
|
-
import { Logger } from '@streamr/utils'
|
|
3
|
-
import EventEmitter from 'eventemitter3'
|
|
4
|
-
import { v4 } from 'uuid'
|
|
5
|
-
import { PeerDescriptor, RouteMessageWrapper } from '../../../generated/packages/dht/protos/DhtRpc'
|
|
6
|
-
import { RouterRpcRemote, ROUTING_TIMEOUT } from './RouterRpcRemote'
|
|
7
|
-
import { RoutingRpcCommunicator } from '../../transport/RoutingRpcCommunicator'
|
|
8
|
-
import { RecursiveOperationRpcClient, RouterRpcClient } from '../../../generated/packages/dht/protos/DhtRpc.client'
|
|
9
|
-
import { Contact } from '../contact/Contact'
|
|
10
|
-
import { RecursiveOperationRpcRemote } from '../recursive-operation/RecursiveOperationRpcRemote'
|
|
11
|
-
import { getPreviousPeer } from './getPreviousPeer'
|
|
12
|
-
import { DhtAddress, areEqualPeerDescriptors, toDhtAddress, toNodeId } from '../../identifiers'
|
|
13
|
-
import { pull } from 'lodash'
|
|
14
|
-
import { RoutingTable, RoutingTablesCache } from './RoutingTablesCache'
|
|
15
|
-
|
|
16
|
-
const logger = new Logger(module)
|
|
17
|
-
|
|
18
|
-
const MAX_FAILED_HOPS = 2
|
|
19
|
-
const ROUTING_TABLE_MAX_SIZE = 5
|
|
20
|
-
|
|
21
|
-
export class RoutingRemoteContact extends Contact {
|
|
22
|
-
|
|
23
|
-
private routerRpcRemote: RouterRpcRemote
|
|
24
|
-
private recursiveOperationRpcRemote: RecursiveOperationRpcRemote
|
|
25
|
-
|
|
26
|
-
constructor(peer: PeerDescriptor, localPeerDescriptor: PeerDescriptor, rpcCommunicator: RoutingRpcCommunicator) {
|
|
27
|
-
super(peer)
|
|
28
|
-
this.routerRpcRemote = new RouterRpcRemote(
|
|
29
|
-
localPeerDescriptor,
|
|
30
|
-
peer,
|
|
31
|
-
rpcCommunicator,
|
|
32
|
-
RouterRpcClient,
|
|
33
|
-
ROUTING_TIMEOUT
|
|
34
|
-
)
|
|
35
|
-
this.recursiveOperationRpcRemote = new RecursiveOperationRpcRemote(
|
|
36
|
-
localPeerDescriptor,
|
|
37
|
-
peer,
|
|
38
|
-
rpcCommunicator,
|
|
39
|
-
RecursiveOperationRpcClient,
|
|
40
|
-
ROUTING_TIMEOUT
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
getRouterRpcRemote(): RouterRpcRemote {
|
|
45
|
-
return this.routerRpcRemote
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
getRecursiveOperationRpcRemote(): RecursiveOperationRpcRemote {
|
|
49
|
-
return this.recursiveOperationRpcRemote
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export interface RoutingSessionEvents {
|
|
54
|
-
// This event is emitted when a peer responds with a success ack
|
|
55
|
-
// to routeMessage call
|
|
56
|
-
routingSucceeded: () => void
|
|
57
|
-
partialSuccess: () => void
|
|
58
|
-
// This event is emitted when all the candidates have been gone
|
|
59
|
-
// through, and none of them responds with a success ack
|
|
60
|
-
routingFailed: () => void
|
|
61
|
-
stopped: () => void
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export enum RoutingMode { ROUTE, FORWARD, RECURSIVE }
|
|
65
|
-
|
|
66
|
-
interface RoutingSessionOptions {
|
|
67
|
-
rpcCommunicator: RoutingRpcCommunicator
|
|
68
|
-
localPeerDescriptor: PeerDescriptor
|
|
69
|
-
routedMessage: RouteMessageWrapper
|
|
70
|
-
parallelism: number
|
|
71
|
-
mode: RoutingMode
|
|
72
|
-
excludedNodeIds: Set<DhtAddress>
|
|
73
|
-
routingTablesCache: RoutingTablesCache
|
|
74
|
-
getConnections: () => PeerDescriptor[]
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export class RoutingSession extends EventEmitter<RoutingSessionEvents> {
|
|
78
|
-
|
|
79
|
-
public readonly sessionId = v4()
|
|
80
|
-
private ongoingRequests: Set<DhtAddress> = new Set()
|
|
81
|
-
private contactedPeers: Set<DhtAddress> = new Set()
|
|
82
|
-
private failedHopCounter = 0
|
|
83
|
-
private successfulHopCounter = 0
|
|
84
|
-
private stopped = false
|
|
85
|
-
private readonly options: RoutingSessionOptions
|
|
86
|
-
|
|
87
|
-
constructor(options: RoutingSessionOptions) {
|
|
88
|
-
super()
|
|
89
|
-
this.options = options
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
private onRequestFailed(nodeId: DhtAddress) {
|
|
93
|
-
logger.trace('onRequestFailed() sessionId: ' + this.sessionId)
|
|
94
|
-
if (this.stopped) {
|
|
95
|
-
return
|
|
96
|
-
}
|
|
97
|
-
if (this.ongoingRequests.has(nodeId)) {
|
|
98
|
-
this.ongoingRequests.delete(nodeId)
|
|
99
|
-
}
|
|
100
|
-
this.deleteParallelRootIfSource(nodeId)
|
|
101
|
-
this.failedHopCounter += 1
|
|
102
|
-
if (this.failedHopCounter >= MAX_FAILED_HOPS) {
|
|
103
|
-
logger.trace(`Stopping routing after ${MAX_FAILED_HOPS} failed attempts for sessionId: ${this.sessionId}`)
|
|
104
|
-
this.emitFailure()
|
|
105
|
-
return
|
|
106
|
-
}
|
|
107
|
-
const contacts = this.updateAndGetRoutablePeers()
|
|
108
|
-
if (contacts.length === 0 && this.ongoingRequests.size === 0) {
|
|
109
|
-
logger.trace('routing failed, emitting routingFailed sessionId: ' + this.sessionId)
|
|
110
|
-
this.emitFailure()
|
|
111
|
-
} else {
|
|
112
|
-
logger.trace('routing failed, retrying to route sessionId: ' + this.sessionId + ' failedHopCounter: ' + this.failedHopCounter)
|
|
113
|
-
this.sendMoreRequests(contacts)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
private emitFailure() {
|
|
118
|
-
if (this.successfulHopCounter >= 1) {
|
|
119
|
-
this.emit('partialSuccess')
|
|
120
|
-
} else {
|
|
121
|
-
this.emit('routingFailed')
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
private onRequestSucceeded() {
|
|
126
|
-
logger.trace('onRequestSucceeded() sessionId: ' + this.sessionId)
|
|
127
|
-
if (this.stopped) {
|
|
128
|
-
return
|
|
129
|
-
}
|
|
130
|
-
this.successfulHopCounter += 1
|
|
131
|
-
if (this.successfulHopCounter >= this.options.parallelism) {
|
|
132
|
-
this.emit('routingSucceeded')
|
|
133
|
-
return
|
|
134
|
-
}
|
|
135
|
-
const contacts = this.updateAndGetRoutablePeers()
|
|
136
|
-
if (contacts.length === 0) {
|
|
137
|
-
this.emit('routingSucceeded')
|
|
138
|
-
} else if (contacts.length > 0 && this.ongoingRequests.size === 0) {
|
|
139
|
-
this.sendMoreRequests(contacts)
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private async sendRouteMessageRequest(contact: RoutingRemoteContact): Promise<boolean> {
|
|
144
|
-
if (this.stopped) {
|
|
145
|
-
return false
|
|
146
|
-
}
|
|
147
|
-
const msg = {
|
|
148
|
-
...this.options.routedMessage,
|
|
149
|
-
routingPath: this.options.routedMessage.routingPath.concat([this.options.localPeerDescriptor])
|
|
150
|
-
}
|
|
151
|
-
if (this.options.mode === RoutingMode.FORWARD) {
|
|
152
|
-
return contact.getRouterRpcRemote().forwardMessage(msg)
|
|
153
|
-
} else if (this.options.mode === RoutingMode.RECURSIVE) {
|
|
154
|
-
return contact.getRecursiveOperationRpcRemote().routeRequest(msg)
|
|
155
|
-
} else {
|
|
156
|
-
return contact.getRouterRpcRemote().routeMessage(msg)
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
updateAndGetRoutablePeers(): RoutingRemoteContact[] {
|
|
161
|
-
logger.trace('getRoutablePeers() sessionId: ' + this.sessionId)
|
|
162
|
-
const previousPeer = getPreviousPeer(this.options.routedMessage)
|
|
163
|
-
const previousId = previousPeer ? toNodeId(previousPeer) : undefined
|
|
164
|
-
const targetId = toDhtAddress(this.options.routedMessage.target)
|
|
165
|
-
let routingTable: RoutingTable
|
|
166
|
-
if (this.options.routingTablesCache.has(targetId, previousId) && this.options.routingTablesCache.get(targetId, previousId)!.getSize() > 0) {
|
|
167
|
-
routingTable = this.options.routingTablesCache.get(targetId, previousId)!
|
|
168
|
-
} else {
|
|
169
|
-
routingTable = new SortedContactList<RoutingRemoteContact>({
|
|
170
|
-
referenceId: toDhtAddress(this.options.routedMessage.target),
|
|
171
|
-
maxSize: ROUTING_TABLE_MAX_SIZE,
|
|
172
|
-
allowToContainReferenceId: true,
|
|
173
|
-
nodeIdDistanceLimit: previousId
|
|
174
|
-
})
|
|
175
|
-
const contacts = this.options.getConnections()
|
|
176
|
-
.map((peer) => new RoutingRemoteContact(
|
|
177
|
-
peer,
|
|
178
|
-
this.options.localPeerDescriptor,
|
|
179
|
-
this.options.rpcCommunicator
|
|
180
|
-
))
|
|
181
|
-
routingTable.addContacts(contacts)
|
|
182
|
-
this.options.routingTablesCache.set(targetId, routingTable, previousId)
|
|
183
|
-
}
|
|
184
|
-
return routingTable.getClosestContacts()
|
|
185
|
-
.filter((contact) => !this.contactedPeers.has(contact.getNodeId()) && !this.options.excludedNodeIds.has(contact.getNodeId()))
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
sendMoreRequests(uncontacted: RoutingRemoteContact[]): void {
|
|
189
|
-
logger.trace('sendMoreRequests() sessionId: ' + this.sessionId)
|
|
190
|
-
if (this.stopped) {
|
|
191
|
-
return
|
|
192
|
-
}
|
|
193
|
-
if (uncontacted.length === 0) {
|
|
194
|
-
this.emitFailure()
|
|
195
|
-
return
|
|
196
|
-
}
|
|
197
|
-
while ((this.ongoingRequests.size < this.options.parallelism) && (uncontacted.length > 0) && !this.stopped) {
|
|
198
|
-
const nextPeer = uncontacted.shift()
|
|
199
|
-
logger.trace(`Sending routeMessage request to contact: ${toNodeId(nextPeer!.getPeerDescriptor())} (sessionId=${this.sessionId})`)
|
|
200
|
-
this.contactedPeers.add(nextPeer!.getNodeId())
|
|
201
|
-
this.ongoingRequests.add(nextPeer!.getNodeId())
|
|
202
|
-
this.addParallelRootIfSource(nextPeer!.getNodeId())
|
|
203
|
-
setImmediate(async () => {
|
|
204
|
-
try {
|
|
205
|
-
const succeeded = await this.sendRouteMessageRequest(nextPeer!)
|
|
206
|
-
if (succeeded) {
|
|
207
|
-
this.onRequestSucceeded()
|
|
208
|
-
} else {
|
|
209
|
-
this.onRequestFailed(nextPeer!.getNodeId())
|
|
210
|
-
}
|
|
211
|
-
} catch (err) {
|
|
212
|
-
logger.debug('Unable to route message ', { err })
|
|
213
|
-
} finally {
|
|
214
|
-
logger.trace('sendRouteMessageRequest returned')
|
|
215
|
-
}
|
|
216
|
-
})
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
private addParallelRootIfSource(nodeId: DhtAddress) {
|
|
221
|
-
if (
|
|
222
|
-
this.options.mode === RoutingMode.RECURSIVE
|
|
223
|
-
&& areEqualPeerDescriptors(this.options.localPeerDescriptor, this.options.routedMessage.sourcePeer!)
|
|
224
|
-
) {
|
|
225
|
-
this.options.routedMessage.parallelRootNodeIds.push(nodeId)
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
private deleteParallelRootIfSource(nodeId: DhtAddress) {
|
|
230
|
-
if (
|
|
231
|
-
this.options.mode === RoutingMode.RECURSIVE
|
|
232
|
-
&& areEqualPeerDescriptors(this.options.localPeerDescriptor, this.options.routedMessage.sourcePeer!)
|
|
233
|
-
) {
|
|
234
|
-
pull(this.options.routedMessage.parallelRootNodeIds, nodeId)
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
public stop(): void {
|
|
239
|
-
this.stopped = true
|
|
240
|
-
this.emit('stopped')
|
|
241
|
-
this.removeAllListeners()
|
|
242
|
-
}
|
|
243
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { DhtAddress } from '../../identifiers'
|
|
2
|
-
import { SortedContactList } from '../contact/SortedContactList'
|
|
3
|
-
import { RoutingRemoteContact } from './RoutingSession'
|
|
4
|
-
import { LRUCache } from 'lru-cache'
|
|
5
|
-
|
|
6
|
-
type RoutingTableID = string
|
|
7
|
-
export type RoutingTable = Pick<
|
|
8
|
-
SortedContactList<RoutingRemoteContact>,
|
|
9
|
-
'getClosestContacts' | 'addContacts' | 'addContact' | 'removeContact' | 'stop' | 'getSize'>
|
|
10
|
-
|
|
11
|
-
const createRoutingTableId = (targetId: DhtAddress, previousId?: DhtAddress): RoutingTableID => {
|
|
12
|
-
return targetId + (previousId ? previousId : '')
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const DEFAULT_LRU_OPTIONS = {
|
|
16
|
-
max: 1000,
|
|
17
|
-
maxAge: 15 * 1000
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* RoutingTablesCache is a cache for routing tables.
|
|
22
|
-
* It is used to store the routing tables for a specific targetId and previousId.
|
|
23
|
-
* Storing the previousId is important as it is used as a minimum distance for the contacts in the table.
|
|
24
|
-
* Calculating a RoutingTable from scratch is an O(n log n) operation (n = number of connections of a node)
|
|
25
|
-
* However,
|
|
26
|
-
* - Adding a contact to a RoutingTable is an O(log n) operation.
|
|
27
|
-
* - Deleting a contact from a RoutingTable is an O(1) operation.
|
|
28
|
-
* Thus, holding the most frequently used routing tables in memory to be updated on
|
|
29
|
-
* connections and disconnections is hugely beneficial in terms of performance.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
export class RoutingTablesCache {
|
|
33
|
-
|
|
34
|
-
private readonly tables: LRUCache<RoutingTableID, RoutingTable> = new LRUCache(DEFAULT_LRU_OPTIONS)
|
|
35
|
-
|
|
36
|
-
get(targetId: DhtAddress, previousId?: DhtAddress): RoutingTable | undefined {
|
|
37
|
-
return this.tables.get(createRoutingTableId(targetId, previousId))
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
set(targetId: DhtAddress, table: RoutingTable, previousId?: DhtAddress): void {
|
|
41
|
-
this.tables.set(createRoutingTableId(targetId, previousId), table)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
has(targetId: DhtAddress, previousId?: DhtAddress): boolean {
|
|
45
|
-
return this.tables.has(createRoutingTableId(targetId, previousId))
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
onNodeDisconnected(nodeId: DhtAddress): void {
|
|
49
|
-
this.tables.forEach((table) => table.removeContact(nodeId))
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
onNodeConnected(remote: RoutingRemoteContact): void {
|
|
53
|
-
this.tables.forEach((table) => table.addContact(remote))
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
reset(): void {
|
|
57
|
-
this.tables.forEach((table) => table.stop())
|
|
58
|
-
this.tables.clear()
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { last } from 'lodash'
|
|
2
|
-
import { PeerDescriptor, RouteMessageWrapper } from '../../../generated/packages/dht/protos/DhtRpc'
|
|
3
|
-
|
|
4
|
-
export const getPreviousPeer = (routeMessage: RouteMessageWrapper): PeerDescriptor | undefined => {
|
|
5
|
-
return last(routeMessage.routingPath)
|
|
6
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { DataEntry } from '../../../generated/packages/dht/protos/DhtRpc'
|
|
2
|
-
import { DhtAddress, toDhtAddress } from '../../identifiers'
|
|
3
|
-
import { MapWithTtl } from '@streamr/utils'
|
|
4
|
-
|
|
5
|
-
export class LocalDataStore {
|
|
6
|
-
|
|
7
|
-
private readonly maxTtl: number
|
|
8
|
-
|
|
9
|
-
constructor(maxTtl: number) {
|
|
10
|
-
this.maxTtl = maxTtl
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// A map into which each node can store one value per data key
|
|
14
|
-
// The first key is the key of the data, the second key is the
|
|
15
|
-
// DhtAddress of the creator of the data
|
|
16
|
-
private store: Map<DhtAddress, MapWithTtl<DhtAddress, DataEntry>> = new Map()
|
|
17
|
-
|
|
18
|
-
public storeEntry(dataEntry: DataEntry): boolean {
|
|
19
|
-
const key = toDhtAddress(dataEntry.key)
|
|
20
|
-
const creatorNodeId = toDhtAddress(dataEntry.creator)
|
|
21
|
-
if (!this.store.has(key)) {
|
|
22
|
-
this.store.set(key, new MapWithTtl((e) => Math.min(e.ttl, this.maxTtl)))
|
|
23
|
-
}
|
|
24
|
-
if (this.store.get(key)!.has(creatorNodeId)) {
|
|
25
|
-
const storedMillis = (dataEntry.createdAt!.seconds * 1000) + (dataEntry.createdAt!.nanos / 1000000)
|
|
26
|
-
const oldLocalEntry = this.store.get(key)!.get(creatorNodeId)!
|
|
27
|
-
const oldStoredMillis = (oldLocalEntry.createdAt!.seconds * 1000) + (oldLocalEntry.createdAt!.nanos / 1000000)
|
|
28
|
-
// do nothing if old entry is newer than the one being replicated
|
|
29
|
-
if (oldStoredMillis >= storedMillis) {
|
|
30
|
-
return false
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
this.store.get(key)!.set(creatorNodeId, dataEntry)
|
|
34
|
-
return true
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
public markAsDeleted(key: DhtAddress, creator: DhtAddress): boolean {
|
|
38
|
-
const item = this.store.get(key)
|
|
39
|
-
if (!item?.has(creator)) {
|
|
40
|
-
return false
|
|
41
|
-
}
|
|
42
|
-
const storedEntry = item.get(creator)
|
|
43
|
-
storedEntry!.deleted = true
|
|
44
|
-
return true
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
public* values(key?: DhtAddress): IterableIterator<DataEntry> {
|
|
48
|
-
if (key !== undefined) {
|
|
49
|
-
const map = this.store.get(key)
|
|
50
|
-
if (map !== undefined) {
|
|
51
|
-
yield* map.values()
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
for (const v of this.store.values()) {
|
|
55
|
-
yield* v.values()
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
public keys(): IterableIterator<DhtAddress> {
|
|
61
|
-
return this.store.keys()
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
public setAllEntriesAsStale(key: DhtAddress): void {
|
|
65
|
-
this.store.get(key)?.forEach((value) => {
|
|
66
|
-
value.stale = true
|
|
67
|
-
})
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
public deleteEntry(key: DhtAddress, creator: DhtAddress): void {
|
|
71
|
-
const storedEntry = this.store.get(key)?.get(creator)
|
|
72
|
-
if (storedEntry) {
|
|
73
|
-
this.store.get(key)?.delete(creator)
|
|
74
|
-
if (this.store.get(key)?.size() === 0) {
|
|
75
|
-
this.store.delete(key)
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
public clear(): void {
|
|
81
|
-
this.store.forEach((value) => value.clear())
|
|
82
|
-
this.store.clear()
|
|
83
|
-
}
|
|
84
|
-
}
|