@streamr/trackerless-network 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/package.json +5 -5
- package/package.json +5 -5
- package/src/NetworkNode.ts +0 -142
- package/src/NetworkStack.ts +0 -197
- package/src/exports.ts +0 -18
- package/src/logic/ContentDeliveryLayerNode.ts +0 -424
- package/src/logic/ContentDeliveryManager.ts +0 -401
- 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 -55
- 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 -286
- 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/types.ts +0 -13
- package/test/benchmark/StreamPartIdDataKeyDistribution.test.ts +0 -60
- package/test/benchmark/first-message.ts +0 -171
- package/test/end-to-end/content-delivery-layer-node-with-real-connections.test.ts +0 -165
- 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 -226
- package/test/end-to-end/proxy-key-exchange.test.ts +0 -126
- package/test/end-to-end/webrtc-full-node-network.test.ts +0 -83
- package/test/end-to-end/websocket-full-node-network.test.ts +0 -82
- 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 -160
- package/test/integration/ContentDeliveryRpcRemote.test.ts +0 -100
- package/test/integration/HandshakeRpcRemote.test.ts +0 -79
- package/test/integration/Handshakes.test.ts +0 -141
- 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 -1
- package/test/unit/ContentDeliveryLayerNode.test.ts +0 -112
- package/test/unit/ContentDeliveryManager.test.ts +0 -96
- 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 -155
- package/test/unit/Handshaker.test.ts +0 -69
- package/test/unit/InspectSession.test.ts +0 -83
- 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 -144
- package/tsconfig.browser.json +0 -13
- package/tsconfig.jest.json +0 -17
- package/tsconfig.json +0 -3
- package/tsconfig.node.json +0 -17
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ConnectionLocker,
|
|
3
|
-
DhtAddress,
|
|
4
|
-
DhtNode,
|
|
5
|
-
EXISTING_CONNECTION_TIMEOUT,
|
|
6
|
-
ITransport,
|
|
7
|
-
PeerDescriptor,
|
|
8
|
-
toDhtAddress,
|
|
9
|
-
toNodeId
|
|
10
|
-
} from '@streamr/dht'
|
|
11
|
-
import {
|
|
12
|
-
Logger,
|
|
13
|
-
Metric,
|
|
14
|
-
MetricsContext,
|
|
15
|
-
MetricsDefinition,
|
|
16
|
-
RateMetric, StreamID, StreamPartID, StreamPartIDUtils,
|
|
17
|
-
UserID,
|
|
18
|
-
toStreamPartID
|
|
19
|
-
} from '@streamr/utils'
|
|
20
|
-
import { createHash } from 'crypto'
|
|
21
|
-
import { EventEmitter } from 'eventemitter3'
|
|
22
|
-
import { sampleSize } from 'lodash'
|
|
23
|
-
import { ProxyDirection, StreamMessage } from '../../generated/packages/trackerless-network/protos/NetworkRpc'
|
|
24
|
-
import { ContentDeliveryLayerNode } from './ContentDeliveryLayerNode'
|
|
25
|
-
import { ControlLayerNode } from './ControlLayerNode'
|
|
26
|
-
import { DiscoveryLayerNode } from './DiscoveryLayerNode'
|
|
27
|
-
import { MAX_NODE_COUNT, PeerDescriptorStoreManager } from './PeerDescriptorStoreManager'
|
|
28
|
-
import { MIN_NEIGHBOR_COUNT as NETWORK_SPLIT_AVOIDANCE_MIN_NEIGHBOR_COUNT, StreamPartNetworkSplitAvoidance } from './StreamPartNetworkSplitAvoidance'
|
|
29
|
-
import { StreamPartReconnect } from './StreamPartReconnect'
|
|
30
|
-
import { createContentDeliveryLayerNode } from './createContentDeliveryLayerNode'
|
|
31
|
-
import { ProxyClient } from './proxy/ProxyClient'
|
|
32
|
-
import { ConnectionManager } from '@streamr/dht/src/exports'
|
|
33
|
-
import { StreamPartitionInfo } from '../types'
|
|
34
|
-
|
|
35
|
-
export type StreamPartDelivery = {
|
|
36
|
-
broadcast: (msg: StreamMessage) => void
|
|
37
|
-
stop: () => Promise<void>
|
|
38
|
-
} & ({
|
|
39
|
-
proxied: false
|
|
40
|
-
discoveryLayerNode: DiscoveryLayerNode
|
|
41
|
-
node: ContentDeliveryLayerNode
|
|
42
|
-
networkSplitAvoidance: StreamPartNetworkSplitAvoidance
|
|
43
|
-
getDiagnosticInfo: () => Record<string, unknown>
|
|
44
|
-
} | {
|
|
45
|
-
proxied: true
|
|
46
|
-
client: ProxyClient
|
|
47
|
-
getDiagnosticInfo: () => Record<string, unknown>
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
export interface Events {
|
|
51
|
-
newMessage: (msg: StreamMessage) => void
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const logger = new Logger(module)
|
|
55
|
-
|
|
56
|
-
interface Metrics extends MetricsDefinition {
|
|
57
|
-
broadcastMessagesPerSecond: Metric
|
|
58
|
-
broadcastBytesPerSecond: Metric
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface ContentDeliveryManagerOptions {
|
|
62
|
-
metricsContext?: MetricsContext
|
|
63
|
-
streamPartitionNeighborTargetCount?: number
|
|
64
|
-
streamPartitionMinPropagationTargets?: number
|
|
65
|
-
acceptProxyConnections?: boolean
|
|
66
|
-
rpcRequestTimeout?: number
|
|
67
|
-
neighborUpdateInterval?: number
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export const streamPartIdToDataKey = (streamPartId: StreamPartID): DhtAddress => {
|
|
71
|
-
return toDhtAddress(new Uint8Array((createHash('sha1').update(streamPartId).digest())))
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export class ContentDeliveryManager extends EventEmitter<Events> {
|
|
75
|
-
|
|
76
|
-
private transport?: ITransport
|
|
77
|
-
private connectionLocker?: ConnectionLocker
|
|
78
|
-
private controlLayerNode?: ControlLayerNode
|
|
79
|
-
private readonly metricsContext: MetricsContext
|
|
80
|
-
private readonly metrics: Metrics
|
|
81
|
-
private readonly options: ContentDeliveryManagerOptions
|
|
82
|
-
private readonly streamParts: Map<StreamPartID, StreamPartDelivery>
|
|
83
|
-
private readonly knownStreamPartEntryPoints: Map<StreamPartID, PeerDescriptor[]> = new Map()
|
|
84
|
-
private started = false
|
|
85
|
-
private destroyed = false
|
|
86
|
-
|
|
87
|
-
constructor(options: ContentDeliveryManagerOptions) {
|
|
88
|
-
super()
|
|
89
|
-
this.options = options
|
|
90
|
-
this.streamParts = new Map()
|
|
91
|
-
this.metricsContext = options.metricsContext ?? new MetricsContext()
|
|
92
|
-
this.metrics = {
|
|
93
|
-
broadcastMessagesPerSecond: new RateMetric(),
|
|
94
|
-
broadcastBytesPerSecond: new RateMetric()
|
|
95
|
-
}
|
|
96
|
-
this.metricsContext.addMetrics('node', this.metrics)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async start(startedAndJoinedControlLayerNode: ControlLayerNode, transport: ITransport, connectionLocker: ConnectionLocker): Promise<void> {
|
|
100
|
-
if (this.started || this.destroyed) {
|
|
101
|
-
return
|
|
102
|
-
}
|
|
103
|
-
this.started = true
|
|
104
|
-
this.controlLayerNode = startedAndJoinedControlLayerNode
|
|
105
|
-
this.transport = transport
|
|
106
|
-
this.connectionLocker = connectionLocker
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async destroy(): Promise<void> {
|
|
110
|
-
if (!this.started || this.destroyed) {
|
|
111
|
-
return
|
|
112
|
-
}
|
|
113
|
-
logger.trace('Destroying ContentDeliveryManager')
|
|
114
|
-
this.destroyed = true
|
|
115
|
-
await Promise.all(Array.from(this.streamParts.values()).map((streamPart) => streamPart.stop()))
|
|
116
|
-
this.streamParts.clear()
|
|
117
|
-
this.removeAllListeners()
|
|
118
|
-
this.controlLayerNode = undefined
|
|
119
|
-
this.transport = undefined
|
|
120
|
-
this.connectionLocker = undefined
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
broadcast(msg: StreamMessage): void {
|
|
124
|
-
const streamPartId = toStreamPartID(msg.messageId!.streamId as StreamID, msg.messageId!.streamPartition)
|
|
125
|
-
logger.debug(`Broadcasting to stream part ${streamPartId}`)
|
|
126
|
-
this.joinStreamPart(streamPartId)
|
|
127
|
-
this.streamParts.get(streamPartId)!.broadcast(msg)
|
|
128
|
-
if (msg.body.oneofKind === 'contentMessage') {
|
|
129
|
-
this.metrics.broadcastMessagesPerSecond.record(1)
|
|
130
|
-
this.metrics.broadcastBytesPerSecond.record(msg.body.contentMessage.content.length)
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
async leaveStreamPart(streamPartId: StreamPartID): Promise<void> {
|
|
135
|
-
const streamPart = this.streamParts.get(streamPartId)
|
|
136
|
-
if (streamPart) {
|
|
137
|
-
await streamPart.stop()
|
|
138
|
-
this.streamParts.delete(streamPartId)
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
joinStreamPart(streamPartId: StreamPartID): void {
|
|
143
|
-
let streamPart = this.streamParts.get(streamPartId)
|
|
144
|
-
if (streamPart !== undefined) {
|
|
145
|
-
return
|
|
146
|
-
}
|
|
147
|
-
logger.debug(`Join stream part ${streamPartId}`)
|
|
148
|
-
const discoveryLayerNode = this.createDiscoveryLayerNode(streamPartId, this.knownStreamPartEntryPoints.get(streamPartId) ?? [])
|
|
149
|
-
const peerDescriptorStoreManager = new PeerDescriptorStoreManager({
|
|
150
|
-
key: streamPartIdToDataKey(streamPartId),
|
|
151
|
-
localPeerDescriptor: this.getPeerDescriptor(),
|
|
152
|
-
fetchDataFromDht: (key) => this.controlLayerNode!.fetchDataFromDht(key),
|
|
153
|
-
storeDataToDht: (key, data) => this.controlLayerNode!.storeDataToDht(key, data),
|
|
154
|
-
deleteDataFromDht: async (key, waitForCompletion) => this.controlLayerNode!.deleteDataFromDht(key, waitForCompletion)
|
|
155
|
-
})
|
|
156
|
-
const networkSplitAvoidance = new StreamPartNetworkSplitAvoidance({
|
|
157
|
-
discoveryLayerNode,
|
|
158
|
-
discoverEntryPoints: async () => peerDescriptorStoreManager.fetchNodes()
|
|
159
|
-
})
|
|
160
|
-
const node = this.createContentDeliveryLayerNode(
|
|
161
|
-
streamPartId,
|
|
162
|
-
discoveryLayerNode,
|
|
163
|
-
() => peerDescriptorStoreManager.isLocalNodeStored()
|
|
164
|
-
)
|
|
165
|
-
const streamPartReconnect = new StreamPartReconnect(discoveryLayerNode, peerDescriptorStoreManager)
|
|
166
|
-
streamPart = {
|
|
167
|
-
proxied: false,
|
|
168
|
-
discoveryLayerNode,
|
|
169
|
-
node,
|
|
170
|
-
networkSplitAvoidance,
|
|
171
|
-
broadcast: (msg: StreamMessage) => node.broadcast(msg),
|
|
172
|
-
stop: async () => {
|
|
173
|
-
streamPartReconnect.destroy()
|
|
174
|
-
networkSplitAvoidance.destroy()
|
|
175
|
-
await peerDescriptorStoreManager.destroy()
|
|
176
|
-
node.stop()
|
|
177
|
-
await discoveryLayerNode.stop()
|
|
178
|
-
},
|
|
179
|
-
getDiagnosticInfo: () => node.getDiagnosticInfo()
|
|
180
|
-
}
|
|
181
|
-
this.streamParts.set(streamPartId, streamPart)
|
|
182
|
-
node.on('message', (message: StreamMessage) => {
|
|
183
|
-
this.emit('newMessage', message)
|
|
184
|
-
})
|
|
185
|
-
const handleEntryPointLeave = async () => {
|
|
186
|
-
if (this.destroyed || peerDescriptorStoreManager.isLocalNodeStored() || this.knownStreamPartEntryPoints.has(streamPartId)) {
|
|
187
|
-
return
|
|
188
|
-
}
|
|
189
|
-
const entryPoints = await peerDescriptorStoreManager.fetchNodes()
|
|
190
|
-
if (entryPoints.length < MAX_NODE_COUNT) {
|
|
191
|
-
await peerDescriptorStoreManager.storeAndKeepLocalNode()
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
discoveryLayerNode.on('manualRejoinRequired', async () => {
|
|
195
|
-
if (!streamPartReconnect.isRunning() && !networkSplitAvoidance.isRunning()) {
|
|
196
|
-
logger.debug('Manual rejoin required for stream part', { streamPartId })
|
|
197
|
-
await streamPartReconnect.reconnect()
|
|
198
|
-
}
|
|
199
|
-
})
|
|
200
|
-
node.on('entryPointLeaveDetected', () => handleEntryPointLeave())
|
|
201
|
-
setImmediate(async () => {
|
|
202
|
-
try {
|
|
203
|
-
await this.startLayersAndJoinDht(streamPartId, peerDescriptorStoreManager)
|
|
204
|
-
} catch (err) {
|
|
205
|
-
logger.warn(`Failed to join to stream part ${streamPartId}`, { err })
|
|
206
|
-
}
|
|
207
|
-
})
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
private async startLayersAndJoinDht(streamPartId: StreamPartID, peerDescriptorStoreManager: PeerDescriptorStoreManager): Promise<void> {
|
|
211
|
-
logger.debug(`Start layers and join DHT for stream part ${streamPartId}`)
|
|
212
|
-
const streamPart = this.streamParts.get(streamPartId)
|
|
213
|
-
if ((streamPart === undefined) || streamPart.proxied) {
|
|
214
|
-
// leaveStreamPart has been called (or leaveStreamPart called, and then setProxies called)
|
|
215
|
-
return
|
|
216
|
-
}
|
|
217
|
-
if ((this.transport! as ConnectionManager).isPrivateClientMode()) {
|
|
218
|
-
await (this.transport! as ConnectionManager).disablePrivateClientMode()
|
|
219
|
-
}
|
|
220
|
-
await streamPart.discoveryLayerNode.start()
|
|
221
|
-
await streamPart.node.start()
|
|
222
|
-
const knownEntryPoints = this.knownStreamPartEntryPoints.get(streamPartId)
|
|
223
|
-
if (knownEntryPoints !== undefined) {
|
|
224
|
-
await Promise.all([
|
|
225
|
-
streamPart.discoveryLayerNode.joinDht(knownEntryPoints),
|
|
226
|
-
streamPart.discoveryLayerNode.joinRing()
|
|
227
|
-
])
|
|
228
|
-
} else {
|
|
229
|
-
const entryPoints = await peerDescriptorStoreManager.fetchNodes()
|
|
230
|
-
await Promise.all([
|
|
231
|
-
streamPart.discoveryLayerNode.joinDht(sampleSize(entryPoints, NETWORK_SPLIT_AVOIDANCE_MIN_NEIGHBOR_COUNT)),
|
|
232
|
-
streamPart.discoveryLayerNode.joinRing()
|
|
233
|
-
])
|
|
234
|
-
if (entryPoints.length < MAX_NODE_COUNT) {
|
|
235
|
-
await peerDescriptorStoreManager.storeAndKeepLocalNode()
|
|
236
|
-
if (streamPart.discoveryLayerNode.getNeighborCount() < NETWORK_SPLIT_AVOIDANCE_MIN_NEIGHBOR_COUNT) {
|
|
237
|
-
setImmediate(() => streamPart.networkSplitAvoidance.avoidNetworkSplit())
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
private createDiscoveryLayerNode(streamPartId: StreamPartID, entryPoints: PeerDescriptor[]): DiscoveryLayerNode {
|
|
244
|
-
return new DhtNode({
|
|
245
|
-
transport: this.controlLayerNode!,
|
|
246
|
-
connectionsView: this.controlLayerNode!.getConnectionsView(),
|
|
247
|
-
serviceId: 'layer1::' + streamPartId,
|
|
248
|
-
peerDescriptor: this.controlLayerNode!.getLocalPeerDescriptor(),
|
|
249
|
-
entryPoints,
|
|
250
|
-
numberOfNodesPerKBucket: 4, // TODO use options option or named constant?
|
|
251
|
-
rpcRequestTimeout: EXISTING_CONNECTION_TIMEOUT,
|
|
252
|
-
dhtJoinTimeout: 20000, // TODO use options option or named constant?
|
|
253
|
-
periodicallyPingNeighbors: true,
|
|
254
|
-
periodicallyPingRingContacts: true,
|
|
255
|
-
neighborPingLimit: 16
|
|
256
|
-
})
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
private createContentDeliveryLayerNode(
|
|
260
|
-
streamPartId: StreamPartID,
|
|
261
|
-
discoveryLayerNode: DiscoveryLayerNode,
|
|
262
|
-
isLocalNodeEntryPoint: () => boolean
|
|
263
|
-
) {
|
|
264
|
-
return createContentDeliveryLayerNode({
|
|
265
|
-
streamPartId,
|
|
266
|
-
transport: this.transport!,
|
|
267
|
-
discoveryLayerNode,
|
|
268
|
-
connectionLocker: this.connectionLocker!,
|
|
269
|
-
localPeerDescriptor: this.controlLayerNode!.getLocalPeerDescriptor(),
|
|
270
|
-
minPropagationTargets: this.options.streamPartitionMinPropagationTargets,
|
|
271
|
-
neighborTargetCount: this.options.streamPartitionNeighborTargetCount,
|
|
272
|
-
acceptProxyConnections: this.options.acceptProxyConnections,
|
|
273
|
-
rpcRequestTimeout: this.options.rpcRequestTimeout,
|
|
274
|
-
neighborUpdateInterval: this.options.neighborUpdateInterval,
|
|
275
|
-
isLocalNodeEntryPoint
|
|
276
|
-
})
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
async setProxies(
|
|
280
|
-
streamPartId: StreamPartID,
|
|
281
|
-
nodes: PeerDescriptor[],
|
|
282
|
-
direction: ProxyDirection,
|
|
283
|
-
userId: UserID,
|
|
284
|
-
connectionCount?: number
|
|
285
|
-
): Promise<void> {
|
|
286
|
-
// TODO explicit default value for "acceptProxyConnections" or make it required
|
|
287
|
-
if (this.options.acceptProxyConnections) {
|
|
288
|
-
throw new Error('cannot set proxies when acceptProxyConnections=true')
|
|
289
|
-
}
|
|
290
|
-
const enable = (nodes.length > 0) && ((connectionCount === undefined) || (connectionCount > 0))
|
|
291
|
-
if (enable) {
|
|
292
|
-
let client: ProxyClient
|
|
293
|
-
const alreadyProxied = this.isProxiedStreamPart(streamPartId)
|
|
294
|
-
if (alreadyProxied) {
|
|
295
|
-
client = (this.streamParts.get(streamPartId)! as { client: ProxyClient }).client
|
|
296
|
-
} else {
|
|
297
|
-
client = this.createProxyClient(streamPartId)
|
|
298
|
-
this.streamParts.set(streamPartId, {
|
|
299
|
-
proxied: true,
|
|
300
|
-
client,
|
|
301
|
-
broadcast: (msg: StreamMessage) => client.broadcast(msg),
|
|
302
|
-
stop: async () => client.stop(),
|
|
303
|
-
getDiagnosticInfo: () => client.getDiagnosticInfo()
|
|
304
|
-
})
|
|
305
|
-
client.on('message', (message: StreamMessage) => {
|
|
306
|
-
this.emit('newMessage', message)
|
|
307
|
-
})
|
|
308
|
-
if (Array.from(this.streamParts.values()).every((streamPart) => streamPart.proxied)) {
|
|
309
|
-
await (this.transport! as ConnectionManager).enablePrivateClientMode()
|
|
310
|
-
}
|
|
311
|
-
await client.start()
|
|
312
|
-
}
|
|
313
|
-
await client.setProxies(nodes, direction, userId, connectionCount)
|
|
314
|
-
} else {
|
|
315
|
-
await this.streamParts.get(streamPartId)?.stop()
|
|
316
|
-
this.streamParts.delete(streamPartId)
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
private createProxyClient(streamPartId: StreamPartID): ProxyClient {
|
|
321
|
-
return new ProxyClient({
|
|
322
|
-
transport: this.transport!,
|
|
323
|
-
localPeerDescriptor: this.controlLayerNode!.getLocalPeerDescriptor(),
|
|
324
|
-
streamPartId,
|
|
325
|
-
connectionLocker: this.connectionLocker!,
|
|
326
|
-
minPropagationTargets: this.options.streamPartitionMinPropagationTargets
|
|
327
|
-
})
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
async inspect(peerDescriptor: PeerDescriptor, streamPartId: StreamPartID): Promise<boolean> {
|
|
331
|
-
const streamPart = this.streamParts.get(streamPartId)
|
|
332
|
-
if ((streamPart !== undefined) && !streamPart.proxied) {
|
|
333
|
-
return streamPart.node.inspect(peerDescriptor)
|
|
334
|
-
}
|
|
335
|
-
return false
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// TODO inline this method?
|
|
339
|
-
getNodeInfo(): StreamPartitionInfo[] {
|
|
340
|
-
const streamParts = Array.from(this.streamParts.entries()).filter(([_, node]) => node.proxied === false)
|
|
341
|
-
return streamParts.map(([streamPartId]) => {
|
|
342
|
-
const stream = this.streamParts.get(streamPartId)! as { node: ContentDeliveryLayerNode, discoveryLayerNode: DiscoveryLayerNode }
|
|
343
|
-
return {
|
|
344
|
-
id: streamPartId,
|
|
345
|
-
controlLayerNeighbors: stream.discoveryLayerNode.getNeighbors(),
|
|
346
|
-
deprecatedContentDeliveryLayerNeighbors: [],
|
|
347
|
-
contentDeliveryLayerNeighbors: stream.node.getInfos()
|
|
348
|
-
}
|
|
349
|
-
})
|
|
350
|
-
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
setStreamPartEntryPoints(streamPartId: StreamPartID, entryPoints: PeerDescriptor[]): void {
|
|
354
|
-
this.knownStreamPartEntryPoints.set(streamPartId, entryPoints)
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
isProxiedStreamPart(streamPartId: StreamPartID, direction?: ProxyDirection): boolean {
|
|
358
|
-
const streamPart = this.streamParts.get(streamPartId)
|
|
359
|
-
return (streamPart !== undefined)
|
|
360
|
-
&& streamPart.proxied
|
|
361
|
-
&& ((direction === undefined) || (streamPart.client.getDirection() === direction))
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
getStreamPartDelivery(streamPartId: StreamPartID): StreamPartDelivery | undefined {
|
|
365
|
-
return this.streamParts.get(streamPartId)
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
hasStreamPart(streamPartId: StreamPartID): boolean {
|
|
369
|
-
return this.streamParts.has(streamPartId)
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
getPeerDescriptor(): PeerDescriptor {
|
|
373
|
-
return this.controlLayerNode!.getLocalPeerDescriptor()
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
getNodeId(): DhtAddress {
|
|
377
|
-
return toNodeId(this.controlLayerNode!.getLocalPeerDescriptor())
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
getNeighbors(streamPartId: StreamPartID): DhtAddress[] {
|
|
381
|
-
const streamPart = this.streamParts.get(streamPartId)
|
|
382
|
-
return (streamPart !== undefined) && (streamPart.proxied === false)
|
|
383
|
-
? streamPart.node.getNeighbors().map((n) => toNodeId(n))
|
|
384
|
-
: []
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
getStreamParts(): StreamPartID[] {
|
|
388
|
-
return Array.from(this.streamParts.keys()).map((id) => StreamPartIDUtils.parse(id))
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
getDiagnosticInfo(): Record<string, unknown> {
|
|
392
|
-
return {
|
|
393
|
-
streamParts: this.getStreamParts().map((id) => {
|
|
394
|
-
return {
|
|
395
|
-
id,
|
|
396
|
-
info: this.getStreamPartDelivery(id)!.getDiagnosticInfo()
|
|
397
|
-
}
|
|
398
|
-
})
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
|
|
2
|
-
import { DhtAddress, DhtCallContext, ListeningRpcCommunicator, PeerDescriptor, toNodeId } from '@streamr/dht'
|
|
3
|
-
import { StreamPartID } from '@streamr/utils'
|
|
4
|
-
import { Empty } from '../../generated/google/protobuf/empty'
|
|
5
|
-
import {
|
|
6
|
-
LeaveStreamPartNotice,
|
|
7
|
-
MessageID,
|
|
8
|
-
MessageRef,
|
|
9
|
-
StreamMessage
|
|
10
|
-
} from '../../generated/packages/trackerless-network/protos/NetworkRpc'
|
|
11
|
-
import { IContentDeliveryRpc } from '../../generated/packages/trackerless-network/protos/NetworkRpc.server'
|
|
12
|
-
|
|
13
|
-
export interface ContentDeliveryRpcLocalOptions {
|
|
14
|
-
localPeerDescriptor: PeerDescriptor
|
|
15
|
-
streamPartId: StreamPartID
|
|
16
|
-
markAndCheckDuplicate: (messageId: MessageID, previousMessageRef?: MessageRef) => boolean
|
|
17
|
-
broadcast: (message: StreamMessage, previousNode?: DhtAddress) => void
|
|
18
|
-
onLeaveNotice(remoteNodeId: DhtAddress, isLocalNodeEntryPoint: boolean): void
|
|
19
|
-
markForInspection(remoteNodeId: DhtAddress, messageId: MessageID): void
|
|
20
|
-
rpcCommunicator: ListeningRpcCommunicator
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export class ContentDeliveryRpcLocal implements IContentDeliveryRpc {
|
|
24
|
-
|
|
25
|
-
private readonly options: ContentDeliveryRpcLocalOptions
|
|
26
|
-
|
|
27
|
-
constructor(options: ContentDeliveryRpcLocalOptions) {
|
|
28
|
-
this.options = options
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async sendStreamMessage(message: StreamMessage, context: ServerCallContext): Promise<Empty> {
|
|
32
|
-
const previousNode = toNodeId((context as DhtCallContext).incomingSourceDescriptor!)
|
|
33
|
-
this.options.markForInspection(previousNode, message.messageId!)
|
|
34
|
-
if (this.options.markAndCheckDuplicate(message.messageId!, message.previousMessageRef)) {
|
|
35
|
-
this.options.broadcast(message, previousNode)
|
|
36
|
-
}
|
|
37
|
-
return Empty
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async leaveStreamPartNotice(message: LeaveStreamPartNotice, context: ServerCallContext): Promise<Empty> {
|
|
41
|
-
if (message.streamPartId === this.options.streamPartId) {
|
|
42
|
-
const sourcePeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
|
|
43
|
-
const remoteNodeId = toNodeId(sourcePeerDescriptor)
|
|
44
|
-
this.options.onLeaveNotice(remoteNodeId, message.isEntryPoint)
|
|
45
|
-
}
|
|
46
|
-
return Empty
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { RpcRemote } from '@streamr/dht'
|
|
2
|
-
import { Logger, StreamPartID } from '@streamr/utils'
|
|
3
|
-
import {
|
|
4
|
-
LeaveStreamPartNotice,
|
|
5
|
-
StreamMessage
|
|
6
|
-
} from '../../generated/packages/trackerless-network/protos/NetworkRpc'
|
|
7
|
-
import { ContentDeliveryRpcClient } from '../../generated/packages/trackerless-network/protos/NetworkRpc.client'
|
|
8
|
-
|
|
9
|
-
const logger = new Logger(module)
|
|
10
|
-
|
|
11
|
-
export class ContentDeliveryRpcRemote extends RpcRemote<ContentDeliveryRpcClient> {
|
|
12
|
-
|
|
13
|
-
private rtt?: number
|
|
14
|
-
|
|
15
|
-
async sendStreamMessage(msg: StreamMessage): Promise<void> {
|
|
16
|
-
const options = this.formDhtRpcOptions({
|
|
17
|
-
notification: true
|
|
18
|
-
})
|
|
19
|
-
this.getClient().sendStreamMessage(msg, options).catch(() => {
|
|
20
|
-
logger.trace('Failed to sendStreamMessage')
|
|
21
|
-
})
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
leaveStreamPartNotice(streamPartId: StreamPartID, isLocalNodeEntryPoint: boolean): void {
|
|
25
|
-
const notification: LeaveStreamPartNotice = {
|
|
26
|
-
streamPartId,
|
|
27
|
-
isEntryPoint: isLocalNodeEntryPoint
|
|
28
|
-
}
|
|
29
|
-
const options = this.formDhtRpcOptions({
|
|
30
|
-
notification: true
|
|
31
|
-
})
|
|
32
|
-
this.getClient().leaveStreamPartNotice(notification, options).catch(() => {
|
|
33
|
-
logger.debug('Failed to send leaveStreamPartNotice')
|
|
34
|
-
})
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
setRtt(rtt: number): void {
|
|
38
|
-
this.rtt = rtt
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
getRtt(): number | undefined {
|
|
42
|
-
return this.rtt
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { ConnectionsView, DataEntry, DhtAddress, ITransport, PeerDescriptor } from '@streamr/dht'
|
|
2
|
-
import { Any } from '../../generated/google/protobuf/any'
|
|
3
|
-
|
|
4
|
-
export interface ControlLayerNode extends ITransport {
|
|
5
|
-
joinDht(entryPointDescriptors: PeerDescriptor[]): Promise<void>
|
|
6
|
-
hasJoined(): boolean
|
|
7
|
-
getLocalPeerDescriptor(): PeerDescriptor
|
|
8
|
-
fetchDataFromDht(key: DhtAddress): Promise<DataEntry[]>
|
|
9
|
-
storeDataToDht(key: DhtAddress, data: Any): Promise<PeerDescriptor[]>
|
|
10
|
-
deleteDataFromDht(key: DhtAddress, waitForCompletion: boolean): Promise<void>
|
|
11
|
-
waitForNetworkConnectivity(): Promise<void>
|
|
12
|
-
getTransport(): ITransport
|
|
13
|
-
getNeighbors(): PeerDescriptor[]
|
|
14
|
-
getConnectionsView(): ConnectionsView
|
|
15
|
-
start(): Promise<void>
|
|
16
|
-
stop(): Promise<void>
|
|
17
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { DhtAddress, PeerDescriptor, RingContacts } from '@streamr/dht'
|
|
2
|
-
|
|
3
|
-
export interface DiscoveryLayerNodeEvents {
|
|
4
|
-
manualRejoinRequired: () => void
|
|
5
|
-
nearbyContactAdded: (peerDescriptor: PeerDescriptor) => void
|
|
6
|
-
nearbyContactRemoved: (peerDescriptor: PeerDescriptor) => void
|
|
7
|
-
randomContactAdded: (peerDescriptor: PeerDescriptor) => void
|
|
8
|
-
randomContactRemoved: (peerDescriptor: PeerDescriptor) => void
|
|
9
|
-
ringContactAdded: (peerDescriptor: PeerDescriptor) => void
|
|
10
|
-
ringContactRemoved: (peerDescriptor: PeerDescriptor) => void
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface DiscoveryLayerNode {
|
|
14
|
-
on<T extends keyof DiscoveryLayerNodeEvents>(eventName: T, listener: (peerDescriptor: PeerDescriptor) => void): void
|
|
15
|
-
on<T extends keyof DiscoveryLayerNodeEvents>(eventName: T, listener: () => void): void
|
|
16
|
-
off<T extends keyof DiscoveryLayerNodeEvents>(eventName: T, listener: (peerDescriptor: PeerDescriptor) => void): void
|
|
17
|
-
off<T extends keyof DiscoveryLayerNodeEvents>(eventName: T, listener: () => void): void
|
|
18
|
-
once<T extends keyof DiscoveryLayerNodeEvents>(eventName: T, listener: (peerDescriptor: PeerDescriptor) => void): void
|
|
19
|
-
once<T extends keyof DiscoveryLayerNodeEvents>(eventName: T, listener: () => void): void
|
|
20
|
-
removeContact: (nodeId: DhtAddress) => void
|
|
21
|
-
getClosestContacts: (maxCount?: number) => PeerDescriptor[]
|
|
22
|
-
getRandomContacts: (maxCount?: number) => PeerDescriptor[]
|
|
23
|
-
getRingContacts: () => RingContacts
|
|
24
|
-
getNeighbors: () => PeerDescriptor[]
|
|
25
|
-
getNeighborCount(): number
|
|
26
|
-
joinDht: (entryPoints: PeerDescriptor[], doRandomJoin?: boolean, retry?: boolean) => Promise<void>
|
|
27
|
-
joinRing: () => Promise<void>
|
|
28
|
-
start: () => Promise<void>
|
|
29
|
-
stop: () => Promise<void>
|
|
30
|
-
}
|