@streamr/trackerless-network 102.0.0-beta.0 → 102.0.0-beta.2
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.js.map +1 -0
- package/dist/generated/google/protobuf/empty.js.map +1 -0
- package/dist/generated/google/protobuf/timestamp.js.map +1 -0
- package/dist/{src/proto → generated}/packages/dht/protos/DhtRpc.client.d.ts +9 -0
- package/dist/{src/proto → generated}/packages/dht/protos/DhtRpc.client.js +7 -0
- package/dist/generated/packages/dht/protos/DhtRpc.client.js.map +1 -0
- package/dist/{src/proto → generated}/packages/dht/protos/DhtRpc.d.ts +32 -8
- package/dist/{src/proto → generated}/packages/dht/protos/DhtRpc.js +23 -7
- package/dist/generated/packages/dht/protos/DhtRpc.js.map +1 -0
- package/dist/{src/proto → generated}/packages/dht/protos/DhtRpc.server.d.ts +5 -0
- package/dist/generated/packages/dht/protos/DhtRpc.server.js.map +1 -0
- package/dist/generated/packages/proto-rpc/protos/ProtoRpc.js.map +1 -0
- package/dist/generated/packages/trackerless-network/protos/NetworkRpc.client.js.map +1 -0
- package/dist/{src/proto → generated}/packages/trackerless-network/protos/NetworkRpc.d.ts +3 -3
- package/dist/{src/proto → generated}/packages/trackerless-network/protos/NetworkRpc.js +1 -1
- package/dist/generated/packages/trackerless-network/protos/NetworkRpc.js.map +1 -0
- package/dist/generated/packages/trackerless-network/protos/NetworkRpc.server.js.map +1 -0
- package/dist/package.json +9 -10
- package/dist/src/NetworkNode.d.ts +4 -3
- package/dist/src/NetworkNode.js.map +1 -1
- package/dist/src/NetworkStack.d.ts +2 -2
- package/dist/src/NetworkStack.js +4 -4
- package/dist/src/NetworkStack.js.map +1 -1
- package/dist/src/exports.d.ts +3 -2
- package/dist/src/exports.js +3 -2
- package/dist/src/exports.js.map +1 -1
- package/dist/src/logic/ContentDeliveryLayerNode.d.ts +2 -1
- package/dist/src/logic/ContentDeliveryLayerNode.js +5 -5
- package/dist/src/logic/ContentDeliveryLayerNode.js.map +1 -1
- package/dist/src/logic/ContentDeliveryManager.d.ts +2 -1
- package/dist/src/logic/ContentDeliveryManager.js +2 -1
- package/dist/src/logic/ContentDeliveryManager.js.map +1 -1
- package/dist/src/logic/ContentDeliveryRpcLocal.d.ts +3 -3
- package/dist/src/logic/ContentDeliveryRpcLocal.js +1 -1
- package/dist/src/logic/ContentDeliveryRpcLocal.js.map +1 -1
- package/dist/src/logic/ContentDeliveryRpcRemote.d.ts +2 -2
- package/dist/src/logic/ControlLayerNode.d.ts +1 -1
- package/dist/src/logic/DiscoveryLayerNode.d.ts +3 -3
- package/dist/src/logic/DuplicateMessageDetector.js +1 -1
- package/dist/src/logic/DuplicateMessageDetector.js.map +1 -1
- package/dist/src/logic/PeerDescriptorStoreManager.d.ts +1 -1
- package/dist/src/logic/PeerDescriptorStoreManager.js +1 -1
- package/dist/src/logic/PeerDescriptorStoreManager.js.map +1 -1
- package/dist/src/logic/inspect/InspectSession.d.ts +2 -2
- package/dist/src/logic/inspect/InspectSession.js +2 -2
- package/dist/src/logic/inspect/InspectSession.js.map +1 -1
- package/dist/src/logic/inspect/Inspector.d.ts +1 -1
- package/dist/src/logic/inspect/Inspector.js +1 -1
- package/dist/src/logic/inspect/Inspector.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/HandshakeRpcLocal.d.ts +2 -2
- package/dist/src/logic/neighbor-discovery/HandshakeRpcRemote.d.ts +2 -2
- package/dist/src/logic/neighbor-discovery/Handshaker.js +2 -2
- package/dist/src/logic/neighbor-discovery/Handshaker.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js +2 -2
- package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.d.ts +2 -2
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.d.ts +1 -1
- package/dist/src/logic/node-info/NodeInfoClient.d.ts +1 -1
- package/dist/src/logic/node-info/NodeInfoClient.js +1 -1
- package/dist/src/logic/node-info/NodeInfoClient.js.map +1 -1
- package/dist/src/logic/node-info/NodeInfoRpcLocal.d.ts +2 -2
- package/dist/src/logic/node-info/NodeInfoRpcLocal.js +1 -1
- package/dist/src/logic/node-info/NodeInfoRpcLocal.js.map +1 -1
- package/dist/src/logic/node-info/NodeInfoRpcRemote.d.ts +2 -2
- package/dist/src/logic/propagation/Propagation.d.ts +1 -1
- package/dist/src/logic/propagation/PropagationTaskStore.d.ts +1 -1
- package/dist/src/logic/proxy/ProxyClient.d.ts +1 -2
- package/dist/src/logic/proxy/ProxyClient.js +2 -3
- package/dist/src/logic/proxy/ProxyClient.js.map +1 -1
- package/dist/src/logic/proxy/ProxyConnectionRpcLocal.d.ts +2 -2
- package/dist/src/logic/proxy/ProxyConnectionRpcLocal.js +4 -4
- package/dist/src/logic/proxy/ProxyConnectionRpcLocal.js.map +1 -1
- package/dist/src/logic/proxy/ProxyConnectionRpcRemote.d.ts +2 -2
- package/dist/src/logic/proxy/ProxyConnectionRpcRemote.js +1 -1
- package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.d.ts +4 -4
- package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.js +1 -1
- package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.js.map +1 -1
- package/dist/src/logic/temporary-connection/TemporaryConnectionRpcRemote.d.ts +1 -1
- package/dist/src/logic/utils.d.ts +1 -1
- package/dist/src/logic/utils.js +2 -2
- package/dist/src/logic/utils.js.map +1 -1
- package/dist/src/types.d.ts +6 -0
- package/dist/src/types.js +3 -0
- package/dist/src/types.js.map +1 -0
- package/dist/test/benchmark/first-message.js +2 -2
- package/dist/test/benchmark/first-message.js.map +1 -1
- package/dist/test/utils/utils.d.ts +2 -2
- package/dist/test/utils/utils.js +5 -4
- package/dist/test/utils/utils.js.map +1 -1
- package/jest.config.ts +13 -0
- package/package.json +9 -10
- package/proto.sh +2 -2
- package/protos/NetworkRpc.proto +2 -3
- package/.eslintignore +0 -7
- package/.eslintrc +0 -3
- package/dist/src/proto/google/protobuf/any.js.map +0 -1
- package/dist/src/proto/google/protobuf/empty.js.map +0 -1
- package/dist/src/proto/google/protobuf/timestamp.js.map +0 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +0 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +0 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.server.js.map +0 -1
- package/dist/src/proto/packages/proto-rpc/protos/ProtoRpc.js.map +0 -1
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.js.map +0 -1
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js.map +0 -1
- package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.server.js.map +0 -1
- package/jest.config.js +0 -8
- package/src/NetworkNode.ts +0 -141
- package/src/NetworkStack.ts +0 -198
- package/src/exports.ts +0 -16
- package/src/logic/ContentDeliveryLayerNode.ts +0 -424
- package/src/logic/ContentDeliveryManager.ts +0 -399
- package/src/logic/ContentDeliveryRpcLocal.ts +0 -48
- package/src/logic/ContentDeliveryRpcRemote.ts +0 -44
- package/src/logic/ControlLayerNode.ts +0 -17
- package/src/logic/DiscoveryLayerNode.ts +0 -30
- package/src/logic/DuplicateMessageDetector.ts +0 -167
- package/src/logic/ExternalNetworkRpc.ts +0 -42
- package/src/logic/NodeList.ts +0 -114
- package/src/logic/PeerDescriptorStoreManager.ts +0 -96
- package/src/logic/StreamPartNetworkSplitAvoidance.ts +0 -90
- package/src/logic/StreamPartReconnect.ts +0 -38
- package/src/logic/createContentDeliveryLayerNode.ts +0 -130
- package/src/logic/formStreamPartDeliveryServiceId.ts +0 -7
- package/src/logic/inspect/InspectSession.ts +0 -54
- package/src/logic/inspect/Inspector.ts +0 -100
- package/src/logic/neighbor-discovery/HandshakeRpcLocal.ts +0 -138
- package/src/logic/neighbor-discovery/HandshakeRpcRemote.ts +0 -66
- package/src/logic/neighbor-discovery/Handshaker.ts +0 -215
- package/src/logic/neighbor-discovery/NeighborFinder.ts +0 -77
- package/src/logic/neighbor-discovery/NeighborUpdateManager.ts +0 -69
- package/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.ts +0 -75
- package/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.ts +0 -35
- package/src/logic/node-info/NodeInfoClient.ts +0 -23
- package/src/logic/node-info/NodeInfoRpcLocal.ts +0 -28
- package/src/logic/node-info/NodeInfoRpcRemote.ts +0 -11
- package/src/logic/propagation/FifoMapWithTTL.ts +0 -116
- package/src/logic/propagation/Propagation.ts +0 -84
- package/src/logic/propagation/PropagationTaskStore.ts +0 -41
- package/src/logic/proxy/ProxyClient.ts +0 -287
- package/src/logic/proxy/ProxyConnectionRpcLocal.ts +0 -106
- package/src/logic/proxy/ProxyConnectionRpcRemote.ts +0 -26
- package/src/logic/temporary-connection/TemporaryConnectionRpcLocal.ts +0 -73
- package/src/logic/temporary-connection/TemporaryConnectionRpcRemote.ts +0 -29
- package/src/logic/utils.ts +0 -18
- package/src/proto/google/protobuf/any.ts +0 -326
- package/src/proto/google/protobuf/empty.ts +0 -81
- package/src/proto/google/protobuf/timestamp.ts +0 -287
- package/src/proto/packages/dht/protos/DhtRpc.client.ts +0 -407
- package/src/proto/packages/dht/protos/DhtRpc.server.ts +0 -160
- package/src/proto/packages/dht/protos/DhtRpc.ts +0 -1244
- package/src/proto/packages/proto-rpc/protos/ProtoRpc.ts +0 -108
- package/src/proto/packages/trackerless-network/protos/NetworkRpc.client.ts +0 -218
- package/src/proto/packages/trackerless-network/protos/NetworkRpc.server.ts +0 -85
- package/src/proto/packages/trackerless-network/protos/NetworkRpc.ts +0 -783
- package/test/benchmark/StreamPartIdDataKeyDistribution.test.ts +0 -60
- package/test/benchmark/first-message.ts +0 -169
- package/test/end-to-end/content-delivery-layer-node-with-real-connections.test.ts +0 -160
- package/test/end-to-end/external-network-rpc.test.ts +0 -67
- package/test/end-to-end/inspect.test.ts +0 -124
- package/test/end-to-end/proxy-and-full-node.test.ts +0 -143
- package/test/end-to-end/proxy-connections.test.ts +0 -228
- package/test/end-to-end/proxy-key-exchange.test.ts +0 -126
- package/test/end-to-end/webrtc-full-node-network.test.ts +0 -85
- package/test/end-to-end/websocket-full-node-network.test.ts +0 -84
- package/test/integration/ContentDeliveryLayerNode-Layer1Node-Latencies.test.ts +0 -139
- package/test/integration/ContentDeliveryLayerNode-Layer1Node.test.ts +0 -162
- package/test/integration/ContentDeliveryManager.test.ts +0 -157
- package/test/integration/ContentDeliveryRpcRemote.test.ts +0 -100
- package/test/integration/HandshakeRpcRemote.test.ts +0 -79
- package/test/integration/Handshakes.test.ts +0 -176
- package/test/integration/Inspect.test.ts +0 -89
- package/test/integration/NeighborUpdateRpcRemote.test.ts +0 -82
- package/test/integration/NetworkNode.test.ts +0 -115
- package/test/integration/NetworkRpc.test.ts +0 -52
- package/test/integration/NetworkStack.test.ts +0 -72
- package/test/integration/NodeInfoRpc.test.ts +0 -109
- package/test/integration/Propagation.test.ts +0 -76
- package/test/integration/joining-streams-on-offline-peers.test.ts +0 -82
- package/test/integration/stream-without-default-entrypoints.test.ts +0 -128
- package/test/integration/streamEntryPointReplacing.test.ts +0 -97
- package/test/types/global.d.ts +0 -2
- package/test/unit/ContentDeliveryLayerNode.test.ts +0 -112
- package/test/unit/ContentDeliveryManager.test.ts +0 -95
- package/test/unit/ContentDeliveryRpcLocal.test.ts +0 -60
- package/test/unit/DuplicateMessageDetector.test.ts +0 -192
- package/test/unit/ExternalNetworkRpc.test.ts +0 -48
- package/test/unit/FifoMapWithTtl.test.ts +0 -253
- package/test/unit/HandshakeRpcLocal.test.ts +0 -168
- package/test/unit/Handshaker.test.ts +0 -69
- package/test/unit/InspectSession.test.ts +0 -80
- package/test/unit/Inspector.test.ts +0 -51
- package/test/unit/NeighborFinder.test.ts +0 -51
- package/test/unit/NeighborUpdateRpcLocal.test.ts +0 -139
- package/test/unit/NetworkNode.test.ts +0 -42
- package/test/unit/NodeList.test.ts +0 -164
- package/test/unit/NumberPair.test.ts +0 -22
- package/test/unit/PeerDescriptorStoreManager.test.ts +0 -103
- package/test/unit/Propagation.test.ts +0 -151
- package/test/unit/ProxyConnectionRpcRemote.test.ts +0 -39
- package/test/unit/StreamPartIDDataKey.test.ts +0 -12
- package/test/unit/StreamPartNetworkSplitAvoidance.test.ts +0 -31
- package/test/unit/StreamPartReconnect.test.ts +0 -30
- package/test/unit/TemporaryConnectionRpcLocal.test.ts +0 -38
- package/test/utils/fake/FakePeerDescriptorStoreManager.ts +0 -29
- package/test/utils/mock/MockConnectionsView.ts +0 -18
- package/test/utils/mock/MockControlLayerNode.ts +0 -78
- package/test/utils/mock/MockDiscoveryLayerNode.ts +0 -60
- package/test/utils/mock/MockHandshaker.ts +0 -17
- package/test/utils/mock/MockNeighborFinder.ts +0 -20
- package/test/utils/mock/MockNeighborUpdateManager.ts +0 -21
- package/test/utils/mock/MockTransport.ts +0 -30
- package/test/utils/utils.ts +0 -143
- package/tsconfig.browser.json +0 -12
- package/tsconfig.jest.json +0 -16
- package/tsconfig.json +0 -3
- package/tsconfig.node.json +0 -16
- /package/dist/{src/proto → generated}/google/protobuf/any.d.ts +0 -0
- /package/dist/{src/proto → generated}/google/protobuf/any.js +0 -0
- /package/dist/{src/proto → generated}/google/protobuf/empty.d.ts +0 -0
- /package/dist/{src/proto → generated}/google/protobuf/empty.js +0 -0
- /package/dist/{src/proto → generated}/google/protobuf/timestamp.d.ts +0 -0
- /package/dist/{src/proto → generated}/google/protobuf/timestamp.js +0 -0
- /package/dist/{src/proto → generated}/packages/dht/protos/DhtRpc.server.js +0 -0
- /package/dist/{src/proto → generated}/packages/proto-rpc/protos/ProtoRpc.d.ts +0 -0
- /package/dist/{src/proto → generated}/packages/proto-rpc/protos/ProtoRpc.js +0 -0
- /package/dist/{src/proto → generated}/packages/trackerless-network/protos/NetworkRpc.client.d.ts +0 -0
- /package/dist/{src/proto → generated}/packages/trackerless-network/protos/NetworkRpc.client.js +0 -0
- /package/dist/{src/proto → generated}/packages/trackerless-network/protos/NetworkRpc.server.d.ts +0 -0
- /package/dist/{src/proto → generated}/packages/trackerless-network/protos/NetworkRpc.server.js +0 -0
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Represent a pair of numbers (a,b). Ordering between two pairs is defined as
|
|
3
|
-
* follows. First compare first numbers. Compare second numbers if first are
|
|
4
|
-
* equal.
|
|
5
|
-
*/
|
|
6
|
-
export class NumberPair {
|
|
7
|
-
private readonly a
|
|
8
|
-
private readonly b
|
|
9
|
-
|
|
10
|
-
constructor(a: number, b: number) {
|
|
11
|
-
this.a = a
|
|
12
|
-
this.b = b
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
greaterThanOrEqual(otherPair: NumberPair): boolean {
|
|
16
|
-
return this.greaterThan(otherPair) || this.equalTo(otherPair)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
greaterThan(otherPair: NumberPair): boolean {
|
|
20
|
-
return this.compareTo(otherPair) === 1
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
equalTo(otherPair: NumberPair): boolean {
|
|
24
|
-
return this.compareTo(otherPair) === 0
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
private compareTo(otherPair: NumberPair): number {
|
|
28
|
-
if (this.a > otherPair.a) {
|
|
29
|
-
return 1
|
|
30
|
-
}
|
|
31
|
-
if (this.a < otherPair.a) {
|
|
32
|
-
return -1
|
|
33
|
-
}
|
|
34
|
-
if (this.b > otherPair.b) {
|
|
35
|
-
return 1
|
|
36
|
-
}
|
|
37
|
-
if (this.b < otherPair.b) {
|
|
38
|
-
return -1
|
|
39
|
-
}
|
|
40
|
-
return 0
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
toString(): string {
|
|
44
|
-
return `${this.a}|${this.b}`
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export class InvalidNumberingError extends Error {
|
|
49
|
-
constructor() {
|
|
50
|
-
super('pre-condition: previousNumber < number')
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export class GapMisMatchError extends Error {
|
|
55
|
-
constructor(state: string, previousNumber: NumberPair, number: NumberPair) {
|
|
56
|
-
super('pre-condition: gap overlap in given numbers:'
|
|
57
|
-
+ ` previousNumber=${previousNumber.toString()}, number=${number.toString()}, state=${state}`)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
*
|
|
63
|
-
* Keeps track of a stream's message numbers and reports already seen numbers
|
|
64
|
-
* as duplicates.
|
|
65
|
-
*
|
|
66
|
-
* Leverages the fact that message are assigned numbers from a strictly
|
|
67
|
-
* increasing integer sequence for lowered space complexity. For example,
|
|
68
|
-
* if we know that all messages up to number N have been seen, we can only
|
|
69
|
-
* store the number N to provide message identity check. This is because
|
|
70
|
-
* anything less than N can be deemed a duplicate.
|
|
71
|
-
*
|
|
72
|
-
* Messages arriving out-of-order makes this a bit harder since gaps form.
|
|
73
|
-
* Most of the code in this class is built to deal with this complexity.
|
|
74
|
-
* Basically, we need to keep track of which intervals [N,M] could still
|
|
75
|
-
* contain unseen messages. We should also remove intervals after we are sure
|
|
76
|
-
* that they contain no unseen messages.
|
|
77
|
-
*
|
|
78
|
-
* In addition to the above, there needs to be a limit to the number of
|
|
79
|
-
* intervals we store, as it could well be that some messages never
|
|
80
|
-
* arrive. The strategy is to start removing the lowest numbered
|
|
81
|
-
* intervals when storage limits are hit.
|
|
82
|
-
*
|
|
83
|
-
*/
|
|
84
|
-
export class DuplicateMessageDetector {
|
|
85
|
-
private readonly maxGapCount: number
|
|
86
|
-
private readonly gaps: Array<[NumberPair, NumberPair]>
|
|
87
|
-
|
|
88
|
-
constructor(maxGapCount = 10000) {
|
|
89
|
-
this.maxGapCount = maxGapCount
|
|
90
|
-
this.gaps = [] // ascending order of half-closed intervals (x,y] representing gaps that contain unseen message(s)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* returns true if number has not yet been seen (i.e. is not a duplicate)
|
|
95
|
-
*/
|
|
96
|
-
markAndCheck(previousNumber: NumberPair | null, number: NumberPair): boolean | never {
|
|
97
|
-
if (previousNumber && previousNumber.greaterThanOrEqual(number)) {
|
|
98
|
-
throw new InvalidNumberingError()
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (this.gaps.length === 0) {
|
|
102
|
-
this.gaps.push([number, new NumberPair(Infinity, Infinity)])
|
|
103
|
-
return true
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Handle special case where previousNumber is not provided. Only
|
|
107
|
-
// minimal duplicate detection is provided (comparing against latest
|
|
108
|
-
// known message number).
|
|
109
|
-
if (previousNumber === null) {
|
|
110
|
-
if (number.greaterThan(this.gaps[this.gaps.length - 1][0])) {
|
|
111
|
-
this.gaps[this.gaps.length - 1][0] = number
|
|
112
|
-
return true
|
|
113
|
-
}
|
|
114
|
-
return false
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
for (let i = this.gaps.length - 1; i >= 0; --i) {
|
|
118
|
-
const [lowerBound, upperBound] = this.gaps[i] // invariant: upperBound > lowerBound
|
|
119
|
-
|
|
120
|
-
// implies number > upperBound (would've been handled in previous iteration if gap exists)
|
|
121
|
-
if (previousNumber.greaterThanOrEqual(upperBound)) {
|
|
122
|
-
return false
|
|
123
|
-
}
|
|
124
|
-
if (previousNumber.greaterThanOrEqual(lowerBound)) {
|
|
125
|
-
if (number.greaterThan(upperBound)) {
|
|
126
|
-
throw new GapMisMatchError(this.toString(), previousNumber, number)
|
|
127
|
-
}
|
|
128
|
-
if (previousNumber.equalTo(lowerBound)) {
|
|
129
|
-
if (number.equalTo(upperBound)) {
|
|
130
|
-
this.gaps.splice(i, 1)
|
|
131
|
-
} else {
|
|
132
|
-
this.gaps[i] = [number, upperBound]
|
|
133
|
-
}
|
|
134
|
-
} else if (number.equalTo(upperBound)) {
|
|
135
|
-
this.gaps[i] = [lowerBound, previousNumber]
|
|
136
|
-
} else {
|
|
137
|
-
this.gaps.splice(i, 1, [lowerBound, previousNumber], [number, upperBound])
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// invariants after:
|
|
141
|
-
// - gaps are in ascending order
|
|
142
|
-
// - the intersection between any two gaps is empty
|
|
143
|
-
// - there are no gaps that define the empty set
|
|
144
|
-
// - last gap is [n, Infinity]
|
|
145
|
-
// - anything not covered by a gap is considered seen
|
|
146
|
-
|
|
147
|
-
this.dropLowestGapIfOverMaxGapCount()
|
|
148
|
-
return true
|
|
149
|
-
}
|
|
150
|
-
if (number.greaterThan(lowerBound)) {
|
|
151
|
-
throw new GapMisMatchError(this.toString(), previousNumber, number)
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return false
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
private dropLowestGapIfOverMaxGapCount(): void {
|
|
158
|
-
// invariant: this.gaps.length <= this.maxGapCount + 1
|
|
159
|
-
if (this.gaps.length > this.maxGapCount) {
|
|
160
|
-
this.gaps.shift()
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
toString(): string {
|
|
165
|
-
return this.gaps.map(([lower, upper]) => `(${lower.toString()}, ${upper.toString()}]`).join(', ')
|
|
166
|
-
}
|
|
167
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { IMessageType } from '@protobuf-ts/runtime'
|
|
2
|
-
import { ServerCallContext, ServiceInfo } from '@protobuf-ts/runtime-rpc'
|
|
3
|
-
import { ITransport, ListeningRpcCommunicator } from '@streamr/dht'
|
|
4
|
-
import { ClassType, ClientTransport, ProtoRpcClient, toProtoRpcClient } from '@streamr/proto-rpc'
|
|
5
|
-
|
|
6
|
-
export const SERVICE_ID = 'external-network-service'
|
|
7
|
-
|
|
8
|
-
export type ExternalRpcClient = ServiceInfo & ClassType
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/prefer-function-type, @typescript-eslint/consistent-type-definitions
|
|
10
|
-
export type ExternalRpcClientClass<T extends ExternalRpcClient> = { new (clientTransport: ClientTransport): T }
|
|
11
|
-
|
|
12
|
-
export class ExternalNetworkRpc {
|
|
13
|
-
|
|
14
|
-
private readonly rpcCommunicator: ListeningRpcCommunicator
|
|
15
|
-
|
|
16
|
-
constructor(transport: ITransport) {
|
|
17
|
-
this.rpcCommunicator = new ListeningRpcCommunicator(SERVICE_ID, transport)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
registerRpcMethod<
|
|
21
|
-
RequestClass extends IMessageType<RequestType>,
|
|
22
|
-
ResponseClass extends IMessageType<ResponseType>,
|
|
23
|
-
RequestType extends object,
|
|
24
|
-
ResponseType extends object
|
|
25
|
-
>(
|
|
26
|
-
request: RequestClass,
|
|
27
|
-
response: ResponseClass,
|
|
28
|
-
name: string,
|
|
29
|
-
fn: (req: RequestType, context: ServerCallContext) => Promise<ResponseType>
|
|
30
|
-
): void {
|
|
31
|
-
this.rpcCommunicator.registerRpcMethod(request, response, name, fn)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
createRpcClient<T extends ExternalRpcClient>(clientClass: ExternalRpcClientClass<T>): ProtoRpcClient<T> {
|
|
35
|
-
return toProtoRpcClient(new clientClass(this.rpcCommunicator.getRpcClientTransport()))
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
destroy(): void {
|
|
39
|
-
this.rpcCommunicator.destroy()
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
}
|
package/src/logic/NodeList.ts
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { DhtAddress, toNodeId } from '@streamr/dht'
|
|
2
|
-
import { sample } from 'lodash'
|
|
3
|
-
import { ContentDeliveryRpcRemote } from './ContentDeliveryRpcRemote'
|
|
4
|
-
import { EventEmitter } from 'eventemitter3'
|
|
5
|
-
|
|
6
|
-
export interface Events {
|
|
7
|
-
nodeAdded: (id: DhtAddress, remote: ContentDeliveryRpcRemote) => void
|
|
8
|
-
nodeRemoved: (id: DhtAddress, remote: ContentDeliveryRpcRemote) => void
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const getValuesOfIncludedKeys = (
|
|
12
|
-
nodes: Map<DhtAddress, ContentDeliveryRpcRemote>,
|
|
13
|
-
exclude: DhtAddress[],
|
|
14
|
-
wsOnly = false
|
|
15
|
-
): ContentDeliveryRpcRemote[] => {
|
|
16
|
-
const values = wsOnly
|
|
17
|
-
? Array.from(nodes.entries()).filter(([_, node]) => node.getPeerDescriptor().websocket !== undefined)
|
|
18
|
-
: Array.from(nodes.entries())
|
|
19
|
-
return values
|
|
20
|
-
.filter(([id]) => !exclude.includes(id))
|
|
21
|
-
.map(([_id, node]) => node)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// The items in the list are in the insertion order
|
|
25
|
-
|
|
26
|
-
export class NodeList extends EventEmitter<Events> {
|
|
27
|
-
private readonly nodes: Map<DhtAddress, ContentDeliveryRpcRemote>
|
|
28
|
-
private readonly limit: number
|
|
29
|
-
private ownId: DhtAddress
|
|
30
|
-
|
|
31
|
-
constructor(ownId: DhtAddress, limit: number) {
|
|
32
|
-
super()
|
|
33
|
-
this.nodes = new Map()
|
|
34
|
-
this.limit = limit
|
|
35
|
-
this.ownId = ownId
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
add(remote: ContentDeliveryRpcRemote): void {
|
|
39
|
-
const nodeId = toNodeId(remote.getPeerDescriptor())
|
|
40
|
-
if ((this.ownId !== nodeId) && (this.nodes.size < this.limit)) {
|
|
41
|
-
const isExistingNode = this.nodes.has(nodeId)
|
|
42
|
-
this.nodes.set(nodeId, remote)
|
|
43
|
-
|
|
44
|
-
if (!isExistingNode) {
|
|
45
|
-
this.emit('nodeAdded', nodeId, remote)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
remove(nodeId: DhtAddress): void {
|
|
51
|
-
if (this.nodes.has(nodeId)) {
|
|
52
|
-
const remote = this.nodes.get(nodeId)!
|
|
53
|
-
this.nodes.delete(nodeId)
|
|
54
|
-
this.emit('nodeRemoved', nodeId, remote)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
has(nodeId: DhtAddress): boolean {
|
|
59
|
-
return this.nodes.has(nodeId)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Replace nodes does not emit nodeRemoved events, use with caution
|
|
63
|
-
replaceAll(neighbors: ContentDeliveryRpcRemote[]): void {
|
|
64
|
-
this.nodes.clear()
|
|
65
|
-
const limited = neighbors.splice(0, this.limit)
|
|
66
|
-
limited.forEach((remote) => {
|
|
67
|
-
this.add(remote)
|
|
68
|
-
})
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
getIds(): DhtAddress[] {
|
|
72
|
-
return Array.from(this.nodes.keys())
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
get(id: DhtAddress): ContentDeliveryRpcRemote | undefined {
|
|
76
|
-
return this.nodes.get(id)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
size(exclude: DhtAddress[] = []): number {
|
|
80
|
-
return Array.from(this.nodes.keys()).filter((node) => !exclude.includes(node)).length
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
getRandom(exclude: DhtAddress[]): ContentDeliveryRpcRemote | undefined {
|
|
84
|
-
return sample(getValuesOfIncludedKeys(this.nodes, exclude))
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
getFirst(exclude: DhtAddress[], wsOnly = false): ContentDeliveryRpcRemote | undefined {
|
|
88
|
-
const included = getValuesOfIncludedKeys(this.nodes, exclude, wsOnly)
|
|
89
|
-
return included[0]
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
getFirstAndLast(exclude: DhtAddress[]): ContentDeliveryRpcRemote[] {
|
|
93
|
-
const included = getValuesOfIncludedKeys(this.nodes, exclude)
|
|
94
|
-
if (included.length === 0) {
|
|
95
|
-
return []
|
|
96
|
-
}
|
|
97
|
-
return included.length > 1 ? [this.getFirst(exclude)!, this.getLast(exclude)!] : [this.getFirst(exclude)!]
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
getLast(exclude: DhtAddress[]): ContentDeliveryRpcRemote | undefined {
|
|
101
|
-
const included = getValuesOfIncludedKeys(this.nodes, exclude)
|
|
102
|
-
return included[included.length - 1]
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
getAll(): ContentDeliveryRpcRemote[] {
|
|
106
|
-
return Array.from(this.nodes.values())
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
stop(): void {
|
|
110
|
-
this.nodes.forEach((node) => this.remove(toNodeId(node.getPeerDescriptor())))
|
|
111
|
-
this.removeAllListeners()
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DataEntry,
|
|
3
|
-
DhtAddress,
|
|
4
|
-
PeerDescriptor,
|
|
5
|
-
areEqualPeerDescriptors
|
|
6
|
-
} from '@streamr/dht'
|
|
7
|
-
import { Logger, scheduleAtInterval } from '@streamr/utils'
|
|
8
|
-
import { Any } from '../proto/google/protobuf/any'
|
|
9
|
-
|
|
10
|
-
const parsePeerDescriptor = (dataEntries: DataEntry[]): PeerDescriptor[] => {
|
|
11
|
-
return dataEntries.filter((entry) => !entry.deleted).map((entry) => Any.unpack(entry.data!, PeerDescriptor))
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const logger = new Logger(module)
|
|
15
|
-
|
|
16
|
-
export const MAX_NODE_COUNT = 8
|
|
17
|
-
|
|
18
|
-
interface PeerDescriptorStoreManagerOptions {
|
|
19
|
-
key: DhtAddress
|
|
20
|
-
localPeerDescriptor: PeerDescriptor
|
|
21
|
-
storeInterval?: number
|
|
22
|
-
fetchDataFromDht: (key: DhtAddress) => Promise<DataEntry[]>
|
|
23
|
-
storeDataToDht: (key: DhtAddress, data: Any) => Promise<PeerDescriptor[]>
|
|
24
|
-
deleteDataFromDht: (key: DhtAddress, waitForCompletion: boolean) => Promise<void>
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* For each key there is usually 0-MAX_NODE_COUNT PeerDescriptors stored in the DHT. If there are fewer node,
|
|
29
|
-
* the peer descriptor of the local node is stored to the DHT.
|
|
30
|
-
*/
|
|
31
|
-
export class PeerDescriptorStoreManager {
|
|
32
|
-
|
|
33
|
-
private readonly abortController: AbortController
|
|
34
|
-
private readonly options: PeerDescriptorStoreManagerOptions
|
|
35
|
-
private isLocalNodeStored_ = false
|
|
36
|
-
|
|
37
|
-
constructor(options: PeerDescriptorStoreManagerOptions) {
|
|
38
|
-
this.options = options
|
|
39
|
-
this.abortController = new AbortController()
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async fetchNodes(): Promise<PeerDescriptor[]> {
|
|
43
|
-
logger.trace('Fetch data', { key: this.options.key })
|
|
44
|
-
try {
|
|
45
|
-
const result = await this.options.fetchDataFromDht(this.options.key)
|
|
46
|
-
return parsePeerDescriptor(result)
|
|
47
|
-
} catch {
|
|
48
|
-
return []
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async storeAndKeepLocalNode(): Promise<void> {
|
|
53
|
-
if (this.abortController.signal.aborted) {
|
|
54
|
-
return
|
|
55
|
-
}
|
|
56
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
57
|
-
this.isLocalNodeStored_ = true
|
|
58
|
-
await this.storeLocalNode()
|
|
59
|
-
await this.keepLocalNode()
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
private async storeLocalNode(): Promise<void> {
|
|
63
|
-
const localPeerDescriptor = this.options.localPeerDescriptor
|
|
64
|
-
const dataToStore = Any.pack(localPeerDescriptor, PeerDescriptor)
|
|
65
|
-
try {
|
|
66
|
-
await this.options.storeDataToDht(this.options.key, dataToStore)
|
|
67
|
-
} catch {
|
|
68
|
-
logger.warn('Failed to store local node', { key: this.options.key })
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
private async keepLocalNode(): Promise<void> {
|
|
73
|
-
await scheduleAtInterval(async () => {
|
|
74
|
-
logger.trace('Attempting to keep local node', { key: this.options.key })
|
|
75
|
-
try {
|
|
76
|
-
const discovered = await this.fetchNodes()
|
|
77
|
-
if (discovered.length < MAX_NODE_COUNT
|
|
78
|
-
|| discovered.some((peerDescriptor) => areEqualPeerDescriptors(peerDescriptor, this.options.localPeerDescriptor))) {
|
|
79
|
-
await this.storeLocalNode()
|
|
80
|
-
}
|
|
81
|
-
} catch {
|
|
82
|
-
logger.debug('Failed to keep local node', { key: this.options.key })
|
|
83
|
-
}
|
|
84
|
-
}, this.options.storeInterval ?? 60000, false, this.abortController.signal)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
public isLocalNodeStored(): boolean {
|
|
88
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
89
|
-
return this.isLocalNodeStored_
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async destroy(): Promise<void> {
|
|
93
|
-
this.abortController.abort()
|
|
94
|
-
await this.options.deleteDataFromDht(this.options.key, false)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { areEqualPeerDescriptors, DhtAddress, toNodeId, PeerDescriptor } from '@streamr/dht'
|
|
2
|
-
import { Logger, wait } from '@streamr/utils'
|
|
3
|
-
import { DiscoveryLayerNode } from './DiscoveryLayerNode'
|
|
4
|
-
|
|
5
|
-
/*
|
|
6
|
-
* Tries to find new neighbors if we currently have less than MIN_NEIGHBOR_COUNT neigbors. It does so by
|
|
7
|
-
* rejoining the stream's control layer network.
|
|
8
|
-
*
|
|
9
|
-
* This way we can avoid some network split scenarios. The functionality is most relevant for small stream
|
|
10
|
-
* networks.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const logger = new Logger(module)
|
|
14
|
-
|
|
15
|
-
const exponentialRunOff = async (
|
|
16
|
-
task: () => Promise<void>,
|
|
17
|
-
description: string,
|
|
18
|
-
abortSignal: AbortSignal,
|
|
19
|
-
baseDelay = 500,
|
|
20
|
-
maxAttempts = 6
|
|
21
|
-
): Promise<void> => {
|
|
22
|
-
for (let i = 1; i <= maxAttempts; i++) {
|
|
23
|
-
if (abortSignal.aborted) {
|
|
24
|
-
return
|
|
25
|
-
}
|
|
26
|
-
const factor = 2 ** i
|
|
27
|
-
const delay = baseDelay * factor
|
|
28
|
-
try {
|
|
29
|
-
await task()
|
|
30
|
-
} catch {
|
|
31
|
-
logger.trace(`${description} failed, retrying in ${delay} ms`)
|
|
32
|
-
}
|
|
33
|
-
try { // Abort controller throws unexpected errors in destroy?
|
|
34
|
-
await wait(delay, abortSignal)
|
|
35
|
-
} catch (err) {
|
|
36
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
37
|
-
logger.trace(`${err}`) // TODO Do we need logging?
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const MIN_NEIGHBOR_COUNT = 4
|
|
43
|
-
|
|
44
|
-
export interface StreamPartNetworkSplitAvoidanceOptions {
|
|
45
|
-
discoveryLayerNode: DiscoveryLayerNode
|
|
46
|
-
discoverEntryPoints: (excludedNodes?: Set<DhtAddress>) => Promise<PeerDescriptor[]>
|
|
47
|
-
exponentialRunOfBaseDelay?: number
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export class StreamPartNetworkSplitAvoidance {
|
|
51
|
-
|
|
52
|
-
private readonly abortController: AbortController
|
|
53
|
-
private readonly options: StreamPartNetworkSplitAvoidanceOptions
|
|
54
|
-
private readonly excludedNodes: Set<DhtAddress> = new Set()
|
|
55
|
-
private running = false
|
|
56
|
-
|
|
57
|
-
constructor(options: StreamPartNetworkSplitAvoidanceOptions) {
|
|
58
|
-
this.options = options
|
|
59
|
-
this.abortController = new AbortController()
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
public async avoidNetworkSplit(): Promise<void> {
|
|
63
|
-
this.running = true
|
|
64
|
-
await exponentialRunOff(async () => {
|
|
65
|
-
const discoveredEntrypoints = await this.options.discoverEntryPoints()
|
|
66
|
-
const filteredEntryPoints = discoveredEntrypoints.filter((peer) => !this.excludedNodes.has(toNodeId(peer)))
|
|
67
|
-
await this.options.discoveryLayerNode.joinDht(filteredEntryPoints, false, false)
|
|
68
|
-
if (this.options.discoveryLayerNode.getNeighborCount() < MIN_NEIGHBOR_COUNT) {
|
|
69
|
-
// Filter out nodes that are not neighbors as those nodes are assumed to be offline
|
|
70
|
-
const newExcludes = filteredEntryPoints
|
|
71
|
-
.filter((peer) => !this.options.discoveryLayerNode.getNeighbors()
|
|
72
|
-
.some((neighbor) => areEqualPeerDescriptors(neighbor, peer)))
|
|
73
|
-
.map((peer) => toNodeId(peer))
|
|
74
|
-
newExcludes.forEach((node) => this.excludedNodes.add(node))
|
|
75
|
-
throw new Error(`Network split is still possible`)
|
|
76
|
-
}
|
|
77
|
-
}, 'avoid network split', this.abortController.signal, this.options.exponentialRunOfBaseDelay)
|
|
78
|
-
this.running = false
|
|
79
|
-
this.excludedNodes.clear()
|
|
80
|
-
logger.trace(`Network split avoided`)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
public isRunning(): boolean {
|
|
84
|
-
return this.running
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
destroy(): void {
|
|
88
|
-
this.abortController.abort()
|
|
89
|
-
}
|
|
90
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { scheduleAtInterval } from '@streamr/utils'
|
|
2
|
-
import { MAX_NODE_COUNT, PeerDescriptorStoreManager } from './PeerDescriptorStoreManager'
|
|
3
|
-
import { DiscoveryLayerNode } from './DiscoveryLayerNode'
|
|
4
|
-
|
|
5
|
-
const DEFAULT_RECONNECT_INTERVAL = 30 * 1000
|
|
6
|
-
export class StreamPartReconnect {
|
|
7
|
-
private abortController?: AbortController
|
|
8
|
-
private readonly discoveryLayerNode: DiscoveryLayerNode
|
|
9
|
-
private readonly peerDescriptorStoreManager: PeerDescriptorStoreManager
|
|
10
|
-
|
|
11
|
-
constructor(discoveryLayerNode: DiscoveryLayerNode, peerDescriptorStoreManager: PeerDescriptorStoreManager) {
|
|
12
|
-
this.discoveryLayerNode = discoveryLayerNode
|
|
13
|
-
this.peerDescriptorStoreManager = peerDescriptorStoreManager
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async reconnect(timeout = DEFAULT_RECONNECT_INTERVAL): Promise<void> {
|
|
17
|
-
this.abortController = new AbortController()
|
|
18
|
-
await scheduleAtInterval(async () => {
|
|
19
|
-
const entryPoints = await this.peerDescriptorStoreManager.fetchNodes()
|
|
20
|
-
await this.discoveryLayerNode.joinDht(entryPoints)
|
|
21
|
-
// Is is necessary to store the node as an entry point here?
|
|
22
|
-
if (!this.peerDescriptorStoreManager.isLocalNodeStored() && entryPoints.length < MAX_NODE_COUNT) {
|
|
23
|
-
await this.peerDescriptorStoreManager.storeAndKeepLocalNode()
|
|
24
|
-
}
|
|
25
|
-
if (this.discoveryLayerNode.getNeighborCount() > 0) {
|
|
26
|
-
this.abortController!.abort()
|
|
27
|
-
}
|
|
28
|
-
}, timeout, true, this.abortController.signal)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
isRunning(): boolean {
|
|
32
|
-
return this.abortController ? !this.abortController.signal.aborted : false
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
destroy(): void {
|
|
36
|
-
this.abortController?.abort()
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { DhtAddress, ListeningRpcCommunicator, toNodeId } from '@streamr/dht'
|
|
2
|
-
import { Handshaker } from './neighbor-discovery/Handshaker'
|
|
3
|
-
import { NeighborFinder } from './neighbor-discovery/NeighborFinder'
|
|
4
|
-
import { NeighborUpdateManager } from './neighbor-discovery/NeighborUpdateManager'
|
|
5
|
-
import { StrictContentDeliveryLayerNodeOptions, ContentDeliveryLayerNode } from './ContentDeliveryLayerNode'
|
|
6
|
-
import { NodeList } from './NodeList'
|
|
7
|
-
import { Propagation } from './propagation/Propagation'
|
|
8
|
-
import { StreamMessage } from '../proto/packages/trackerless-network/protos/NetworkRpc'
|
|
9
|
-
import type { MarkOptional } from 'ts-essentials'
|
|
10
|
-
import { ProxyConnectionRpcLocal } from './proxy/ProxyConnectionRpcLocal'
|
|
11
|
-
import { Inspector } from './inspect/Inspector'
|
|
12
|
-
import { TemporaryConnectionRpcLocal } from './temporary-connection/TemporaryConnectionRpcLocal'
|
|
13
|
-
import { formStreamPartContentDeliveryServiceId } from './formStreamPartDeliveryServiceId'
|
|
14
|
-
|
|
15
|
-
type ContentDeliveryLayerNodeOptions = MarkOptional<StrictContentDeliveryLayerNodeOptions,
|
|
16
|
-
'nearbyNodeView' | 'randomNodeView' | 'neighbors' | 'leftNodeView' | 'rightNodeView' | 'propagation'
|
|
17
|
-
| 'handshaker' | 'neighborFinder' | 'neighborUpdateManager' | 'neighborTargetCount'
|
|
18
|
-
| 'rpcCommunicator' | 'nodeViewSize'
|
|
19
|
-
| 'inspector' | 'temporaryConnectionRpcLocal'> & {
|
|
20
|
-
maxContactCount?: number
|
|
21
|
-
minPropagationTargets?: number
|
|
22
|
-
acceptProxyConnections?: boolean
|
|
23
|
-
neighborUpdateInterval?: number
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const createConfigWithDefaults = (options: ContentDeliveryLayerNodeOptions): StrictContentDeliveryLayerNodeOptions => {
|
|
27
|
-
const ownNodeId = toNodeId(options.localPeerDescriptor)
|
|
28
|
-
const rpcCommunicator = options.rpcCommunicator ?? new ListeningRpcCommunicator(
|
|
29
|
-
formStreamPartContentDeliveryServiceId(options.streamPartId),
|
|
30
|
-
options.transport
|
|
31
|
-
)
|
|
32
|
-
const neighborTargetCount = options.neighborTargetCount ?? 4
|
|
33
|
-
const maxContactCount = options.maxContactCount ?? 20
|
|
34
|
-
const minPropagationTargets = options.minPropagationTargets ?? 2
|
|
35
|
-
const acceptProxyConnections = options.acceptProxyConnections ?? false
|
|
36
|
-
const neighborUpdateInterval = options.neighborUpdateInterval ?? 10000
|
|
37
|
-
const neighbors = options.neighbors ?? new NodeList(ownNodeId, maxContactCount)
|
|
38
|
-
const leftNodeView = options.leftNodeView ?? new NodeList(ownNodeId, maxContactCount)
|
|
39
|
-
const rightNodeView = options.rightNodeView ?? new NodeList(ownNodeId, maxContactCount)
|
|
40
|
-
const nearbyNodeView = options.nearbyNodeView ?? new NodeList(ownNodeId, maxContactCount)
|
|
41
|
-
const randomNodeView = options.randomNodeView ?? new NodeList(ownNodeId, maxContactCount)
|
|
42
|
-
const ongoingHandshakes = new Set<DhtAddress>()
|
|
43
|
-
|
|
44
|
-
const temporaryConnectionRpcLocal = new TemporaryConnectionRpcLocal({
|
|
45
|
-
rpcCommunicator,
|
|
46
|
-
localPeerDescriptor: options.localPeerDescriptor,
|
|
47
|
-
streamPartId: options.streamPartId,
|
|
48
|
-
connectionLocker: options.connectionLocker
|
|
49
|
-
})
|
|
50
|
-
const proxyConnectionRpcLocal = acceptProxyConnections ? new ProxyConnectionRpcLocal({
|
|
51
|
-
localPeerDescriptor: options.localPeerDescriptor,
|
|
52
|
-
streamPartId: options.streamPartId,
|
|
53
|
-
rpcCommunicator
|
|
54
|
-
}) : undefined
|
|
55
|
-
const propagation = options.propagation ?? new Propagation({
|
|
56
|
-
minPropagationTargets,
|
|
57
|
-
sendToNeighbor: async (neighborId: DhtAddress, msg: StreamMessage): Promise<void> => {
|
|
58
|
-
const remote = neighbors.get(neighborId) ?? temporaryConnectionRpcLocal.getNodes().get(neighborId)
|
|
59
|
-
const proxyConnection = proxyConnectionRpcLocal?.getConnection(neighborId)
|
|
60
|
-
if (remote) {
|
|
61
|
-
await remote.sendStreamMessage(msg)
|
|
62
|
-
} else if (proxyConnection) {
|
|
63
|
-
await proxyConnection.remote.sendStreamMessage(msg)
|
|
64
|
-
} else {
|
|
65
|
-
throw new Error('Propagation target not found')
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
})
|
|
69
|
-
const handshaker = options.handshaker ?? new Handshaker({
|
|
70
|
-
localPeerDescriptor: options.localPeerDescriptor,
|
|
71
|
-
streamPartId: options.streamPartId,
|
|
72
|
-
rpcCommunicator,
|
|
73
|
-
neighbors,
|
|
74
|
-
leftNodeView,
|
|
75
|
-
rightNodeView,
|
|
76
|
-
nearbyNodeView,
|
|
77
|
-
randomNodeView,
|
|
78
|
-
maxNeighborCount: neighborTargetCount,
|
|
79
|
-
rpcRequestTimeout: options.rpcRequestTimeout,
|
|
80
|
-
ongoingHandshakes
|
|
81
|
-
})
|
|
82
|
-
const neighborFinder = options.neighborFinder ?? new NeighborFinder({
|
|
83
|
-
neighbors,
|
|
84
|
-
leftNodeView,
|
|
85
|
-
rightNodeView,
|
|
86
|
-
nearbyNodeView,
|
|
87
|
-
randomNodeView,
|
|
88
|
-
doFindNeighbors: (excludedIds) => handshaker.attemptHandshakesOnContacts(excludedIds),
|
|
89
|
-
minCount: neighborTargetCount
|
|
90
|
-
})
|
|
91
|
-
const neighborUpdateManager = options.neighborUpdateManager ?? new NeighborUpdateManager({
|
|
92
|
-
neighbors,
|
|
93
|
-
nearbyNodeView,
|
|
94
|
-
localPeerDescriptor: options.localPeerDescriptor,
|
|
95
|
-
neighborFinder,
|
|
96
|
-
streamPartId: options.streamPartId,
|
|
97
|
-
rpcCommunicator,
|
|
98
|
-
neighborUpdateInterval,
|
|
99
|
-
neighborTargetCount,
|
|
100
|
-
ongoingHandshakes
|
|
101
|
-
})
|
|
102
|
-
const inspector = options.inspector ?? new Inspector({
|
|
103
|
-
localPeerDescriptor: options.localPeerDescriptor,
|
|
104
|
-
rpcCommunicator,
|
|
105
|
-
streamPartId: options.streamPartId,
|
|
106
|
-
connectionLocker: options.connectionLocker
|
|
107
|
-
})
|
|
108
|
-
return {
|
|
109
|
-
...options,
|
|
110
|
-
neighbors,
|
|
111
|
-
leftNodeView,
|
|
112
|
-
rightNodeView,
|
|
113
|
-
nearbyNodeView,
|
|
114
|
-
randomNodeView,
|
|
115
|
-
rpcCommunicator,
|
|
116
|
-
handshaker,
|
|
117
|
-
neighborFinder,
|
|
118
|
-
neighborUpdateManager,
|
|
119
|
-
propagation,
|
|
120
|
-
neighborTargetCount,
|
|
121
|
-
nodeViewSize: maxContactCount,
|
|
122
|
-
proxyConnectionRpcLocal,
|
|
123
|
-
inspector,
|
|
124
|
-
temporaryConnectionRpcLocal
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export const createContentDeliveryLayerNode = (options: ContentDeliveryLayerNodeOptions): ContentDeliveryLayerNode => {
|
|
129
|
-
return new ContentDeliveryLayerNode(createConfigWithDefaults(options))
|
|
130
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { ServiceID } from '@streamr/dht'
|
|
2
|
-
import { StreamPartID } from '@streamr/utils'
|
|
3
|
-
|
|
4
|
-
export const formStreamPartContentDeliveryServiceId = (streamPartId: StreamPartID): ServiceID => {
|
|
5
|
-
// could be "content-delivery" instead of "delivery", but that is a breaking change
|
|
6
|
-
return `stream-part-delivery-${streamPartId}`
|
|
7
|
-
}
|