@streamr/dht 100.0.0-testnet-three.4 → 100.0.0-testnet-three.6
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/package.json +7 -6
- package/dist/src/connection/ConnectionManager.d.ts +2 -1
- package/dist/src/connection/ConnectionManager.js +8 -1
- package/dist/src/connection/ConnectionManager.js.map +1 -1
- package/dist/src/connection/Handshaker.d.ts +2 -0
- package/dist/src/connection/Handshaker.js +6 -1
- package/dist/src/connection/Handshaker.js.map +1 -1
- package/dist/src/connection/ManagedConnection.js +1 -0
- package/dist/src/connection/ManagedConnection.js.map +1 -1
- package/dist/src/dht/DhtNode.d.ts +2 -1
- package/dist/src/dht/DhtNode.js +13 -6
- package/dist/src/dht/DhtNode.js.map +1 -1
- package/dist/src/dht/routing/Router.d.ts +5 -2
- package/dist/src/dht/routing/Router.js +17 -3
- package/dist/src/dht/routing/Router.js.map +1 -1
- package/dist/src/dht/routing/RouterRpcLocal.d.ts +2 -3
- package/dist/src/dht/routing/RouterRpcLocal.js +2 -2
- package/dist/src/dht/routing/RouterRpcLocal.js.map +1 -1
- package/dist/src/dht/routing/RoutingSession.d.ts +8 -6
- package/dist/src/dht/routing/RoutingSession.js +42 -40
- package/dist/src/dht/routing/RoutingSession.js.map +1 -1
- package/dist/src/dht/routing/RoutingTablesCache.d.ts +24 -0
- package/dist/src/dht/routing/RoutingTablesCache.js +46 -0
- package/dist/src/dht/routing/RoutingTablesCache.js.map +1 -0
- package/package.json +7 -6
- package/src/connection/ConnectionManager.ts +10 -2
- package/src/connection/Handshaker.ts +7 -2
- package/src/connection/ManagedConnection.ts +1 -0
- package/src/dht/DhtNode.ts +13 -6
- package/src/dht/routing/Router.ts +22 -6
- package/src/dht/routing/RouterRpcLocal.ts +4 -5
- package/src/dht/routing/RoutingSession.ts +50 -44
- package/src/dht/routing/RoutingTablesCache.ts +58 -0
- package/test/integration/RouteMessage.test.ts +5 -5
- package/test/unit/LocalDataStore.test.ts +2 -2
- package/test/unit/PeerManager.test.ts +1 -1
- package/test/unit/Router.test.ts +2 -1
- package/test/unit/RoutingSession.test.ts +7 -1
- package/test/utils/mock/Router.ts +9 -0
|
@@ -6,10 +6,11 @@ import { RoutingRpcCommunicator } from '../../transport/RoutingRpcCommunicator';
|
|
|
6
6
|
import { Contact } from '../contact/Contact';
|
|
7
7
|
import { RecursiveOperationRpcRemote } from '../recursive-operation/RecursiveOperationRpcRemote';
|
|
8
8
|
import { DhtAddress } from '../../identifiers';
|
|
9
|
-
|
|
9
|
+
import { RoutingTablesCache } from './RoutingTablesCache';
|
|
10
|
+
export declare class RoutingRemoteContact extends Contact {
|
|
10
11
|
private routerRpcRemote;
|
|
11
12
|
private recursiveOperationRpcRemote;
|
|
12
|
-
constructor(peer:
|
|
13
|
+
constructor(peer: PeerDescriptor, localPeerDescriptor: PeerDescriptor, rpcCommunicator: RoutingRpcCommunicator);
|
|
13
14
|
getRouterRpcRemote(): RouterRpcRemote;
|
|
14
15
|
getRecursiveOperationRpcRemote(): RecursiveOperationRpcRemote;
|
|
15
16
|
}
|
|
@@ -31,12 +32,13 @@ interface RoutingSessionConfig {
|
|
|
31
32
|
connections: Map<DhtAddress, DhtNodeRpcRemote>;
|
|
32
33
|
parallelism: number;
|
|
33
34
|
mode: RoutingMode;
|
|
34
|
-
excludedNodeIds
|
|
35
|
+
excludedNodeIds: Set<DhtAddress>;
|
|
36
|
+
routingTablesCache: RoutingTablesCache;
|
|
35
37
|
}
|
|
36
38
|
export declare class RoutingSession extends EventEmitter<RoutingSessionEvents> {
|
|
37
39
|
readonly sessionId: string;
|
|
38
40
|
private ongoingRequests;
|
|
39
|
-
private
|
|
41
|
+
private contactedPeers;
|
|
40
42
|
private failedHopCounter;
|
|
41
43
|
private successfulHopCounter;
|
|
42
44
|
private stopped;
|
|
@@ -46,8 +48,8 @@ export declare class RoutingSession extends EventEmitter<RoutingSessionEvents> {
|
|
|
46
48
|
private emitFailure;
|
|
47
49
|
private onRequestSucceeded;
|
|
48
50
|
private sendRouteMessageRequest;
|
|
49
|
-
updateAndGetRoutablePeers():
|
|
50
|
-
sendMoreRequests(uncontacted:
|
|
51
|
+
updateAndGetRoutablePeers(): RoutingRemoteContact[];
|
|
52
|
+
sendMoreRequests(uncontacted: RoutingRemoteContact[]): void;
|
|
51
53
|
private addParallelRootIfSource;
|
|
52
54
|
private deleteParallelRootIfSource;
|
|
53
55
|
stop(): void;
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.RoutingSession = exports.RoutingMode = void 0;
|
|
6
|
+
exports.RoutingSession = exports.RoutingMode = exports.RoutingRemoteContact = void 0;
|
|
7
7
|
const SortedContactList_1 = require("../contact/SortedContactList");
|
|
8
8
|
const utils_1 = require("@streamr/utils");
|
|
9
9
|
const eventemitter3_1 = __importDefault(require("eventemitter3"));
|
|
@@ -18,14 +18,14 @@ const identifiers_1 = require("../../identifiers");
|
|
|
18
18
|
const lodash_1 = require("lodash");
|
|
19
19
|
const logger = new utils_1.Logger(module);
|
|
20
20
|
const MAX_FAILED_HOPS = 2;
|
|
21
|
-
const
|
|
22
|
-
class
|
|
21
|
+
const ROUTING_TABLE_MAX_SIZE = 20;
|
|
22
|
+
class RoutingRemoteContact extends Contact_1.Contact {
|
|
23
23
|
routerRpcRemote;
|
|
24
24
|
recursiveOperationRpcRemote;
|
|
25
25
|
constructor(peer, localPeerDescriptor, rpcCommunicator) {
|
|
26
|
-
super(peer
|
|
27
|
-
this.routerRpcRemote = new RouterRpcRemote_1.RouterRpcRemote(localPeerDescriptor, peer
|
|
28
|
-
this.recursiveOperationRpcRemote = new RecursiveOperationRpcRemote_1.RecursiveOperationRpcRemote(localPeerDescriptor, peer
|
|
26
|
+
super(peer);
|
|
27
|
+
this.routerRpcRemote = new RouterRpcRemote_1.RouterRpcRemote(localPeerDescriptor, peer, rpcCommunicator, DhtRpc_client_1.RouterRpcClient, RpcRemote_1.EXISTING_CONNECTION_TIMEOUT);
|
|
28
|
+
this.recursiveOperationRpcRemote = new RecursiveOperationRpcRemote_1.RecursiveOperationRpcRemote(localPeerDescriptor, peer, rpcCommunicator, DhtRpc_client_1.RecursiveOperationRpcClient, RpcRemote_1.EXISTING_CONNECTION_TIMEOUT);
|
|
29
29
|
}
|
|
30
30
|
getRouterRpcRemote() {
|
|
31
31
|
return this.routerRpcRemote;
|
|
@@ -34,6 +34,7 @@ class RemoteContact extends Contact_1.Contact {
|
|
|
34
34
|
return this.recursiveOperationRpcRemote;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
exports.RoutingRemoteContact = RoutingRemoteContact;
|
|
37
38
|
var RoutingMode;
|
|
38
39
|
(function (RoutingMode) {
|
|
39
40
|
RoutingMode[RoutingMode["ROUTE"] = 0] = "ROUTE";
|
|
@@ -43,7 +44,7 @@ var RoutingMode;
|
|
|
43
44
|
class RoutingSession extends eventemitter3_1.default {
|
|
44
45
|
sessionId = (0, uuid_1.v4)();
|
|
45
46
|
ongoingRequests = new Set();
|
|
46
|
-
|
|
47
|
+
contactedPeers = new Set();
|
|
47
48
|
failedHopCounter = 0;
|
|
48
49
|
successfulHopCounter = 0;
|
|
49
50
|
stopped = false;
|
|
@@ -51,16 +52,6 @@ class RoutingSession extends eventemitter3_1.default {
|
|
|
51
52
|
constructor(config) {
|
|
52
53
|
super();
|
|
53
54
|
this.config = config;
|
|
54
|
-
const previousPeer = (0, getPreviousPeer_1.getPreviousPeer)(config.routedMessage);
|
|
55
|
-
const previousId = previousPeer ? (0, identifiers_1.getNodeIdFromPeerDescriptor)(previousPeer) : undefined;
|
|
56
|
-
this.contactList = new SortedContactList_1.SortedContactList({
|
|
57
|
-
referenceId: (0, identifiers_1.getDhtAddressFromRaw)(config.routedMessage.target),
|
|
58
|
-
maxSize: CONTACT_LIST_MAX_SIZE,
|
|
59
|
-
allowToContainReferenceId: true,
|
|
60
|
-
nodeIdDistanceLimit: previousId,
|
|
61
|
-
excludedNodeIds: config.excludedNodeIds,
|
|
62
|
-
emitEvents: false
|
|
63
|
-
});
|
|
64
55
|
}
|
|
65
56
|
onRequestFailed(nodeId) {
|
|
66
57
|
logger.trace('onRequestFailed() sessionId: ' + this.sessionId);
|
|
@@ -71,15 +62,18 @@ class RoutingSession extends eventemitter3_1.default {
|
|
|
71
62
|
this.ongoingRequests.delete(nodeId);
|
|
72
63
|
}
|
|
73
64
|
this.deleteParallelRootIfSource(nodeId);
|
|
65
|
+
this.failedHopCounter += 1;
|
|
66
|
+
if (this.failedHopCounter >= MAX_FAILED_HOPS) {
|
|
67
|
+
logger.trace(`Stopping routing after ${MAX_FAILED_HOPS} failed attempts for sessionId: ${this.sessionId}`);
|
|
68
|
+
this.emitFailure();
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
74
71
|
const contacts = this.updateAndGetRoutablePeers();
|
|
75
72
|
if (contacts.length === 0 && this.ongoingRequests.size === 0) {
|
|
76
73
|
logger.trace('routing failed, emitting routingFailed sessionId: ' + this.sessionId);
|
|
77
|
-
// TODO should call this.stop() so that we do cleanup? (after the emitFailure call)
|
|
78
|
-
this.stopped = true;
|
|
79
74
|
this.emitFailure();
|
|
80
75
|
}
|
|
81
76
|
else {
|
|
82
|
-
this.failedHopCounter += 1;
|
|
83
77
|
logger.trace('routing failed, retrying to route sessionId: ' + this.sessionId + ' failedHopCounter: ' + this.failedHopCounter);
|
|
84
78
|
this.sendMoreRequests(contacts);
|
|
85
79
|
}
|
|
@@ -98,10 +92,12 @@ class RoutingSession extends eventemitter3_1.default {
|
|
|
98
92
|
return;
|
|
99
93
|
}
|
|
100
94
|
this.successfulHopCounter += 1;
|
|
95
|
+
if (this.successfulHopCounter >= this.config.parallelism) {
|
|
96
|
+
this.emit('routingSucceeded');
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
101
99
|
const contacts = this.updateAndGetRoutablePeers();
|
|
102
|
-
if (
|
|
103
|
-
// TODO should call this.stop() so that we do cleanup? (after the routingSucceeded call)
|
|
104
|
-
this.stopped = true;
|
|
100
|
+
if (contacts.length === 0) {
|
|
105
101
|
this.emit('routingSucceeded');
|
|
106
102
|
}
|
|
107
103
|
else if (contacts.length > 0 && this.ongoingRequests.size === 0) {
|
|
@@ -128,16 +124,28 @@ class RoutingSession extends eventemitter3_1.default {
|
|
|
128
124
|
}
|
|
129
125
|
updateAndGetRoutablePeers() {
|
|
130
126
|
logger.trace('getRoutablePeers() sessionId: ' + this.sessionId);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
127
|
+
const previousPeer = (0, getPreviousPeer_1.getPreviousPeer)(this.config.routedMessage);
|
|
128
|
+
const previousId = previousPeer ? (0, identifiers_1.getNodeIdFromPeerDescriptor)(previousPeer) : undefined;
|
|
129
|
+
const targetId = (0, identifiers_1.getDhtAddressFromRaw)(this.config.routedMessage.target);
|
|
130
|
+
let routingTable;
|
|
131
|
+
if (this.config.routingTablesCache.has(targetId, previousId)) {
|
|
132
|
+
routingTable = this.config.routingTablesCache.get(targetId, previousId);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
routingTable = new SortedContactList_1.SortedContactList({
|
|
136
|
+
referenceId: (0, identifiers_1.getDhtAddressFromRaw)(this.config.routedMessage.target),
|
|
137
|
+
maxSize: ROUTING_TABLE_MAX_SIZE,
|
|
138
|
+
allowToContainReferenceId: true,
|
|
139
|
+
nodeIdDistanceLimit: previousId,
|
|
140
|
+
emitEvents: false
|
|
141
|
+
});
|
|
142
|
+
const contacts = Array.from(this.config.connections.values())
|
|
143
|
+
.map((peer) => new RoutingRemoteContact(peer.getPeerDescriptor(), this.config.localPeerDescriptor, this.config.rpcCommunicator));
|
|
144
|
+
routingTable.addContacts(contacts);
|
|
145
|
+
this.config.routingTablesCache.set(targetId, routingTable, previousId);
|
|
146
|
+
}
|
|
147
|
+
return routingTable.getAllContacts()
|
|
148
|
+
.filter((contact) => !this.contactedPeers.has(contact.getNodeId()) && !this.config.excludedNodeIds.has(contact.getNodeId()));
|
|
141
149
|
}
|
|
142
150
|
sendMoreRequests(uncontacted) {
|
|
143
151
|
logger.trace('sendMoreRequests() sessionId: ' + this.sessionId);
|
|
@@ -148,16 +156,11 @@ class RoutingSession extends eventemitter3_1.default {
|
|
|
148
156
|
this.emitFailure();
|
|
149
157
|
return;
|
|
150
158
|
}
|
|
151
|
-
if (this.failedHopCounter >= MAX_FAILED_HOPS) {
|
|
152
|
-
logger.trace(`Stopping routing after ${MAX_FAILED_HOPS} failed attempts for sessionId: ${this.sessionId}`);
|
|
153
|
-
this.emitFailure();
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
159
|
while ((this.ongoingRequests.size < this.config.parallelism) && (uncontacted.length > 0) && !this.stopped) {
|
|
157
160
|
const nextPeer = uncontacted.shift();
|
|
158
161
|
// eslint-disable-next-line max-len
|
|
159
162
|
logger.trace(`Sending routeMessage request to contact: ${(0, identifiers_1.getNodeIdFromPeerDescriptor)(nextPeer.getPeerDescriptor())} (sessionId=${this.sessionId})`);
|
|
160
|
-
this.
|
|
163
|
+
this.contactedPeers.add(nextPeer.getNodeId());
|
|
161
164
|
this.ongoingRequests.add(nextPeer.getNodeId());
|
|
162
165
|
this.addParallelRootIfSource(nextPeer.getNodeId());
|
|
163
166
|
setImmediate(async () => {
|
|
@@ -193,7 +196,6 @@ class RoutingSession extends eventemitter3_1.default {
|
|
|
193
196
|
}
|
|
194
197
|
stop() {
|
|
195
198
|
this.stopped = true;
|
|
196
|
-
this.contactList.stop();
|
|
197
199
|
this.emit('stopped');
|
|
198
200
|
this.removeAllListeners();
|
|
199
201
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RoutingSession.js","sourceRoot":"","sources":["../../../../src/dht/routing/RoutingSession.ts"],"names":[],"mappings":";;;;;;AACA,oEAAgE;AAChE,0CAAuC;AACvC,kEAAwC;AACxC,+BAAyB;AAEzB,uDAAmD;AAEnD,iFAA4G;AAC5G,gDAA4C;AAC5C,oGAAgG;AAChG,oDAAkE;AAClE,uDAAmD;AACnD,mDAA0H;AAC1H,mCAA6B;
|
|
1
|
+
{"version":3,"file":"RoutingSession.js","sourceRoot":"","sources":["../../../../src/dht/routing/RoutingSession.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { DhtAddress } from '../../identifiers';
|
|
2
|
+
import { SortedContactList } from '../contact/SortedContactList';
|
|
3
|
+
import { RoutingRemoteContact } from './RoutingSession';
|
|
4
|
+
export type RoutingTable = Pick<SortedContactList<RoutingRemoteContact>, 'getAllContacts' | 'addContacts' | 'addContact' | 'removeContact' | 'stop'>;
|
|
5
|
+
/**
|
|
6
|
+
* RoutingTablesCache is a cache for routing tables.
|
|
7
|
+
* It is used to store the routing tables for a specific targetId and previousId.
|
|
8
|
+
* Storing the previousId is important as it is used as a minimum distance for the contacts in the table.
|
|
9
|
+
* Calculating a RoutingTable from scratch is an O(n log n) operation (n = number of connections of a node)
|
|
10
|
+
* However,
|
|
11
|
+
* - Adding a contact to a RoutingTable is an O(log n) operation.
|
|
12
|
+
* - Deleting a contact from a RoutingTable is an O(1) operation.
|
|
13
|
+
* Thus, holding the most frequently used routing tables in memory to be updated on
|
|
14
|
+
* connections and disconnections is hugely beneficial in terms of performance.
|
|
15
|
+
*/
|
|
16
|
+
export declare class RoutingTablesCache {
|
|
17
|
+
private readonly tables;
|
|
18
|
+
get(targetId: DhtAddress, previousId?: DhtAddress): RoutingTable | undefined;
|
|
19
|
+
set(targetId: DhtAddress, table: RoutingTable, previousId?: DhtAddress): void;
|
|
20
|
+
has(targetId: DhtAddress, previousId?: DhtAddress): boolean;
|
|
21
|
+
onNodeDisconnected(nodeId: DhtAddress): void;
|
|
22
|
+
onNodeConnected(remote: RoutingRemoteContact): void;
|
|
23
|
+
reset(): void;
|
|
24
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RoutingTablesCache = void 0;
|
|
4
|
+
const lru_cache_1 = require("lru-cache");
|
|
5
|
+
const createRoutingTableId = (targetId, previousId) => {
|
|
6
|
+
return targetId + (previousId ? previousId : '');
|
|
7
|
+
};
|
|
8
|
+
const DEFAULT_LRU_OPTIONS = {
|
|
9
|
+
max: 1000,
|
|
10
|
+
maxAge: 15 * 1000
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* RoutingTablesCache is a cache for routing tables.
|
|
14
|
+
* It is used to store the routing tables for a specific targetId and previousId.
|
|
15
|
+
* Storing the previousId is important as it is used as a minimum distance for the contacts in the table.
|
|
16
|
+
* Calculating a RoutingTable from scratch is an O(n log n) operation (n = number of connections of a node)
|
|
17
|
+
* However,
|
|
18
|
+
* - Adding a contact to a RoutingTable is an O(log n) operation.
|
|
19
|
+
* - Deleting a contact from a RoutingTable is an O(1) operation.
|
|
20
|
+
* Thus, holding the most frequently used routing tables in memory to be updated on
|
|
21
|
+
* connections and disconnections is hugely beneficial in terms of performance.
|
|
22
|
+
*/
|
|
23
|
+
class RoutingTablesCache {
|
|
24
|
+
tables = new lru_cache_1.LRUCache(DEFAULT_LRU_OPTIONS);
|
|
25
|
+
get(targetId, previousId) {
|
|
26
|
+
return this.tables.get(createRoutingTableId(targetId, previousId));
|
|
27
|
+
}
|
|
28
|
+
set(targetId, table, previousId) {
|
|
29
|
+
this.tables.set(createRoutingTableId(targetId, previousId), table);
|
|
30
|
+
}
|
|
31
|
+
has(targetId, previousId) {
|
|
32
|
+
return this.tables.has(createRoutingTableId(targetId, previousId));
|
|
33
|
+
}
|
|
34
|
+
onNodeDisconnected(nodeId) {
|
|
35
|
+
this.tables.forEach((table) => table.removeContact(nodeId));
|
|
36
|
+
}
|
|
37
|
+
onNodeConnected(remote) {
|
|
38
|
+
this.tables.forEach((table) => table.addContact(remote));
|
|
39
|
+
}
|
|
40
|
+
reset() {
|
|
41
|
+
this.tables.forEach((table) => table.stop());
|
|
42
|
+
this.tables.clear();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.RoutingTablesCache = RoutingTablesCache;
|
|
46
|
+
//# sourceMappingURL=RoutingTablesCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RoutingTablesCache.js","sourceRoot":"","sources":["../../../../src/dht/routing/RoutingTablesCache.ts"],"names":[],"mappings":";;;AAGA,yCAAoC;AAKpC,MAAM,oBAAoB,GAAG,CAAC,QAAoB,EAAE,UAAuB,EAAkB,EAAE;IAC3F,OAAO,QAAQ,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;AACpD,CAAC,CAAA;AAED,MAAM,mBAAmB,GAAG;IACxB,GAAG,EAAE,IAAI;IACT,MAAM,EAAE,EAAE,GAAG,IAAI;CACpB,CAAA;AAED;;;;;;;;;;EAUE;AAEF,MAAa,kBAAkB;IAEV,MAAM,GAA2C,IAAI,oBAAQ,CAAC,mBAAmB,CAAC,CAAA;IAEnG,GAAG,CAAC,QAAoB,EAAE,UAAuB;QAC7C,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAA;IACtE,CAAC;IAED,GAAG,CAAC,QAAoB,EAAE,KAAmB,EAAE,UAAuB;QAClE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,CAAA;IACtE,CAAC;IAED,GAAG,CAAC,QAAoB,EAAE,UAAuB;QAC7C,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAA;IACtE,CAAC;IAED,kBAAkB,CAAC,MAAkB;QACjC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAA;IAC/D,CAAC;IAED,eAAe,CAAC,MAA4B;QACxC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAA;IAC5D,CAAC;IAED,KAAK;QACD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;QAC5C,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;IACvB,CAAC;CACJ;AA5BD,gDA4BC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamr/dht",
|
|
3
|
-
"version": "100.0.0-testnet-three.
|
|
3
|
+
"version": "100.0.0-testnet-three.6",
|
|
4
4
|
"description": "Streamr Network DHT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -30,27 +30,28 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@protobuf-ts/runtime": "^2.8.2",
|
|
32
32
|
"@protobuf-ts/runtime-rpc": "^2.8.2",
|
|
33
|
-
"@streamr/autocertifier-client": "100.0.0-testnet-three.
|
|
34
|
-
"@streamr/proto-rpc": "100.0.0-testnet-three.
|
|
35
|
-
"@streamr/utils": "100.0.0-testnet-three.
|
|
33
|
+
"@streamr/autocertifier-client": "100.0.0-testnet-three.6",
|
|
34
|
+
"@streamr/proto-rpc": "100.0.0-testnet-three.6",
|
|
35
|
+
"@streamr/utils": "100.0.0-testnet-three.6",
|
|
36
36
|
"eventemitter3": "^5.0.0",
|
|
37
37
|
"heap": "^0.2.6",
|
|
38
38
|
"ipaddr.js": "^2.0.1",
|
|
39
39
|
"k-bucket": "^5.1.0",
|
|
40
40
|
"lodash": "^4.17.21",
|
|
41
|
+
"lru-cache": "10.2.0",
|
|
41
42
|
"node-datachannel": "^0.4.3",
|
|
42
43
|
"uuid": "^9.0.1",
|
|
43
44
|
"websocket": "^1.0.34"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"@streamr/browser-test-runner": "^0.0.1",
|
|
47
|
-
"@streamr/test-utils": "100.0.0-testnet-three.
|
|
48
|
+
"@streamr/test-utils": "100.0.0-testnet-three.6",
|
|
48
49
|
"@types/express": "^4.17.21",
|
|
49
50
|
"@types/heap": "^0.2.34",
|
|
50
51
|
"@types/k-bucket": "^5.0.1",
|
|
51
52
|
"@types/lodash": "^4.14.202",
|
|
52
53
|
"@types/sinon": "^17.0.3",
|
|
53
|
-
"@types/uuid": "^9.0.
|
|
54
|
+
"@types/uuid": "^9.0.8",
|
|
54
55
|
"@types/websocket": "^1.0.10",
|
|
55
56
|
"express": "^4.17.1",
|
|
56
57
|
"jest-leak-detector": "^27.3.1",
|
|
@@ -96,7 +96,7 @@ export class ConnectionManager extends EventEmitter<TransportEvents> implements
|
|
|
96
96
|
private config: ConnectionManagerConfig
|
|
97
97
|
private readonly metricsContext: MetricsContext
|
|
98
98
|
// TODO use config option or named constant?
|
|
99
|
-
private readonly duplicateMessageDetector: DuplicateDetector = new DuplicateDetector(
|
|
99
|
+
private readonly duplicateMessageDetector: DuplicateDetector = new DuplicateDetector(10000)
|
|
100
100
|
private readonly metrics: ConnectionManagerMetrics
|
|
101
101
|
private locks = new ConnectionLockHandler()
|
|
102
102
|
private connections: Map<DhtAddress, ManagedConnection> = new Map()
|
|
@@ -311,7 +311,7 @@ export class ConnectionManager extends EventEmitter<TransportEvents> implements
|
|
|
311
311
|
return this.locks.isRemoteLocked(nodeId)
|
|
312
312
|
}
|
|
313
313
|
|
|
314
|
-
|
|
314
|
+
private handleMessage(message: Message): void {
|
|
315
315
|
logger.trace('Received message of type ' + message.messageType)
|
|
316
316
|
if (message.messageType !== MessageType.RPC) {
|
|
317
317
|
logger.trace('Filtered out non-RPC message of type ' + message.messageType)
|
|
@@ -332,6 +332,14 @@ export class ConnectionManager extends EventEmitter<TransportEvents> implements
|
|
|
332
332
|
}
|
|
333
333
|
}
|
|
334
334
|
|
|
335
|
+
public handleIncomingMessage(message: Message): boolean {
|
|
336
|
+
if (message.serviceId === INTERNAL_SERVICE_ID) {
|
|
337
|
+
this.rpcCommunicator?.handleMessageFromPeer(message)
|
|
338
|
+
return true
|
|
339
|
+
}
|
|
340
|
+
return false
|
|
341
|
+
}
|
|
342
|
+
|
|
335
343
|
private onData(data: Uint8Array, peerDescriptor: PeerDescriptor): void {
|
|
336
344
|
if (this.state === ConnectionManagerState.STOPPED) {
|
|
337
345
|
return
|
|
@@ -22,7 +22,7 @@ export class Handshaker extends EventEmitter<HandshakerEvents> {
|
|
|
22
22
|
private static readonly HANDSHAKER_SERVICE_ID = 'system/handshaker'
|
|
23
23
|
private localPeerDescriptor: PeerDescriptor
|
|
24
24
|
private connection: IConnection
|
|
25
|
-
|
|
25
|
+
private readonly onDataListener: (data: Uint8Array) => void
|
|
26
26
|
constructor(
|
|
27
27
|
localPeerDescriptor: PeerDescriptor,
|
|
28
28
|
connection: IConnection
|
|
@@ -30,7 +30,8 @@ export class Handshaker extends EventEmitter<HandshakerEvents> {
|
|
|
30
30
|
super()
|
|
31
31
|
this.localPeerDescriptor = localPeerDescriptor
|
|
32
32
|
this.connection = connection
|
|
33
|
-
this.
|
|
33
|
+
this.onDataListener = (data: Uint8Array) => this.onData(data)
|
|
34
|
+
this.connection.on('data', this.onDataListener)
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
private onData(data: Uint8Array) {
|
|
@@ -101,4 +102,8 @@ export class Handshaker extends EventEmitter<HandshakerEvents> {
|
|
|
101
102
|
this.connection.send(Message.toBinary(msg))
|
|
102
103
|
logger.trace('handshake response sent')
|
|
103
104
|
}
|
|
105
|
+
|
|
106
|
+
public stop(): void {
|
|
107
|
+
this.connection.off('data', this.onDataListener)
|
|
108
|
+
}
|
|
104
109
|
}
|
|
@@ -177,6 +177,7 @@ export class ManagedConnection extends EventEmitter<Events> {
|
|
|
177
177
|
|
|
178
178
|
this.setRemotePeerDescriptor(peerDescriptor)
|
|
179
179
|
this.handshakeCompleted = true
|
|
180
|
+
this.handshaker!.stop()
|
|
180
181
|
|
|
181
182
|
while (this.outputBuffer.length > 0) {
|
|
182
183
|
logger.trace('emptying outputBuffer')
|
package/src/dht/DhtNode.ts
CHANGED
|
@@ -231,7 +231,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
|
|
|
231
231
|
{ rpcRequestTimeout: this.config.rpcRequestTimeout }
|
|
232
232
|
)
|
|
233
233
|
|
|
234
|
-
this.transport.on('message', (message: Message) => this.
|
|
234
|
+
this.transport.on('message', (message: Message) => this.handleMessageFromTransport(message))
|
|
235
235
|
|
|
236
236
|
this.initPeerManager()
|
|
237
237
|
|
|
@@ -250,7 +250,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
|
|
|
250
250
|
connections: this.peerManager!.connections,
|
|
251
251
|
localPeerDescriptor: this.localPeerDescriptor!,
|
|
252
252
|
addContact: (contact: PeerDescriptor, setActive?: boolean) => this.peerManager!.addContact([contact], setActive),
|
|
253
|
-
|
|
253
|
+
handleMessage: (message: Message) => this.handleMessageFromRouter(message),
|
|
254
254
|
})
|
|
255
255
|
this.recursiveOperationManager = new RecursiveOperationManager({
|
|
256
256
|
rpcCommunicator: this.rpcCommunicator,
|
|
@@ -326,10 +326,12 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
|
|
|
326
326
|
})
|
|
327
327
|
this.transport!.on('connected', (peerDescriptor: PeerDescriptor) => {
|
|
328
328
|
this.peerManager!.onContactConnected(peerDescriptor)
|
|
329
|
+
this.router!.onNodeConnected(peerDescriptor)
|
|
329
330
|
this.emit('connected', peerDescriptor)
|
|
330
331
|
})
|
|
331
332
|
this.transport!.on('disconnected', (peerDescriptor: PeerDescriptor, gracefulLeave: boolean) => {
|
|
332
333
|
this.peerManager!.onContactDisconnected(getNodeIdFromPeerDescriptor(peerDescriptor), gracefulLeave)
|
|
334
|
+
this.router!.onNodeDisconnected(peerDescriptor)
|
|
333
335
|
this.emit('disconnected', peerDescriptor, gracefulLeave)
|
|
334
336
|
})
|
|
335
337
|
this.transport!.getConnections().forEach((peer) => {
|
|
@@ -378,13 +380,18 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
|
|
|
378
380
|
)
|
|
379
381
|
}
|
|
380
382
|
|
|
381
|
-
private
|
|
382
|
-
const nodeId = getNodeIdFromPeerDescriptor(message.sourceDescriptor!)
|
|
383
|
+
private handleMessageFromTransport(message: Message): void {
|
|
383
384
|
if (message.serviceId === this.config.serviceId) {
|
|
384
|
-
logger.trace('calling this.handleMessageFromPeer ' + nodeId + ' ' + message.serviceId + ' ' + message.messageId)
|
|
385
385
|
this.rpcCommunicator?.handleMessageFromPeer(message)
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
private handleMessageFromRouter(message: Message): void {
|
|
390
|
+
if (message.serviceId === this.config.serviceId) {
|
|
391
|
+
this.rpcCommunicator?.handleMessageFromPeer(message)
|
|
392
|
+
} else if (this.connectionManager?.handleIncomingMessage(message)) {
|
|
393
|
+
// message was handled by connectionManager
|
|
386
394
|
} else {
|
|
387
|
-
logger.trace('emit "message" ' + nodeId + ' ' + message.serviceId + ' ' + message.messageId)
|
|
388
395
|
this.emit('message', message)
|
|
389
396
|
}
|
|
390
397
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { Message, PeerDescriptor, RouteMessageAck, RouteMessageError, RouteMessageWrapper } from '../../proto/packages/dht/protos/DhtRpc'
|
|
2
|
-
import { RoutingMode, RoutingSession, RoutingSessionEvents } from './RoutingSession'
|
|
2
|
+
import { RoutingMode, RoutingRemoteContact, RoutingSession, RoutingSessionEvents } from './RoutingSession'
|
|
3
3
|
import { Logger, executeSafePromise, raceEvents3, withTimeout } from '@streamr/utils'
|
|
4
4
|
import { RoutingRpcCommunicator } from '../../transport/RoutingRpcCommunicator'
|
|
5
5
|
import { DuplicateDetector } from './DuplicateDetector'
|
|
6
|
-
import { ConnectionManager } from '../../connection/ConnectionManager'
|
|
7
6
|
import { DhtNodeRpcRemote } from '../DhtNodeRpcRemote'
|
|
8
7
|
import { v4 } from 'uuid'
|
|
9
8
|
import { RouterRpcLocal, createRouteMessageAck } from './RouterRpcLocal'
|
|
10
9
|
import { DhtAddress, areEqualPeerDescriptors, getDhtAddressFromRaw, getNodeIdFromPeerDescriptor } from '../../identifiers'
|
|
10
|
+
import { RoutingTablesCache } from './RoutingTablesCache'
|
|
11
11
|
|
|
12
12
|
export interface RouterConfig {
|
|
13
13
|
rpcCommunicator: RoutingRpcCommunicator
|
|
14
14
|
localPeerDescriptor: PeerDescriptor
|
|
15
15
|
connections: Map<DhtAddress, DhtNodeRpcRemote>
|
|
16
16
|
addContact: (contact: PeerDescriptor, setActive?: boolean) => void
|
|
17
|
-
|
|
17
|
+
handleMessage: (message: Message) => void
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
interface ForwardingTableEntry {
|
|
@@ -27,9 +27,10 @@ const logger = new Logger(module)
|
|
|
27
27
|
export class Router {
|
|
28
28
|
|
|
29
29
|
private readonly forwardingTable: Map<DhtAddress, ForwardingTableEntry> = new Map()
|
|
30
|
+
private readonly routingTablesCache = new RoutingTablesCache()
|
|
30
31
|
private ongoingRoutingSessions: Map<string, RoutingSession> = new Map()
|
|
31
32
|
// TODO use config option or named constant?
|
|
32
|
-
private readonly duplicateRequestDetector: DuplicateDetector = new DuplicateDetector(
|
|
33
|
+
private readonly duplicateRequestDetector: DuplicateDetector = new DuplicateDetector(10000)
|
|
33
34
|
private stopped = false
|
|
34
35
|
private readonly config: RouterConfig
|
|
35
36
|
|
|
@@ -45,7 +46,7 @@ export class Router {
|
|
|
45
46
|
setForwardingEntries: (routedMessage: RouteMessageWrapper) => this.setForwardingEntries(routedMessage),
|
|
46
47
|
duplicateRequestDetector: this.duplicateRequestDetector,
|
|
47
48
|
localPeerDescriptor: this.config.localPeerDescriptor,
|
|
48
|
-
|
|
49
|
+
handleMessage: this.config.handleMessage
|
|
49
50
|
})
|
|
50
51
|
this.config.rpcCommunicator.registerRpcMethod(
|
|
51
52
|
RouteMessageWrapper,
|
|
@@ -168,7 +169,8 @@ export class Router {
|
|
|
168
169
|
// TODO use config option or named constant?
|
|
169
170
|
parallelism: areEqualPeerDescriptors(this.config.localPeerDescriptor, routedMessage.sourcePeer!) ? 2 : 1,
|
|
170
171
|
mode,
|
|
171
|
-
excludedNodeIds
|
|
172
|
+
excludedNodeIds,
|
|
173
|
+
routingTablesCache: this.routingTablesCache
|
|
172
174
|
})
|
|
173
175
|
}
|
|
174
176
|
|
|
@@ -188,6 +190,19 @@ export class Router {
|
|
|
188
190
|
this.ongoingRoutingSessions.delete(sessionId)
|
|
189
191
|
}
|
|
190
192
|
|
|
193
|
+
onNodeConnected(peerDescriptor: PeerDescriptor): void {
|
|
194
|
+
const remote = new RoutingRemoteContact(peerDescriptor, this.config.localPeerDescriptor, this.config.rpcCommunicator)
|
|
195
|
+
this.routingTablesCache.onNodeConnected(remote)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
onNodeDisconnected(peerDescriptor: PeerDescriptor): void {
|
|
199
|
+
this.routingTablesCache.onNodeDisconnected(getNodeIdFromPeerDescriptor(peerDescriptor))
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
public resetCache(): void {
|
|
203
|
+
this.routingTablesCache.reset()
|
|
204
|
+
}
|
|
205
|
+
|
|
191
206
|
public stop(): void {
|
|
192
207
|
this.stopped = true
|
|
193
208
|
this.ongoingRoutingSessions.forEach((session, _id) => {
|
|
@@ -199,6 +214,7 @@ export class Router {
|
|
|
199
214
|
})
|
|
200
215
|
this.forwardingTable.clear()
|
|
201
216
|
this.duplicateRequestDetector.clear()
|
|
217
|
+
this.routingTablesCache.reset()
|
|
202
218
|
}
|
|
203
219
|
|
|
204
220
|
private setForwardingEntries(routedMessage: RouteMessageWrapper): void {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Logger, areEqualBinaries } from '@streamr/utils'
|
|
2
|
-
import {
|
|
3
|
-
import { PeerDescriptor, RouteMessageAck, RouteMessageError, RouteMessageWrapper } from '../../proto/packages/dht/protos/DhtRpc'
|
|
2
|
+
import { Message, PeerDescriptor, RouteMessageAck, RouteMessageError, RouteMessageWrapper } from '../../proto/packages/dht/protos/DhtRpc'
|
|
4
3
|
import { IRouterRpc } from '../../proto/packages/dht/protos/DhtRpc.server'
|
|
5
4
|
import { DuplicateDetector } from './DuplicateDetector'
|
|
6
5
|
import { RoutingMode } from './RoutingSession'
|
|
@@ -11,9 +10,9 @@ interface RouterRpcLocalConfig {
|
|
|
11
10
|
doRouteMessage: (routedMessage: RouteMessageWrapper, mode?: RoutingMode) => RouteMessageAck
|
|
12
11
|
addContact: (contact: PeerDescriptor, setActive: boolean) => void
|
|
13
12
|
setForwardingEntries: (routedMessage: RouteMessageWrapper) => void
|
|
13
|
+
handleMessage: (message: Message) => void
|
|
14
14
|
duplicateRequestDetector: DuplicateDetector
|
|
15
15
|
localPeerDescriptor: PeerDescriptor
|
|
16
|
-
connectionManager?: ConnectionManager
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
const logger = new Logger(module)
|
|
@@ -45,7 +44,7 @@ export class RouterRpcLocal implements IRouterRpc {
|
|
|
45
44
|
if (areEqualBinaries(this.config.localPeerDescriptor.nodeId, routedMessage.target)) {
|
|
46
45
|
logger.trace(`routing message targeted to self ${routedMessage.requestId}`)
|
|
47
46
|
this.config.setForwardingEntries(routedMessage)
|
|
48
|
-
this.config.
|
|
47
|
+
this.config.handleMessage(routedMessage.message!)
|
|
49
48
|
return createRouteMessageAck(routedMessage)
|
|
50
49
|
} else {
|
|
51
50
|
return this.config.doRouteMessage(routedMessage)
|
|
@@ -71,7 +70,7 @@ export class RouterRpcLocal implements IRouterRpc {
|
|
|
71
70
|
logger.trace(`Forwarding found message targeted to self ${routedMessage.requestId}`)
|
|
72
71
|
const forwardedMessage = routedMessage.message!
|
|
73
72
|
if (areEqualPeerDescriptors(this.config.localPeerDescriptor, forwardedMessage.targetDescriptor!)) {
|
|
74
|
-
this.config.
|
|
73
|
+
this.config.handleMessage(forwardedMessage)
|
|
75
74
|
return createRouteMessageAck(routedMessage)
|
|
76
75
|
}
|
|
77
76
|
return this.config.doRouteMessage({ ...routedMessage, requestId: v4(), target: forwardedMessage.targetDescriptor!.nodeId })
|