@streamr/trackerless-network 102.0.0-beta.1 → 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.
Files changed (103) hide show
  1. package/dist/package.json +5 -5
  2. package/package.json +5 -5
  3. package/src/NetworkNode.ts +0 -142
  4. package/src/NetworkStack.ts +0 -197
  5. package/src/exports.ts +0 -18
  6. package/src/logic/ContentDeliveryLayerNode.ts +0 -424
  7. package/src/logic/ContentDeliveryManager.ts +0 -401
  8. package/src/logic/ContentDeliveryRpcLocal.ts +0 -48
  9. package/src/logic/ContentDeliveryRpcRemote.ts +0 -44
  10. package/src/logic/ControlLayerNode.ts +0 -17
  11. package/src/logic/DiscoveryLayerNode.ts +0 -30
  12. package/src/logic/DuplicateMessageDetector.ts +0 -167
  13. package/src/logic/ExternalNetworkRpc.ts +0 -42
  14. package/src/logic/NodeList.ts +0 -114
  15. package/src/logic/PeerDescriptorStoreManager.ts +0 -96
  16. package/src/logic/StreamPartNetworkSplitAvoidance.ts +0 -90
  17. package/src/logic/StreamPartReconnect.ts +0 -38
  18. package/src/logic/createContentDeliveryLayerNode.ts +0 -130
  19. package/src/logic/formStreamPartDeliveryServiceId.ts +0 -7
  20. package/src/logic/inspect/InspectSession.ts +0 -55
  21. package/src/logic/inspect/Inspector.ts +0 -100
  22. package/src/logic/neighbor-discovery/HandshakeRpcLocal.ts +0 -138
  23. package/src/logic/neighbor-discovery/HandshakeRpcRemote.ts +0 -66
  24. package/src/logic/neighbor-discovery/Handshaker.ts +0 -215
  25. package/src/logic/neighbor-discovery/NeighborFinder.ts +0 -77
  26. package/src/logic/neighbor-discovery/NeighborUpdateManager.ts +0 -69
  27. package/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.ts +0 -75
  28. package/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.ts +0 -35
  29. package/src/logic/node-info/NodeInfoClient.ts +0 -23
  30. package/src/logic/node-info/NodeInfoRpcLocal.ts +0 -28
  31. package/src/logic/node-info/NodeInfoRpcRemote.ts +0 -11
  32. package/src/logic/propagation/FifoMapWithTTL.ts +0 -116
  33. package/src/logic/propagation/Propagation.ts +0 -84
  34. package/src/logic/propagation/PropagationTaskStore.ts +0 -41
  35. package/src/logic/proxy/ProxyClient.ts +0 -286
  36. package/src/logic/proxy/ProxyConnectionRpcLocal.ts +0 -106
  37. package/src/logic/proxy/ProxyConnectionRpcRemote.ts +0 -26
  38. package/src/logic/temporary-connection/TemporaryConnectionRpcLocal.ts +0 -73
  39. package/src/logic/temporary-connection/TemporaryConnectionRpcRemote.ts +0 -29
  40. package/src/logic/utils.ts +0 -18
  41. package/src/types.ts +0 -13
  42. package/test/benchmark/StreamPartIdDataKeyDistribution.test.ts +0 -60
  43. package/test/benchmark/first-message.ts +0 -171
  44. package/test/end-to-end/content-delivery-layer-node-with-real-connections.test.ts +0 -165
  45. package/test/end-to-end/external-network-rpc.test.ts +0 -67
  46. package/test/end-to-end/inspect.test.ts +0 -124
  47. package/test/end-to-end/proxy-and-full-node.test.ts +0 -143
  48. package/test/end-to-end/proxy-connections.test.ts +0 -226
  49. package/test/end-to-end/proxy-key-exchange.test.ts +0 -126
  50. package/test/end-to-end/webrtc-full-node-network.test.ts +0 -83
  51. package/test/end-to-end/websocket-full-node-network.test.ts +0 -82
  52. package/test/integration/ContentDeliveryLayerNode-Layer1Node-Latencies.test.ts +0 -139
  53. package/test/integration/ContentDeliveryLayerNode-Layer1Node.test.ts +0 -162
  54. package/test/integration/ContentDeliveryManager.test.ts +0 -160
  55. package/test/integration/ContentDeliveryRpcRemote.test.ts +0 -100
  56. package/test/integration/HandshakeRpcRemote.test.ts +0 -79
  57. package/test/integration/Handshakes.test.ts +0 -141
  58. package/test/integration/Inspect.test.ts +0 -89
  59. package/test/integration/NeighborUpdateRpcRemote.test.ts +0 -82
  60. package/test/integration/NetworkNode.test.ts +0 -115
  61. package/test/integration/NetworkRpc.test.ts +0 -52
  62. package/test/integration/NetworkStack.test.ts +0 -72
  63. package/test/integration/NodeInfoRpc.test.ts +0 -109
  64. package/test/integration/Propagation.test.ts +0 -76
  65. package/test/integration/joining-streams-on-offline-peers.test.ts +0 -82
  66. package/test/integration/stream-without-default-entrypoints.test.ts +0 -128
  67. package/test/integration/streamEntryPointReplacing.test.ts +0 -97
  68. package/test/types/global.d.ts +0 -1
  69. package/test/unit/ContentDeliveryLayerNode.test.ts +0 -112
  70. package/test/unit/ContentDeliveryManager.test.ts +0 -96
  71. package/test/unit/ContentDeliveryRpcLocal.test.ts +0 -60
  72. package/test/unit/DuplicateMessageDetector.test.ts +0 -192
  73. package/test/unit/ExternalNetworkRpc.test.ts +0 -48
  74. package/test/unit/FifoMapWithTtl.test.ts +0 -253
  75. package/test/unit/HandshakeRpcLocal.test.ts +0 -155
  76. package/test/unit/Handshaker.test.ts +0 -69
  77. package/test/unit/InspectSession.test.ts +0 -83
  78. package/test/unit/Inspector.test.ts +0 -51
  79. package/test/unit/NeighborFinder.test.ts +0 -51
  80. package/test/unit/NeighborUpdateRpcLocal.test.ts +0 -139
  81. package/test/unit/NetworkNode.test.ts +0 -42
  82. package/test/unit/NodeList.test.ts +0 -164
  83. package/test/unit/NumberPair.test.ts +0 -22
  84. package/test/unit/PeerDescriptorStoreManager.test.ts +0 -103
  85. package/test/unit/Propagation.test.ts +0 -151
  86. package/test/unit/ProxyConnectionRpcRemote.test.ts +0 -39
  87. package/test/unit/StreamPartIDDataKey.test.ts +0 -12
  88. package/test/unit/StreamPartNetworkSplitAvoidance.test.ts +0 -31
  89. package/test/unit/StreamPartReconnect.test.ts +0 -30
  90. package/test/unit/TemporaryConnectionRpcLocal.test.ts +0 -38
  91. package/test/utils/fake/FakePeerDescriptorStoreManager.ts +0 -29
  92. package/test/utils/mock/MockConnectionsView.ts +0 -18
  93. package/test/utils/mock/MockControlLayerNode.ts +0 -78
  94. package/test/utils/mock/MockDiscoveryLayerNode.ts +0 -60
  95. package/test/utils/mock/MockHandshaker.ts +0 -17
  96. package/test/utils/mock/MockNeighborFinder.ts +0 -20
  97. package/test/utils/mock/MockNeighborUpdateManager.ts +0 -21
  98. package/test/utils/mock/MockTransport.ts +0 -30
  99. package/test/utils/utils.ts +0 -144
  100. package/tsconfig.browser.json +0 -13
  101. package/tsconfig.jest.json +0 -17
  102. package/tsconfig.json +0 -3
  103. package/tsconfig.node.json +0 -17
@@ -1,286 +0,0 @@
1
- import {
2
- ConnectionLocker,
3
- DhtAddress,
4
- ITransport,
5
- ListeningRpcCommunicator,
6
- PeerDescriptor,
7
- toNodeId
8
- } from '@streamr/dht'
9
- import { Logger, StreamPartID, UserID, addManagedEventListener, wait } from '@streamr/utils'
10
- import { EventEmitter } from 'eventemitter3'
11
- import { sampleSize } from 'lodash'
12
- import {
13
- LeaveStreamPartNotice,
14
- MessageID,
15
- MessageRef,
16
- ProxyDirection,
17
- StreamMessage
18
- } from '../../../generated/packages/trackerless-network/protos/NetworkRpc'
19
- import { ContentDeliveryRpcClient, ProxyConnectionRpcClient } from '../../../generated/packages/trackerless-network/protos/NetworkRpc.client'
20
- import { ContentDeliveryRpcLocal } from '../ContentDeliveryRpcLocal'
21
- import { ContentDeliveryRpcRemote } from '../ContentDeliveryRpcRemote'
22
- import { DuplicateMessageDetector } from '../DuplicateMessageDetector'
23
- import { NodeList } from '../NodeList'
24
- import { formStreamPartContentDeliveryServiceId } from '../formStreamPartDeliveryServiceId'
25
- import { Propagation } from '../propagation/Propagation'
26
- import { markAndCheckDuplicate } from '../utils'
27
- import { ProxyConnectionRpcRemote } from './ProxyConnectionRpcRemote'
28
-
29
- // TODO use options option or named constant?
30
- export const retry = async <T>(task: () => Promise<T>, description: string, abortSignal: AbortSignal, delay = 10000): Promise<T> => {
31
- while (true) {
32
- try {
33
- const result = await task()
34
- return result
35
- } catch {
36
- logger.warn(`Failed ${description} (retrying after delay)`, {
37
- delayInMs: delay
38
- })
39
- }
40
- await wait(delay, abortSignal)
41
- }
42
- }
43
-
44
- interface ProxyClientOptions {
45
- transport: ITransport
46
- localPeerDescriptor: PeerDescriptor
47
- streamPartId: StreamPartID
48
- connectionLocker: ConnectionLocker
49
- minPropagationTargets?: number // TODO could be required option if we apply all defaults somewhere at higher level
50
- }
51
-
52
- interface ProxyDefinition {
53
- nodes: Map<DhtAddress, PeerDescriptor>
54
- connectionCount: number
55
- direction: ProxyDirection
56
- userId: UserID
57
- }
58
-
59
- interface ProxyConnection {
60
- peerDescriptor: PeerDescriptor
61
- direction: ProxyDirection
62
- }
63
-
64
- interface Events {
65
- message: (message: StreamMessage) => void
66
- }
67
-
68
- const logger = new Logger(module)
69
-
70
- const SERVICE_ID = 'system/proxy-client'
71
-
72
- export class ProxyClient extends EventEmitter<Events> {
73
-
74
- private readonly rpcCommunicator: ListeningRpcCommunicator
75
- private readonly contentDeliveryRpcLocal: ContentDeliveryRpcLocal
76
- private readonly options: ProxyClientOptions
77
- private readonly duplicateDetectors: Map<string, DuplicateMessageDetector> = new Map()
78
- private definition?: ProxyDefinition
79
- private readonly connections: Map<DhtAddress, ProxyConnection> = new Map()
80
- private readonly propagation: Propagation
81
- private readonly neighbors: NodeList
82
- private readonly abortController: AbortController
83
-
84
- constructor(options: ProxyClientOptions) {
85
- super()
86
- this.options = options
87
- this.rpcCommunicator = new ListeningRpcCommunicator(formStreamPartContentDeliveryServiceId(options.streamPartId), options.transport)
88
- // TODO use options option or named constant?
89
- this.neighbors = new NodeList(toNodeId(this.options.localPeerDescriptor), 1000)
90
- this.contentDeliveryRpcLocal = new ContentDeliveryRpcLocal({
91
- localPeerDescriptor: this.options.localPeerDescriptor,
92
- streamPartId: this.options.streamPartId,
93
- markAndCheckDuplicate: (msg: MessageID, prev?: MessageRef) => markAndCheckDuplicate(this.duplicateDetectors, msg, prev),
94
- broadcast: (message: StreamMessage, previousNode?: DhtAddress) => this.broadcast(message, previousNode),
95
- onLeaveNotice: (remoteNodeId: DhtAddress) => {
96
- const contact = this.neighbors.get(remoteNodeId)
97
- if (contact) {
98
- // TODO should we catch possible promise rejection?
99
- setImmediate(() => this.onNodeDisconnected(contact.getPeerDescriptor()))
100
- }
101
- },
102
- rpcCommunicator: this.rpcCommunicator,
103
- markForInspection: () => {}
104
- })
105
- this.propagation = new Propagation({
106
- // TODO use options option or named constant?
107
- minPropagationTargets: options.minPropagationTargets ?? 2,
108
- sendToNeighbor: async (neighborId: DhtAddress, msg: StreamMessage): Promise<void> => {
109
- const remote = this.neighbors.get(neighborId)
110
- if (remote) {
111
- await remote.sendStreamMessage(msg)
112
- } else {
113
- throw new Error('Propagation target not found')
114
- }
115
- }
116
- })
117
- this.abortController = new AbortController()
118
- }
119
-
120
- private registerDefaultServerMethods(): void {
121
- this.rpcCommunicator.registerRpcNotification(StreamMessage, 'sendStreamMessage',
122
- (msg: StreamMessage, context) => this.contentDeliveryRpcLocal.sendStreamMessage(msg, context))
123
- this.rpcCommunicator.registerRpcNotification(LeaveStreamPartNotice, 'leaveStreamPartNotice',
124
- (req: LeaveStreamPartNotice, context) => this.contentDeliveryRpcLocal.leaveStreamPartNotice(req, context))
125
- }
126
-
127
- async setProxies(
128
- nodes: PeerDescriptor[],
129
- direction: ProxyDirection,
130
- userId: UserID,
131
- connectionCount?: number
132
- ): Promise<void> {
133
- logger.trace('Setting proxies', { streamPartId: this.options.streamPartId, peerDescriptors: nodes, direction, userId, connectionCount })
134
- if (connectionCount !== undefined && connectionCount > nodes.length) {
135
- throw new Error('Cannot set connectionCount above the size of the configured array of nodes')
136
- }
137
- const nodesIds = new Map<DhtAddress, PeerDescriptor>()
138
- nodes.forEach((peerDescriptor) => {
139
- nodesIds.set(toNodeId(peerDescriptor), peerDescriptor)
140
- })
141
- this.definition = {
142
- nodes: nodesIds,
143
- userId,
144
- direction,
145
- connectionCount: connectionCount ?? nodes.length
146
- }
147
- await this.updateConnections()
148
- }
149
-
150
- private async updateConnections(): Promise<void> {
151
- await Promise.all(this.getInvalidConnections().map(async (id) => {
152
- await this.closeConnection(id)
153
- }))
154
- const connectionCountDiff = this.definition!.connectionCount - this.connections.size
155
- if (connectionCountDiff > 0) {
156
- await this.openRandomConnections(connectionCountDiff)
157
- } else if (connectionCountDiff < 0) {
158
- await this.closeRandomConnections(-connectionCountDiff)
159
- }
160
- }
161
-
162
- private getInvalidConnections(): DhtAddress[] {
163
- return Array.from(this.connections.keys()).filter((id) => {
164
- return !this.definition!.nodes.has(id)
165
- || this.definition!.direction !== this.connections.get(id)!.direction
166
- })
167
- }
168
-
169
- private async openRandomConnections(connectionCount: number): Promise<void> {
170
- const proxiesToAttempt = sampleSize(Array.from(this.definition!.nodes.keys()).filter((id) =>
171
- !this.connections.has(id)
172
- ), connectionCount)
173
- await Promise.all(proxiesToAttempt.map((id) =>
174
- this.attemptConnection(id, this.definition!.direction, this.definition!.userId)
175
- ))
176
- }
177
-
178
- private async attemptConnection(nodeId: DhtAddress, direction: ProxyDirection, userId: UserID): Promise<void> {
179
- const peerDescriptor = this.definition!.nodes.get(nodeId)!
180
- const rpcRemote = new ProxyConnectionRpcRemote(
181
- this.options.localPeerDescriptor,
182
- peerDescriptor,
183
- this.rpcCommunicator,
184
- ProxyConnectionRpcClient
185
- )
186
- const accepted = await rpcRemote.requestConnection(direction, userId)
187
- if (accepted) {
188
- this.options.connectionLocker.lockConnection(peerDescriptor, SERVICE_ID)
189
- this.connections.set(nodeId, { peerDescriptor, direction })
190
- const remote = new ContentDeliveryRpcRemote(
191
- this.options.localPeerDescriptor,
192
- peerDescriptor,
193
- this.rpcCommunicator,
194
- ContentDeliveryRpcClient
195
- )
196
- this.neighbors.add(remote)
197
- this.propagation.onNeighborJoined(nodeId)
198
- logger.info('Open proxy connection', {
199
- nodeId,
200
- streamPartId: this.options.streamPartId
201
- })
202
- } else {
203
- logger.warn('Unable to open proxy connection', {
204
- nodeId,
205
- streamPartId: this.options.streamPartId
206
- })
207
- }
208
- }
209
-
210
- private async closeRandomConnections(connectionCount: number): Promise<void> {
211
- const proxiesToDisconnect = sampleSize(Array.from(this.connections.keys()), connectionCount)
212
- await Promise.allSettled(proxiesToDisconnect.map((node) => this.closeConnection(node)))
213
- }
214
-
215
- private async closeConnection(nodeId: DhtAddress): Promise<void> {
216
- if (this.connections.has(nodeId)) {
217
- logger.info('Close proxy connection', {
218
- nodeId
219
- })
220
- const server = this.neighbors.get(nodeId)
221
- server?.leaveStreamPartNotice(this.options.streamPartId, false)
222
- this.removeConnection(this.connections.get(nodeId)!.peerDescriptor)
223
- }
224
- }
225
-
226
- private removeConnection(peerDescriptor: PeerDescriptor): void {
227
- const nodeId = toNodeId(peerDescriptor)
228
- this.connections.delete(nodeId)
229
- this.neighbors.remove(nodeId)
230
- this.options.connectionLocker.unlockConnection(peerDescriptor, SERVICE_ID)
231
- }
232
-
233
- broadcast(msg: StreamMessage, previousNode?: DhtAddress): void {
234
- if (!previousNode) {
235
- markAndCheckDuplicate(this.duplicateDetectors, msg.messageId!, msg.previousMessageRef)
236
- }
237
- this.emit('message', msg)
238
- this.propagation.feedUnseenMessage(msg, this.neighbors.getIds(), previousNode ?? null)
239
- }
240
-
241
- hasConnection(nodeId: DhtAddress, direction: ProxyDirection): boolean {
242
- return this.connections.has(nodeId) && this.connections.get(nodeId)!.direction === direction
243
- }
244
-
245
- getDirection(): ProxyDirection {
246
- return this.definition!.direction
247
- }
248
-
249
- private async onNodeDisconnected(peerDescriptor: PeerDescriptor): Promise<void> {
250
- const nodeId = toNodeId(peerDescriptor)
251
- if (this.connections.has(nodeId)) {
252
- this.options.connectionLocker.unlockConnection(peerDescriptor, SERVICE_ID)
253
- this.removeConnection(peerDescriptor)
254
- await retry(() => this.updateConnections(), 'updating proxy connections', this.abortController.signal)
255
- }
256
- }
257
-
258
- async start(): Promise<void> {
259
- this.registerDefaultServerMethods()
260
- addManagedEventListener(
261
- this.options.transport,
262
- 'disconnected',
263
- // TODO should we catch possible promise rejection?
264
- (peerDescriptor: PeerDescriptor) => this.onNodeDisconnected(peerDescriptor),
265
- this.abortController.signal
266
- )
267
- }
268
-
269
- public getDiagnosticInfo(): Record<string, unknown> {
270
- return {
271
- neighbors: this.neighbors.getAll().map((neighbor) => neighbor.getPeerDescriptor()),
272
- }
273
- }
274
-
275
- stop(): void {
276
- this.neighbors.getAll().forEach((remote) => {
277
- this.options.connectionLocker.unlockConnection(remote.getPeerDescriptor(), SERVICE_ID)
278
- remote.leaveStreamPartNotice(this.options.streamPartId, false)
279
- })
280
- this.neighbors.stop()
281
- this.rpcCommunicator.destroy()
282
- this.connections.clear()
283
- this.abortController.abort()
284
- }
285
-
286
- }
@@ -1,106 +0,0 @@
1
- import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
2
- import { DhtAddress, DhtCallContext, ListeningRpcCommunicator, PeerDescriptor, toNodeId } from '@streamr/dht'
3
- import { Logger, StreamPartID, toUserId, UserID } from '@streamr/utils'
4
- import { EventEmitter } from 'eventemitter3'
5
- import {
6
- ProxyConnectionRequest,
7
- ProxyConnectionResponse,
8
- ProxyDirection,
9
- StreamMessage
10
- } from '../../../generated/packages/trackerless-network/protos/NetworkRpc'
11
- import { ContentDeliveryRpcClient } from '../../../generated/packages/trackerless-network/protos/NetworkRpc.client'
12
- import { IProxyConnectionRpc } from '../../../generated/packages/trackerless-network/protos/NetworkRpc.server'
13
- import { ContentDeliveryRpcRemote } from '../ContentDeliveryRpcRemote'
14
-
15
- const logger = new Logger(module)
16
-
17
- interface ProxyConnection {
18
- direction: ProxyDirection // Direction is from the client's point of view
19
- userId: UserID
20
- remote: ContentDeliveryRpcRemote
21
- }
22
-
23
- interface ProxyConnectionRpcLocalOptions {
24
- localPeerDescriptor: PeerDescriptor
25
- streamPartId: StreamPartID
26
- rpcCommunicator: ListeningRpcCommunicator
27
- }
28
-
29
- export interface Events {
30
- newConnection: (nodeId: DhtAddress) => void
31
- }
32
-
33
- export class ProxyConnectionRpcLocal extends EventEmitter<Events> implements IProxyConnectionRpc {
34
-
35
- private readonly options: ProxyConnectionRpcLocalOptions
36
- private readonly connections: Map<DhtAddress, ProxyConnection> = new Map()
37
-
38
- constructor(options: ProxyConnectionRpcLocalOptions) {
39
- super()
40
- this.options = options
41
- this.options.rpcCommunicator.registerRpcMethod(ProxyConnectionRequest, ProxyConnectionResponse, 'requestConnection',
42
- (msg: ProxyConnectionRequest, context) => this.requestConnection(msg, context))
43
- }
44
-
45
- getConnection(nodeId: DhtAddress): ProxyConnection | undefined {
46
- return this.connections.get(nodeId)
47
- }
48
-
49
- hasConnection(nodeId: DhtAddress): boolean {
50
- return this.connections.has(nodeId)
51
- }
52
-
53
- removeConnection(nodeId: DhtAddress): void {
54
- this.connections.delete(nodeId)
55
- }
56
-
57
- stop(): void {
58
- this.connections.forEach((connection) => connection.remote.leaveStreamPartNotice(this.options.streamPartId, false))
59
- this.connections.clear()
60
- this.removeAllListeners()
61
- }
62
-
63
- getPropagationTargets(msg: StreamMessage): DhtAddress[] {
64
- if (msg.body.oneofKind === 'groupKeyRequest') {
65
- try {
66
- const recipientId = msg.body.groupKeyRequest.recipientId
67
- return this.getNodeIdsForUserId(toUserId(recipientId))
68
- } catch (err) {
69
- logger.trace(`Could not parse GroupKeyRequest`, { err })
70
- return []
71
- }
72
- } else {
73
- return this.getSubscribers()
74
- }
75
- }
76
-
77
- private getNodeIdsForUserId(userId: UserID): DhtAddress[] {
78
- return Array.from(this.connections.keys()).filter((nodeId) => this.connections.get(nodeId)!.userId === userId)
79
- }
80
-
81
- private getSubscribers(): DhtAddress[] {
82
- return Array.from(this.connections.keys()).filter((key) => this.connections.get(key)!.direction === ProxyDirection.SUBSCRIBE)
83
- }
84
-
85
- // IProxyConnectionRpc server method
86
- async requestConnection(request: ProxyConnectionRequest, context: ServerCallContext): Promise<ProxyConnectionResponse> {
87
- const senderPeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
88
- const remoteNodeId = toNodeId(senderPeerDescriptor)
89
- this.connections.set(remoteNodeId, {
90
- direction: request.direction,
91
- userId: toUserId(request.userId),
92
- remote: new ContentDeliveryRpcRemote(
93
- this.options.localPeerDescriptor,
94
- senderPeerDescriptor,
95
- this.options.rpcCommunicator,
96
- ContentDeliveryRpcClient
97
- )
98
- })
99
- const response: ProxyConnectionResponse = {
100
- accepted: true
101
- }
102
- logger.trace(`Accepted connection request from ${remoteNodeId} to ${this.options.streamPartId}`)
103
- this.emit('newConnection', remoteNodeId)
104
- return response
105
- }
106
- }
@@ -1,26 +0,0 @@
1
- import { EXISTING_CONNECTION_TIMEOUT, RpcRemote } from '@streamr/dht'
2
- import { Logger, UserID, toUserIdRaw } from '@streamr/utils'
3
- import { ProxyConnectionRequest, ProxyDirection } from '../../../generated/packages/trackerless-network/protos/NetworkRpc'
4
- import { ProxyConnectionRpcClient } from '../../../generated/packages/trackerless-network/protos/NetworkRpc.client'
5
-
6
- const logger = new Logger(module)
7
-
8
- export class ProxyConnectionRpcRemote extends RpcRemote<ProxyConnectionRpcClient> {
9
-
10
- async requestConnection(direction: ProxyDirection, userId: UserID): Promise<boolean> {
11
- const request: ProxyConnectionRequest = {
12
- direction,
13
- userId: toUserIdRaw(userId)
14
- }
15
- const options = this.formDhtRpcOptions({
16
- timeout: EXISTING_CONNECTION_TIMEOUT
17
- })
18
- try {
19
- const res = await this.getClient().requestConnection(request, options)
20
- return res.accepted
21
- } catch (err) {
22
- logger.debug(`ProxyConnectionRequest failed with error`, { err })
23
- return false
24
- }
25
- }
26
- }
@@ -1,73 +0,0 @@
1
- import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
2
- import { ConnectionLocker, DhtAddress, DhtCallContext, ListeningRpcCommunicator, toNodeId } from '@streamr/dht'
3
- import { StreamPartID } from '@streamr/utils'
4
- import { Empty } from '../../../generated/google/protobuf/empty'
5
- import { PeerDescriptor } from '../../../generated/packages/dht/protos/DhtRpc'
6
- import {
7
- CloseTemporaryConnection,
8
- TemporaryConnectionRequest,
9
- TemporaryConnectionResponse
10
- } from '../../../generated/packages/trackerless-network/protos/NetworkRpc'
11
- import { ContentDeliveryRpcClient } from '../../../generated/packages/trackerless-network/protos/NetworkRpc.client'
12
- import { ITemporaryConnectionRpc } from '../../../generated/packages/trackerless-network/protos/NetworkRpc.server'
13
- import { ContentDeliveryRpcRemote } from '../ContentDeliveryRpcRemote'
14
- import { NodeList } from '../NodeList'
15
-
16
- interface TemporaryConnectionRpcLocalOptions {
17
- rpcCommunicator: ListeningRpcCommunicator
18
- localPeerDescriptor: PeerDescriptor
19
- streamPartId: StreamPartID
20
- connectionLocker: ConnectionLocker
21
- }
22
-
23
- const LOCK_ID_BASE = 'system/content-delivery/temporary-connection/'
24
-
25
- export class TemporaryConnectionRpcLocal implements ITemporaryConnectionRpc {
26
-
27
- private readonly options: TemporaryConnectionRpcLocalOptions
28
- private readonly temporaryNodes: NodeList
29
- private readonly lockId: string
30
- constructor(options: TemporaryConnectionRpcLocalOptions) {
31
- this.options = options
32
- // TODO use options option or named constant?
33
- this.temporaryNodes = new NodeList(toNodeId(options.localPeerDescriptor), 10)
34
- this.lockId = LOCK_ID_BASE + options.streamPartId
35
- }
36
-
37
- getNodes(): NodeList {
38
- return this.temporaryNodes
39
- }
40
-
41
- hasNode(node: DhtAddress): boolean {
42
- return this.temporaryNodes.has(node)
43
- }
44
-
45
- removeNode(nodeId: DhtAddress): void {
46
- this.temporaryNodes.remove(nodeId)
47
- this.options.connectionLocker.weakUnlockConnection(nodeId, this.lockId)
48
- }
49
-
50
- async openConnection(
51
- _request: TemporaryConnectionRequest,
52
- context: ServerCallContext
53
- ): Promise<TemporaryConnectionResponse> {
54
- const sender = (context as DhtCallContext).incomingSourceDescriptor!
55
- const remote = new ContentDeliveryRpcRemote(
56
- this.options.localPeerDescriptor,
57
- sender,
58
- this.options.rpcCommunicator,
59
- ContentDeliveryRpcClient
60
- )
61
- this.temporaryNodes.add(remote)
62
- this.options.connectionLocker.weakLockConnection(toNodeId(sender), this.lockId)
63
- return {
64
- accepted: true
65
- }
66
- }
67
-
68
- async closeConnection(_request: CloseTemporaryConnection, context: ServerCallContext): Promise<Empty> {
69
- const remoteNodeId = toNodeId((context as DhtCallContext).incomingSourceDescriptor!)
70
- this.removeNode(remoteNodeId)
71
- return {}
72
- }
73
- }
@@ -1,29 +0,0 @@
1
- import { RpcRemote, toNodeId } from '@streamr/dht'
2
- import { Logger } from '@streamr/utils'
3
- import { TemporaryConnectionRpcClient } from '../../../generated/packages/trackerless-network/protos/NetworkRpc.client'
4
-
5
- const logger = new Logger(module)
6
-
7
- export class TemporaryConnectionRpcRemote extends RpcRemote<TemporaryConnectionRpcClient> {
8
-
9
- async openConnection(): Promise<boolean> {
10
- try {
11
- const response = await this.getClient().openConnection({}, this.formDhtRpcOptions())
12
- return response.accepted
13
- } catch (err: any) {
14
- logger.debug(`temporaryConnection to ${toNodeId(this.getPeerDescriptor())} failed`, { err })
15
- return false
16
- }
17
- }
18
-
19
- async closeConnection(): Promise<void> {
20
- try {
21
- await this.getClient().closeConnection({}, this.formDhtRpcOptions({
22
- connect: false,
23
- notification: true
24
- }))
25
- } catch (err) {
26
- logger.trace(`closeConnection to ${toNodeId(this.getPeerDescriptor())} failed`, { err })
27
- }
28
- }
29
- }
@@ -1,18 +0,0 @@
1
- import { toUserId } from '@streamr/utils'
2
- import { MessageID, MessageRef } from '../../generated/packages/trackerless-network/protos/NetworkRpc'
3
- import { DuplicateMessageDetector, NumberPair } from './DuplicateMessageDetector'
4
-
5
- export const markAndCheckDuplicate = (
6
- duplicateDetectors: Map<string, DuplicateMessageDetector>,
7
- currentMessage: MessageID,
8
- previousMessageRef?: MessageRef
9
- ): boolean => {
10
- const detectorKey = `${toUserId(currentMessage.publisherId)}-${currentMessage.messageChainId}`
11
- const previousNumberPair = previousMessageRef ?
12
- new NumberPair(Number(previousMessageRef.timestamp), previousMessageRef.sequenceNumber) : null
13
- const currentNumberPair = new NumberPair(Number(currentMessage.timestamp), currentMessage.sequenceNumber)
14
- if (!duplicateDetectors.has(detectorKey)) {
15
- duplicateDetectors.set(detectorKey, new DuplicateMessageDetector())
16
- }
17
- return duplicateDetectors.get(detectorKey)!.markAndCheck(previousNumberPair, currentNumberPair)
18
- }
package/src/types.ts DELETED
@@ -1,13 +0,0 @@
1
- import { ChangeFieldType } from '@streamr/utils'
2
- import { MarkRequired } from 'ts-essentials'
3
- import {
4
- ContentDeliveryLayerNeighborInfo as ContentDeliveryLayerNeighborInfo_,
5
- NodeInfoResponse,
6
- StreamPartitionInfo as StreamPartitionInfo_
7
- } from '../generated/packages/trackerless-network/protos/NetworkRpc'
8
-
9
- // These types are part of trackerless-network's public API. Therefore removing optionality from fields which are
10
- // actually required. TODO: could do the same thing for other generated interfaces which are part of the public API.
11
- export type ContentDeliveryLayerNeighborInfo = MarkRequired<ContentDeliveryLayerNeighborInfo_, 'peerDescriptor'>
12
- export type StreamPartitionInfo = ChangeFieldType<Required<StreamPartitionInfo_>, 'contentDeliveryLayerNeighbors', ContentDeliveryLayerNeighborInfo[]>
13
- export type NodeInfo = ChangeFieldType<Required<NodeInfoResponse>, 'streamPartitions', StreamPartitionInfo[]>
@@ -1,60 +0,0 @@
1
- /* eslint-disable no-console */
2
-
3
- import { DhtAddress } from '@streamr/dht'
4
- import { StreamPartIDUtils } from '@streamr/utils'
5
- import { groupBy, range } from 'lodash'
6
- import { streamPartIdToDataKey } from '../../src/logic/ContentDeliveryManager'
7
-
8
- describe('StreamPartIdDataKeyDistribution', () => {
9
-
10
- it('partitions are well distributed', () => {
11
-
12
- const streamId = 'stream'
13
- const dataKeys = range(100).map((i) => {
14
- const streamPartId = StreamPartIDUtils.parse(streamId + '#' + i)
15
- return streamPartIdToDataKey(streamPartId)
16
- })
17
-
18
- const byInitials = groupBy(dataKeys, (dataKey: DhtAddress) => dataKey[0])
19
- expect(Object.keys(byInitials).length).toEqual(16)
20
- console.log(Object.values(byInitials).map((a) => a.length))
21
- })
22
-
23
- it('streamIds are well distributed', () => {
24
- const dataKeys = range(10000).map(() => {
25
- const streamPartId = StreamPartIDUtils.parse(Math.random().toString(32).substr(2, 32) + '#0')
26
- return streamPartIdToDataKey(streamPartId)
27
- })
28
- const byInitials = groupBy(dataKeys, (dataKey: DhtAddress) => dataKey[0])
29
- expect(Object.keys(byInitials).length).toEqual(16)
30
- console.log(Object.values(byInitials).map((a) => a.length))
31
- })
32
-
33
- it('streamPartIds are well distributed', () => {
34
- const streamIds = range(10000).map(() => Math.random().toString(32).substr(2, 32))
35
- const dataKeys: DhtAddress[] = []
36
- streamIds.forEach((streamId) => {
37
- range(100).forEach((i) => {
38
- const streamPartId = StreamPartIDUtils.parse(streamId + '#' + i)
39
- dataKeys.push(streamPartIdToDataKey(streamPartId))
40
- })
41
- })
42
-
43
- const byInitials = groupBy(dataKeys, (dataKey: DhtAddress) => dataKey[0])
44
- expect(Object.keys(byInitials).length).toEqual(16)
45
- console.log(Object.values(byInitials).map((a) => a.length))
46
-
47
- const byTwoInitials = groupBy(dataKeys, (dataKey: DhtAddress) => dataKey[0] + dataKey[1])
48
- expect(Object.keys(byTwoInitials).length).toEqual(16 * 16)
49
- console.log(Object.values(byTwoInitials).map((a) => a.length))
50
-
51
- const byThreeInitials = groupBy(dataKeys, (dataKey: DhtAddress) => dataKey[0] + dataKey[1] + dataKey[2])
52
- expect(Object.keys(byThreeInitials).length).toEqual(16 * 16 * 16)
53
- console.log(Object.values(byThreeInitials).map((a) => a.length))
54
-
55
- const byFourInitials = groupBy(dataKeys, (dataKey: DhtAddress) => dataKey[0] + dataKey[1] + dataKey[2] + dataKey[3])
56
- expect(Object.keys(byFourInitials).length).toEqual(16 * 16 * 16 * 16)
57
- console.log(Object.values(byFourInitials).map((a) => a.length))
58
- })
59
-
60
- })