@streamr/dht 102.0.0-beta.1 → 102.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/dist/generated/google/protobuf/any.d.ts +180 -0
  2. package/dist/generated/google/protobuf/any.js +155 -0
  3. package/dist/generated/google/protobuf/any.js.map +1 -0
  4. package/dist/generated/google/protobuf/empty.d.ts +31 -0
  5. package/dist/generated/google/protobuf/empty.js +32 -0
  6. package/dist/generated/google/protobuf/empty.js.map +1 -0
  7. package/dist/generated/google/protobuf/timestamp.d.ts +155 -0
  8. package/dist/generated/google/protobuf/timestamp.js +136 -0
  9. package/dist/generated/google/protobuf/timestamp.js.map +1 -0
  10. package/dist/generated/packages/dht/protos/DhtRpc.client.d.ts +361 -0
  11. package/dist/generated/packages/dht/protos/DhtRpc.client.js +285 -0
  12. package/dist/generated/packages/dht/protos/DhtRpc.client.js.map +1 -0
  13. package/dist/generated/packages/dht/protos/DhtRpc.d.ts +999 -0
  14. package/dist/generated/packages/dht/protos/DhtRpc.js +677 -0
  15. package/dist/generated/packages/dht/protos/DhtRpc.js.map +1 -0
  16. package/dist/generated/packages/dht/protos/DhtRpc.server.d.ts +162 -0
  17. package/dist/generated/packages/dht/protos/DhtRpc.server.js +3 -0
  18. package/dist/generated/packages/dht/protos/DhtRpc.server.js.map +1 -0
  19. package/dist/generated/packages/proto-rpc/protos/ProtoRpc.d.ts +87 -0
  20. package/dist/generated/packages/proto-rpc/protos/ProtoRpc.js +66 -0
  21. package/dist/generated/packages/proto-rpc/protos/ProtoRpc.js.map +1 -0
  22. package/dist/package.json +7 -7
  23. package/package.json +7 -7
  24. package/eslint.config.mjs +0 -12
  25. package/src/connection/Connection.ts +0 -28
  26. package/src/connection/ConnectionLockRpcLocal.ts +0 -78
  27. package/src/connection/ConnectionLockRpcRemote.ts +0 -64
  28. package/src/connection/ConnectionLockStates.ts +0 -131
  29. package/src/connection/ConnectionManager.ts +0 -661
  30. package/src/connection/ConnectionsView.ts +0 -8
  31. package/src/connection/ConnectorFacade.ts +0 -217
  32. package/src/connection/Handshaker.ts +0 -209
  33. package/src/connection/IConnection.ts +0 -40
  34. package/src/connection/ManagedConnection.ts +0 -113
  35. package/src/connection/OutputBuffer.ts +0 -28
  36. package/src/connection/PendingConnection.ts +0 -68
  37. package/src/connection/connectivityChecker.ts +0 -108
  38. package/src/connection/connectivityRequestHandler.ts +0 -116
  39. package/src/connection/simulator/Simulator.ts +0 -369
  40. package/src/connection/simulator/SimulatorConnection.ts +0 -137
  41. package/src/connection/simulator/SimulatorConnector.ts +0 -98
  42. package/src/connection/simulator/SimulatorTransport.ts +0 -15
  43. package/src/connection/simulator/pings.ts +0 -42
  44. package/src/connection/webrtc/BrowserWebrtcConnection.ts +0 -242
  45. package/src/connection/webrtc/IWebrtcConnection.ts +0 -24
  46. package/src/connection/webrtc/NodeWebrtcConnection.ts +0 -245
  47. package/src/connection/webrtc/WebrtcConnector.ts +0 -234
  48. package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +0 -108
  49. package/src/connection/webrtc/WebrtcConnectorRpcRemote.ts +0 -60
  50. package/src/connection/webrtc/iceServerAsString.ts +0 -15
  51. package/src/connection/websocket/AbstractWebsocketClientConnection.ts +0 -122
  52. package/src/connection/websocket/AutoCertifierClientFacade.ts +0 -89
  53. package/src/connection/websocket/BrowserWebsocketClientConnection.ts +0 -44
  54. package/src/connection/websocket/NodeWebsocketClientConnection.ts +0 -39
  55. package/src/connection/websocket/WebsocketClientConnector.ts +0 -119
  56. package/src/connection/websocket/WebsocketClientConnectorRpcLocal.ts +0 -38
  57. package/src/connection/websocket/WebsocketClientConnectorRpcRemote.ts +0 -19
  58. package/src/connection/websocket/WebsocketServer.ts +0 -164
  59. package/src/connection/websocket/WebsocketServerConnection.ts +0 -109
  60. package/src/connection/websocket/WebsocketServerConnector.ts +0 -290
  61. package/src/dht/DhtNode.ts +0 -683
  62. package/src/dht/DhtNodeRpcLocal.ts +0 -84
  63. package/src/dht/DhtNodeRpcRemote.ts +0 -107
  64. package/src/dht/ExternalApiRpcLocal.ts +0 -58
  65. package/src/dht/ExternalApiRpcRemote.ts +0 -41
  66. package/src/dht/PeerManager.ts +0 -305
  67. package/src/dht/contact/Contact.ts +0 -19
  68. package/src/dht/contact/ContactList.ts +0 -43
  69. package/src/dht/contact/RandomContactList.ts +0 -56
  70. package/src/dht/contact/RingContactList.ts +0 -143
  71. package/src/dht/contact/RpcRemote.ts +0 -72
  72. package/src/dht/contact/SortedContactList.ts +0 -173
  73. package/src/dht/contact/getClosestNodes.ts +0 -24
  74. package/src/dht/contact/ringIdentifiers.ts +0 -62
  75. package/src/dht/discovery/DiscoverySession.ts +0 -129
  76. package/src/dht/discovery/PeerDiscovery.ts +0 -244
  77. package/src/dht/discovery/RingDiscoverySession.ts +0 -148
  78. package/src/dht/recursive-operation/RecursiveOperationManager.ts +0 -251
  79. package/src/dht/recursive-operation/RecursiveOperationRpcLocal.ts +0 -34
  80. package/src/dht/recursive-operation/RecursiveOperationRpcRemote.ts +0 -43
  81. package/src/dht/recursive-operation/RecursiveOperationSession.ts +0 -231
  82. package/src/dht/recursive-operation/RecursiveOperationSessionRpcLocal.ts +0 -35
  83. package/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.ts +0 -30
  84. package/src/dht/routing/DuplicateDetector.ts +0 -34
  85. package/src/dht/routing/Router.ts +0 -246
  86. package/src/dht/routing/RouterRpcLocal.ts +0 -78
  87. package/src/dht/routing/RouterRpcRemote.ts +0 -80
  88. package/src/dht/routing/RoutingSession.ts +0 -243
  89. package/src/dht/routing/RoutingTablesCache.ts +0 -60
  90. package/src/dht/routing/getPreviousPeer.ts +0 -6
  91. package/src/dht/store/LocalDataStore.ts +0 -84
  92. package/src/dht/store/StoreManager.ts +0 -170
  93. package/src/dht/store/StoreRpcLocal.ts +0 -89
  94. package/src/dht/store/StoreRpcRemote.ts +0 -32
  95. package/src/exports.ts +0 -33
  96. package/src/helpers/AddressTools.ts +0 -28
  97. package/src/helpers/Connectivity.ts +0 -19
  98. package/src/helpers/browser/isBrowserEnvironment.ts +0 -1
  99. package/src/helpers/browser/isBrowserEnvironment_override.ts +0 -3
  100. package/src/helpers/createPeerDescriptor.ts +0 -57
  101. package/src/helpers/createPeerDescriptorSignaturePayload.ts +0 -28
  102. package/src/helpers/debugHelpers.ts +0 -9
  103. package/src/helpers/errors.ts +0 -49
  104. package/src/helpers/offering.ts +0 -15
  105. package/src/helpers/protoClasses.ts +0 -57
  106. package/src/helpers/protoToString.ts +0 -21
  107. package/src/helpers/version.ts +0 -32
  108. package/src/identifiers.ts +0 -29
  109. package/src/rpc-protocol/DhtCallContext.ts +0 -14
  110. package/src/rpc-protocol/DhtRpcOptions.ts +0 -10
  111. package/src/transport/ITransport.ts +0 -37
  112. package/src/transport/ListeningRpcCommunicator.ts +0 -32
  113. package/src/transport/RoutingRpcCommunicator.ts +0 -66
  114. package/src/types/ServiceID.ts +0 -1
  115. package/src/types/textencoding.d.ts +0 -6
  116. package/test/benchmark/Find.test.ts +0 -72
  117. package/test/benchmark/KademliaCorrectness.test.ts +0 -114
  118. package/test/benchmark/RingCorrectness.test.ts +0 -157
  119. package/test/benchmark/SortedContactListBenchmark.test.ts +0 -108
  120. package/test/benchmark/WebsocketServerMemoryLeak.test.ts +0 -41
  121. package/test/benchmark/hybrid-network-simulation/RingContactList.test.ts +0 -71
  122. package/test/end-to-end/GeoIpLayer0.test.ts +0 -55
  123. package/test/end-to-end/Layer0-Layer1.test.ts +0 -93
  124. package/test/end-to-end/Layer0.test.ts +0 -76
  125. package/test/end-to-end/Layer0MixedConnectionTypes.test.ts +0 -110
  126. package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +0 -137
  127. package/test/end-to-end/Layer0Webrtc.test.ts +0 -85
  128. package/test/end-to-end/Layer1-Scale-WebSocket.test.ts +0 -82
  129. package/test/end-to-end/Layer1-Scale-Webrtc.test.ts +0 -76
  130. package/test/end-to-end/RecoveryFromFailedAutoCertification.test.ts +0 -52
  131. package/test/end-to-end/WebsocketConnectionRequest.test.ts +0 -69
  132. package/test/end-to-end/memory-leak.test.ts +0 -80
  133. package/test/integration/ConnectionLocking.test.ts +0 -192
  134. package/test/integration/ConnectionManager.test.ts +0 -528
  135. package/test/integration/ConnectivityChecking.test.ts +0 -53
  136. package/test/integration/DhtJoinPeerDiscovery.test.ts +0 -49
  137. package/test/integration/DhtNode.test.ts +0 -66
  138. package/test/integration/DhtNodeExternalAPI.test.ts +0 -48
  139. package/test/integration/DhtNodeRpcRemote.test.ts +0 -66
  140. package/test/integration/DhtRpc.test.ts +0 -121
  141. package/test/integration/Find.test.ts +0 -45
  142. package/test/integration/GeoIpConnectivityChecking.test.ts +0 -72
  143. package/test/integration/Layer1-scale.test.ts +0 -189
  144. package/test/integration/Mock-Layer1-Layer0.test.ts +0 -85
  145. package/test/integration/MultipleEntryPointJoining.test.ts +0 -105
  146. package/test/integration/ReplicateData.test.ts +0 -104
  147. package/test/integration/RouteMessage.test.ts +0 -230
  148. package/test/integration/RouterRpcRemote.test.ts +0 -77
  149. package/test/integration/SimultaneousConnections.test.ts +0 -316
  150. package/test/integration/Store.test.ts +0 -85
  151. package/test/integration/StoreAndDelete.test.ts +0 -77
  152. package/test/integration/StoreOnDhtWithThreeNodes.test.ts +0 -59
  153. package/test/integration/StoreOnDhtWithTwoNodes.test.ts +0 -51
  154. package/test/integration/StoreRpcRemote.test.ts +0 -54
  155. package/test/integration/WebrtcConnectionManagement.test.ts +0 -191
  156. package/test/integration/WebrtcConnectorRpc.test.ts +0 -125
  157. package/test/integration/Websocket.test.ts +0 -65
  158. package/test/integration/WebsocketClientConnectorRpc.test.ts +0 -69
  159. package/test/integration/WebsocketConnectionManagement.test.ts +0 -191
  160. package/test/integration/rpc-connections-over-webrtc.test.ts +0 -123
  161. package/test/kademlia-simulation/data/nodeids.json +0 -13002
  162. package/test/kademlia-simulation/data/orderedneighbors.json +0 -1001
  163. package/test/types/global.d.ts +0 -1
  164. package/test/unit/AddressTools.test.ts +0 -44
  165. package/test/unit/AutoCertifierClientFacade.test.ts +0 -58
  166. package/test/unit/ConnectionManager.test.ts +0 -65
  167. package/test/unit/ConnectivityHelpers.test.ts +0 -61
  168. package/test/unit/DiscoverySession.test.ts +0 -87
  169. package/test/unit/DuplicateDetector.test.ts +0 -31
  170. package/test/unit/Handshaker.test.ts +0 -169
  171. package/test/unit/ListeningRpcCommunicator.test.ts +0 -52
  172. package/test/unit/LocalDataStore.test.ts +0 -108
  173. package/test/unit/ManagedConnection.test.ts +0 -58
  174. package/test/unit/PeerManager.test.ts +0 -93
  175. package/test/unit/PendingConnection.test.ts +0 -57
  176. package/test/unit/ProtobufMessage.test.ts +0 -21
  177. package/test/unit/RandomContactList.test.ts +0 -58
  178. package/test/unit/RecursiveOperationManager.test.ts +0 -161
  179. package/test/unit/RecursiveOperationSession.test.ts +0 -68
  180. package/test/unit/Router.test.ts +0 -137
  181. package/test/unit/RoutingSession.test.ts +0 -86
  182. package/test/unit/SortedContactList.test.ts +0 -115
  183. package/test/unit/StoreManager.test.ts +0 -146
  184. package/test/unit/StoreRpcLocal.test.ts +0 -167
  185. package/test/unit/WebrtcConnection.test.ts +0 -29
  186. package/test/unit/WebrtcConnector.test.ts +0 -56
  187. package/test/unit/WebsocketClientConnector.test.ts +0 -101
  188. package/test/unit/WebsocketServer.test.ts +0 -66
  189. package/test/unit/WebsocketServerConnector.test.ts +0 -102
  190. package/test/unit/connectivityRequestHandler.test.ts +0 -104
  191. package/test/unit/createPeerDescriptor.test.ts +0 -69
  192. package/test/unit/customMatchers.test.ts +0 -34
  193. package/test/unit/getClosestNodes.test.ts +0 -30
  194. package/test/unit/version.test.ts +0 -18
  195. package/test/unit/webrtcReplaceInternalIpWithExternalIp.test.ts +0 -18
  196. package/test/utils/FakeConnectorFacade.ts +0 -41
  197. package/test/utils/FakeRpcCommunicator.ts +0 -23
  198. package/test/utils/FakeTransport.ts +0 -79
  199. package/test/utils/customMatchers.ts +0 -71
  200. package/test/utils/mock/MockConnection.ts +0 -26
  201. package/test/utils/mock/MockConnectionsView.ts +0 -18
  202. package/test/utils/mock/MockRouter.ts +0 -62
  203. package/test/utils/mock/MockRpcCommunicator.ts +0 -7
  204. package/test/utils/mock/MockTransport.ts +0 -26
  205. package/test/utils/mock/mockDataEntry.ts +0 -38
  206. package/test/utils/topology.ts +0 -79
  207. package/test/utils/utils.ts +0 -268
  208. package/tsconfig.browser.json +0 -17
  209. package/tsconfig.jest.json +0 -25
  210. package/tsconfig.json +0 -3
  211. package/tsconfig.node.json +0 -24
@@ -1,244 +0,0 @@
1
- import { Logger, scheduleAtInterval, setAbortableTimeout } from '@streamr/utils'
2
- import { ConnectionLocker } from '../../connection/ConnectionManager'
3
- import {
4
- DhtAddress,
5
- areEqualPeerDescriptors,
6
- randomDhtAddress,
7
- toDhtAddress,
8
- toNodeId,
9
- toDhtAddressRaw
10
- } from '../../identifiers'
11
- import { PeerDescriptor } from '../../../generated/packages/dht/protos/DhtRpc'
12
- import { ServiceID } from '../../types/ServiceID'
13
- import { DhtNodeRpcRemote } from '../DhtNodeRpcRemote'
14
- import { PeerManager } from '../PeerManager'
15
- import { getClosestNodes } from '../contact/getClosestNodes'
16
- import { RingIdRaw, getRingIdRawFromPeerDescriptor } from '../contact/ringIdentifiers'
17
- import { DiscoverySession } from './DiscoverySession'
18
- import { RingDiscoverySession } from './RingDiscoverySession'
19
- import { CONTROL_LAYER_NODE_SERVICE_ID } from '../DhtNode'
20
-
21
- interface PeerDiscoveryOptions {
22
- localPeerDescriptor: PeerDescriptor
23
- joinNoProgressLimit: number
24
- serviceId: ServiceID
25
- parallelism: number
26
- joinTimeout: number
27
- connectionLocker?: ConnectionLocker
28
- peerManager: PeerManager
29
- abortSignal: AbortSignal
30
- createDhtNodeRpcRemote: (peerDescriptor: PeerDescriptor) => DhtNodeRpcRemote
31
- }
32
-
33
- export const createDistantDhtAddress = (address: DhtAddress): DhtAddress => {
34
- const raw = toDhtAddressRaw(address)
35
- const flipped = raw.map((val) => ~val)
36
- return toDhtAddress(flipped)
37
- }
38
-
39
- const logger = new Logger(module)
40
-
41
- export class PeerDiscovery {
42
-
43
- private ongoingDiscoverySessions: Map<string, DiscoverySession> = new Map()
44
- private ongoingRingDiscoverySessions: Map<string, RingDiscoverySession> = new Map()
45
-
46
- private rejoinOngoing = false
47
- private joinCalled = false
48
- private recoveryIntervalStarted = false
49
- private readonly options: PeerDiscoveryOptions
50
-
51
- constructor(options: PeerDiscoveryOptions) {
52
- this.options = options
53
- }
54
-
55
- async joinDht(
56
- entryPoints: PeerDescriptor[],
57
- doAdditionalDistantPeerDiscovery = true,
58
- retry = true
59
- ): Promise<void> {
60
- const contactedPeers = new Set<DhtAddress>()
61
- const distantJoinOptions = doAdditionalDistantPeerDiscovery
62
- ? { enabled: true, contactedPeers: new Set<DhtAddress>() } : { enabled: false } as const
63
- await Promise.all(entryPoints.map((entryPoint) => this.joinThroughEntryPoint(
64
- entryPoint,
65
- contactedPeers,
66
- distantJoinOptions,
67
- retry
68
- )))
69
- }
70
-
71
- private async joinThroughEntryPoint(
72
- entryPointDescriptor: PeerDescriptor,
73
- // Note that this set is mutated by DiscoverySession
74
- contactedPeers: Set<DhtAddress>,
75
- additionalDistantJoin: { enabled: true, contactedPeers: Set<DhtAddress> } | { enabled: false },
76
- retry = true
77
- ): Promise<void> {
78
- if (this.isStopped()) {
79
- return
80
- }
81
- this.joinCalled = true
82
- logger.debug(
83
- `Joining ${this.options.serviceId === CONTROL_LAYER_NODE_SERVICE_ID
84
- ? 'The Streamr Network' : `Control Layer for ${this.options.serviceId}`}`
85
- + ` via entrypoint ${toNodeId(entryPointDescriptor)}`
86
- )
87
- if (areEqualPeerDescriptors(entryPointDescriptor, this.options.localPeerDescriptor)) {
88
- return
89
- }
90
- this.options.connectionLocker?.lockConnection(entryPointDescriptor, `${this.options.serviceId}::joinDht`)
91
- this.options.peerManager.addContact(entryPointDescriptor)
92
- const targetId = toNodeId(this.options.localPeerDescriptor)
93
- const sessions = [this.createSession(targetId, contactedPeers)]
94
- if (additionalDistantJoin.enabled) {
95
- sessions.push(this.createSession(createDistantDhtAddress(targetId), additionalDistantJoin.contactedPeers))
96
- }
97
- await this.runSessions(sessions, entryPointDescriptor, retry)
98
- this.options.connectionLocker?.unlockConnection(entryPointDescriptor, `${this.options.serviceId}::joinDht`)
99
-
100
- }
101
-
102
- async joinRing(): Promise<void> {
103
- const contactedPeers = new Set<DhtAddress>()
104
- const sessions = [this.createRingSession(getRingIdRawFromPeerDescriptor(this.options.localPeerDescriptor), contactedPeers)]
105
- await this.runRingSessions(sessions)
106
- }
107
-
108
- private createSession(targetId: DhtAddress, contactedPeers: Set<DhtAddress>): DiscoverySession {
109
- const sessionOptions = {
110
- targetId,
111
- parallelism: this.options.parallelism,
112
- noProgressLimit: this.options.joinNoProgressLimit,
113
- peerManager: this.options.peerManager,
114
- contactedPeers,
115
- abortSignal: this.options.abortSignal,
116
- createDhtNodeRpcRemote: this.options.createDhtNodeRpcRemote
117
- }
118
- return new DiscoverySession(sessionOptions)
119
- }
120
-
121
- private createRingSession(targetId: RingIdRaw, contactedPeers: Set<DhtAddress>): RingDiscoverySession {
122
- const sessionOptions = {
123
- targetId,
124
- parallelism: this.options.parallelism,
125
- noProgressLimit: this.options.joinNoProgressLimit,
126
- peerManager: this.options.peerManager,
127
- contactedPeers,
128
- abortSignal: this.options.abortSignal,
129
- createDhtNodeRpcRemote: this.options.createDhtNodeRpcRemote
130
- }
131
- return new RingDiscoverySession(sessionOptions)
132
- }
133
-
134
- private async runSessions(sessions: DiscoverySession[], entryPointDescriptor: PeerDescriptor, retry: boolean): Promise<void> {
135
- try {
136
- for (const session of sessions) {
137
- this.ongoingDiscoverySessions.set(session.id, session)
138
- await session.findClosestNodes(this.options.joinTimeout)
139
- }
140
- } catch (_e) {
141
- logger.debug(`DHT join on ${this.options.serviceId} timed out`)
142
- } finally {
143
- if (!this.isStopped()) {
144
- if (this.options.peerManager.getNeighborCount() === 0) {
145
- if (retry) {
146
- // TODO should we catch possible promise rejection?
147
- // TODO use options option or named constant?
148
- setAbortableTimeout(() => this.rejoinDht(entryPointDescriptor), 1000, this.options.abortSignal)
149
- }
150
- } else {
151
- await this.ensureRecoveryIntervalIsRunning()
152
- }
153
- }
154
- sessions.forEach((session) => this.ongoingDiscoverySessions.delete(session.id))
155
- }
156
- }
157
-
158
- private async runRingSessions(sessions: RingDiscoverySession[]): Promise<void> {
159
- try {
160
- for (const session of sessions) {
161
- this.ongoingRingDiscoverySessions.set(session.id, session)
162
- await session.findClosestNodes(this.options.joinTimeout)
163
- }
164
- } catch (_e) {
165
- logger.debug(`Ring join on ${this.options.serviceId} timed out`)
166
- } finally {
167
- sessions.forEach((session) => this.ongoingDiscoverySessions.delete(session.id))
168
- }
169
- }
170
-
171
- public async rejoinDht(
172
- entryPoint: PeerDescriptor,
173
- contactedPeers: Set<DhtAddress> = new Set(),
174
- distantJoinContactPeers: Set<DhtAddress> = new Set()
175
- ): Promise<void> {
176
- if (this.isStopped() || this.rejoinOngoing) {
177
- return
178
- }
179
- logger.debug(`Rejoining DHT ${this.options.serviceId}`)
180
- this.rejoinOngoing = true
181
- try {
182
- await this.joinThroughEntryPoint(entryPoint, contactedPeers, { enabled: true, contactedPeers: distantJoinContactPeers })
183
- logger.debug(`Rejoined DHT successfully ${this.options.serviceId}!`)
184
- } catch {
185
- logger.warn(`Rejoining DHT ${this.options.serviceId} failed`)
186
- if (!this.isStopped()) {
187
- // TODO should we catch possible promise rejection?
188
- // TODO use options option or named constant?
189
- setAbortableTimeout(() => this.rejoinDht(entryPoint), 5000, this.options.abortSignal)
190
- }
191
- } finally {
192
- this.rejoinOngoing = false
193
- }
194
- }
195
-
196
- private async ensureRecoveryIntervalIsRunning(): Promise<void> {
197
- if (!this.recoveryIntervalStarted) {
198
- this.recoveryIntervalStarted = true
199
- // TODO use options option or named constant?
200
- await scheduleAtInterval(() => this.fetchClosestAndRandomNeighbors(), 60000, true, this.options.abortSignal)
201
- }
202
- }
203
-
204
- private async fetchClosestAndRandomNeighbors(): Promise<void> {
205
- if (this.isStopped()) {
206
- return
207
- }
208
- const localNodeId = toNodeId(this.options.localPeerDescriptor)
209
- const nodes = this.getClosestNeighbors(localNodeId, this.options.parallelism)
210
- const randomNodes = this.getClosestNeighbors(randomDhtAddress(), 1)
211
- await Promise.allSettled([
212
- ...nodes.map(async (node: PeerDescriptor) => {
213
- const remote = this.options.createDhtNodeRpcRemote(node)
214
- const contacts = await remote.getClosestPeers(localNodeId)
215
- for (const contact of contacts) {
216
- this.options.peerManager.addContact(contact)
217
- }
218
- }),
219
- ...randomNodes.map(async (node: PeerDescriptor) => {
220
- const remote = this.options.createDhtNodeRpcRemote(node)
221
- const contacts = await remote.getClosestPeers(randomDhtAddress())
222
- for (const contact of contacts) {
223
- this.options.peerManager.addContact(contact)
224
- }
225
- })
226
- ])
227
- }
228
-
229
- private getClosestNeighbors(referenceId: DhtAddress, maxCount: number): PeerDescriptor[] {
230
- return getClosestNodes(referenceId, this.options.peerManager.getNeighbors().map((n) => n.getPeerDescriptor()), { maxCount })
231
- }
232
-
233
- public isJoinOngoing(): boolean {
234
- return !this.joinCalled ? true : this.ongoingDiscoverySessions.size > 0
235
- }
236
-
237
- public isJoinCalled(): boolean {
238
- return this.joinCalled
239
- }
240
-
241
- private isStopped() {
242
- return this.options.abortSignal.aborted
243
- }
244
- }
@@ -1,148 +0,0 @@
1
- import { Gate, Logger, withTimeout } from '@streamr/utils'
2
- import { v4 } from 'uuid'
3
- import { DhtAddress, toNodeId } from '../../identifiers'
4
- import { PeerDescriptor } from '../../../generated/packages/dht/protos/DhtRpc'
5
- import { DhtNodeRpcRemote } from '../DhtNodeRpcRemote'
6
- import { PeerManager } from '../PeerManager'
7
- import { RingContacts } from '../contact/RingContactList'
8
- import { RingId, RingIdRaw, getLeftDistance, getRingIdFromPeerDescriptor, getRingIdFromRaw } from '../contact/ringIdentifiers'
9
-
10
- const logger = new Logger(module)
11
-
12
- interface RingDiscoverySessionOptions {
13
- targetId: RingIdRaw
14
- parallelism: number
15
- noProgressLimit: number
16
- peerManager: PeerManager
17
- // Note that contacted peers will be mutated by the DiscoverySession or other parallel sessions
18
- contactedPeers: Set<DhtAddress>
19
- abortSignal: AbortSignal
20
- }
21
-
22
- export class RingDiscoverySession {
23
-
24
- public readonly id = v4()
25
- private noProgressCounter = 0
26
- private ongoingRequests: Set<DhtAddress> = new Set()
27
- private doneGate = new Gate(false)
28
- private readonly options: RingDiscoverySessionOptions
29
- private numContactedPeers = 0
30
- private targetIdAsRingId: RingId
31
-
32
- constructor(options: RingDiscoverySessionOptions) {
33
- this.options = options
34
- this.targetIdAsRingId = getRingIdFromRaw(this.options.targetId)
35
- }
36
-
37
- private addContacts(contacts: PeerDescriptor[]): void {
38
- if (this.options.abortSignal.aborted || this.doneGate.isOpen()) {
39
- return
40
- }
41
- for (const contact of contacts) {
42
- this.options.peerManager.addContact(contact)
43
- }
44
- }
45
-
46
- private async fetchClosestContactsFromRemote(contact: DhtNodeRpcRemote): Promise<RingContacts> {
47
- if (this.options.abortSignal.aborted || this.doneGate.isOpen()) {
48
- return { left: [], right: [] }
49
- }
50
- logger.trace(`Getting closest ring peers from contact: ${toNodeId(contact.getPeerDescriptor())}`)
51
- this.numContactedPeers++
52
- this.options.contactedPeers.add(contact.getNodeId())
53
- const returnedContacts = await contact.getClosestRingPeers(this.options.targetId)
54
- this.options.peerManager.setContactActive(contact.getNodeId())
55
- return returnedContacts
56
- }
57
-
58
- private onRequestSucceeded(nodeId: DhtAddress, contacts: RingContacts) {
59
- if (!this.ongoingRequests.has(nodeId)) {
60
- return
61
- }
62
- this.ongoingRequests.delete(nodeId)
63
- const oldClosestContacts = this.options.peerManager.getClosestRingContactsTo(this.options.targetId, 1)
64
- const oldClosestLeftDistance = getLeftDistance(
65
- this.targetIdAsRingId,
66
- getRingIdFromPeerDescriptor(oldClosestContacts.left[0].getPeerDescriptor())
67
- )
68
- const oldClosestRightDistance = getLeftDistance(
69
- this.targetIdAsRingId,
70
- getRingIdFromPeerDescriptor(oldClosestContacts.right[0].getPeerDescriptor())
71
- )
72
- this.addContacts(contacts.left.concat(contacts.right))
73
- const newClosestContacts = this.options.peerManager.getClosestRingContactsTo(this.options.targetId, 1)
74
- const newClosestLeftDistance = getLeftDistance(this.targetIdAsRingId,
75
- getRingIdFromPeerDescriptor(newClosestContacts.left[0].getPeerDescriptor()))
76
- const newClosestRightDistance = getLeftDistance(this.targetIdAsRingId,
77
- getRingIdFromPeerDescriptor(newClosestContacts.right[0].getPeerDescriptor()))
78
- if (newClosestLeftDistance >= oldClosestLeftDistance && newClosestRightDistance >= oldClosestRightDistance) {
79
- this.noProgressCounter++
80
- }
81
- }
82
-
83
- private onRequestFailed(peer: DhtNodeRpcRemote) {
84
- if (!this.ongoingRequests.has(peer.getNodeId())) {
85
- return
86
- }
87
- this.ongoingRequests.delete(peer.getNodeId())
88
- this.options.peerManager.removeContact(peer.getNodeId())
89
- }
90
-
91
- private findMoreContacts(): void {
92
- if (this.options.abortSignal.aborted || this.doneGate.isOpen()) {
93
- return
94
- }
95
- const uncontacted = this.options.peerManager.getClosestRingContactsTo(
96
- this.options.targetId,
97
- this.options.parallelism,
98
- this.options.contactedPeers
99
- )
100
- if ((uncontacted.left.length === 0 && uncontacted.right.length === 0)
101
- || this.noProgressCounter >= this.options.noProgressLimit) {
102
- this.doneGate.open()
103
- return
104
- }
105
- // ask from both sides equally
106
- const merged = []
107
- const alreadyInMerged: Set<DhtAddress> = new Set()
108
- const length = Math.max(uncontacted.left.length, uncontacted.right.length)
109
- for (let i = 0; i < length; i++) {
110
- if (i < uncontacted.left.length) {
111
- if (!alreadyInMerged.has(uncontacted.left[i].getNodeId())) {
112
- merged.push(uncontacted.left[i])
113
- alreadyInMerged.add(uncontacted.left[i].getNodeId())
114
- }
115
- }
116
- if (i < uncontacted.right.length) {
117
- if (!alreadyInMerged.has(uncontacted.right[i].getNodeId())) {
118
- merged.push(uncontacted.right[i])
119
- alreadyInMerged.add(uncontacted.right[i].getNodeId())
120
- }
121
- }
122
- }
123
-
124
- for (const nextPeer of merged) {
125
- if (this.ongoingRequests.size >= this.options.parallelism) {
126
- break
127
- }
128
- this.ongoingRequests.add(nextPeer.getNodeId())
129
- // eslint-disable-next-line promise/catch-or-return
130
- this.fetchClosestContactsFromRemote(nextPeer)
131
- .then((contacts) => this.onRequestSucceeded(nextPeer.getNodeId(), contacts))
132
- .catch(() => this.onRequestFailed(nextPeer))
133
- .finally(() => {
134
- this.findMoreContacts()
135
- })
136
- }
137
- }
138
-
139
- public async findClosestNodes(timeout: number): Promise<void> {
140
- if (this.options.peerManager.getNearbyContactCount(this.options.contactedPeers) === 0) {
141
- return
142
- }
143
- setImmediate(() => {
144
- this.findMoreContacts()
145
- })
146
- await withTimeout(this.doneGate.waitUntilOpen(), timeout, 'discovery session timed out', this.options.abortSignal)
147
- }
148
- }
@@ -1,251 +0,0 @@
1
- import {
2
- DataEntry,
3
- PeerDescriptor,
4
- RecursiveOperation,
5
- RecursiveOperationRequest,
6
- RouteMessageAck,
7
- RouteMessageError,
8
- RouteMessageWrapper
9
- } from '../../../generated/packages/dht/protos/DhtRpc'
10
- import { Router } from '../routing/Router'
11
- import { RoutingMode } from '../routing/RoutingSession'
12
- import { Logger, areEqualBinaries, runAndWaitForEvents3, wait } from '@streamr/utils'
13
- import { RoutingRpcCommunicator } from '../../transport/RoutingRpcCommunicator'
14
- import { RecursiveOperationSessionRpcRemote } from './RecursiveOperationSessionRpcRemote'
15
- import { RECURSIVE_OPERATION_TIMEOUT, RecursiveOperationSession, RecursiveOperationSessionEvents } from './RecursiveOperationSession'
16
- import { DhtNodeRpcRemote } from '../DhtNodeRpcRemote'
17
- import { ITransport } from '../../transport/ITransport'
18
- import { LocalDataStore } from '../store/LocalDataStore'
19
- import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicator'
20
- import { RecursiveOperationSessionRpcClient } from '../../../generated/packages/dht/protos/DhtRpc.client'
21
- import { SortedContactList } from '../contact/SortedContactList'
22
- import { getPreviousPeer } from '../routing/getPreviousPeer'
23
- import { createRouteMessageAck } from '../routing/RouterRpcLocal'
24
- import { ServiceID } from '../../types/ServiceID'
25
- import { RecursiveOperationRpcLocal } from './RecursiveOperationRpcLocal'
26
- import { DhtAddress, areEqualPeerDescriptors, toDhtAddress, toNodeId, toDhtAddressRaw } from '../../identifiers'
27
- import { getDistance } from '../PeerManager'
28
- import { ConnectionsView } from '../../exports'
29
-
30
- interface RecursiveOperationManagerOptions {
31
- rpcCommunicator: RoutingRpcCommunicator
32
- sessionTransport: ITransport
33
- router: Router
34
- connectionsView: ConnectionsView
35
- localPeerDescriptor: PeerDescriptor
36
- serviceId: ServiceID
37
- localDataStore: LocalDataStore
38
- addContact: (contact: PeerDescriptor) => void
39
- createDhtNodeRpcRemote: (peerDescriptor: PeerDescriptor) => DhtNodeRpcRemote
40
- }
41
-
42
- export interface RecursiveOperationResult { closestNodes: PeerDescriptor[], dataEntries?: DataEntry[] }
43
-
44
- const logger = new Logger(module)
45
-
46
- export class RecursiveOperationManager {
47
-
48
- private ongoingSessions: Map<string, RecursiveOperationSession> = new Map()
49
- private stopped = false
50
- private readonly options: RecursiveOperationManagerOptions
51
-
52
- constructor(options: RecursiveOperationManagerOptions) {
53
- this.options = options
54
- this.registerLocalRpcMethods()
55
- }
56
-
57
- private registerLocalRpcMethods() {
58
- const rpcLocal = new RecursiveOperationRpcLocal({
59
- doRouteRequest: (routedMessage: RouteMessageWrapper) => this.doRouteRequest(routedMessage),
60
- addContact: (contact: PeerDescriptor) => this.options.addContact(contact),
61
- isMostLikelyDuplicate: (requestId: string) => this.options.router.isMostLikelyDuplicate(requestId),
62
- addToDuplicateDetector: (requestId: string) => this.options.router.addToDuplicateDetector(requestId)
63
- })
64
- this.options.rpcCommunicator.registerRpcMethod(
65
- RouteMessageWrapper,
66
- RouteMessageAck,
67
- 'routeRequest',
68
- async (routedMessage: RouteMessageWrapper) => {
69
- if (this.stopped) {
70
- return createRouteMessageAck(routedMessage, RouteMessageError.STOPPED)
71
- } else {
72
- return rpcLocal.routeRequest(routedMessage)
73
- }
74
- }
75
- )
76
- }
77
-
78
- public async execute(
79
- targetId: DhtAddress,
80
- operation: RecursiveOperation,
81
- excludedPeer?: DhtAddress,
82
- waitForCompletion = true
83
- ): Promise<RecursiveOperationResult> {
84
- if (this.stopped) {
85
- return { closestNodes: [] }
86
- }
87
- const session = new RecursiveOperationSession({
88
- transport: this.options.sessionTransport,
89
- targetId,
90
- localPeerDescriptor: this.options.localPeerDescriptor,
91
- // TODO use options option or named constant?
92
- waitedRoutingPathCompletions: this.options.connectionsView.getConnectionCount() > 1 ? 2 : 1,
93
- operation,
94
- // TODO would it make sense to give excludedPeer as one of the fields RecursiveOperationSession?
95
- doRouteRequest: (routedMessage: RouteMessageWrapper) => {
96
- return this.doRouteRequest(routedMessage, excludedPeer)
97
- }
98
- })
99
- if (this.options.connectionsView.getConnectionCount() === 0) {
100
- const dataEntries = Array.from(this.options.localDataStore.values(targetId))
101
- session.onResponseReceived(
102
- toNodeId(this.options.localPeerDescriptor),
103
- [this.options.localPeerDescriptor],
104
- [this.options.localPeerDescriptor],
105
- dataEntries,
106
- true
107
- )
108
- return session.getResults()
109
- }
110
- this.ongoingSessions.set(session.getId(), session)
111
- if (waitForCompletion === true) {
112
- try {
113
- await runAndWaitForEvents3<RecursiveOperationSessionEvents>(
114
- [() => session.start(this.options.serviceId)],
115
- [[session, 'completed']],
116
- // TODO use options option or named constant?
117
- RECURSIVE_OPERATION_TIMEOUT
118
- )
119
- } catch (err) {
120
- logger.debug('start failed', { err })
121
- }
122
- } else {
123
- session.start(this.options.serviceId)
124
- // Wait for delete operation to be sent out by the router
125
- // TODO: Add a feature to wait for the router to pass the message?
126
- await wait(50)
127
- }
128
- if (operation === RecursiveOperation.FETCH_DATA) {
129
- const dataEntries = Array.from(this.options.localDataStore.values(targetId))
130
- if (dataEntries.length > 0) {
131
- this.sendResponse([this.options.localPeerDescriptor], this.options.localPeerDescriptor, session.getId(), [], dataEntries, true)
132
- }
133
- } else if (operation === RecursiveOperation.DELETE_DATA) {
134
- this.options.localDataStore.markAsDeleted(targetId, toNodeId(this.options.localPeerDescriptor))
135
- }
136
- this.ongoingSessions.delete(session.getId())
137
- session.stop()
138
- return session.getResults()
139
- }
140
-
141
- private sendResponse(
142
- routingPath: PeerDescriptor[],
143
- targetPeerDescriptor: PeerDescriptor,
144
- serviceId: ServiceID,
145
- closestConnectedNodes: PeerDescriptor[],
146
- dataEntries: DataEntry[],
147
- noCloserNodesFound: boolean = false
148
- ): void {
149
- const isOwnNode = areEqualPeerDescriptors(this.options.localPeerDescriptor, targetPeerDescriptor)
150
- if (isOwnNode && this.ongoingSessions.has(serviceId)) {
151
- this.ongoingSessions.get(serviceId)!
152
- .onResponseReceived(
153
- toNodeId(this.options.localPeerDescriptor),
154
- routingPath,
155
- closestConnectedNodes,
156
- dataEntries,
157
- noCloserNodesFound
158
- )
159
- } else {
160
- // TODO use options option or named constant?
161
- const remoteCommunicator = new ListeningRpcCommunicator(
162
- serviceId,
163
- this.options.sessionTransport,
164
- { rpcRequestTimeout: RECURSIVE_OPERATION_TIMEOUT }
165
- )
166
- const rpcRemote = new RecursiveOperationSessionRpcRemote(
167
- this.options.localPeerDescriptor,
168
- targetPeerDescriptor,
169
- remoteCommunicator,
170
- RecursiveOperationSessionRpcClient,
171
- // TODO use options option or named constant?
172
- 10000
173
- )
174
- rpcRemote.sendResponse(routingPath, closestConnectedNodes, dataEntries, noCloserNodesFound)
175
- remoteCommunicator.destroy()
176
- }
177
- }
178
-
179
- private doRouteRequest(routedMessage: RouteMessageWrapper, excludedPeer?: DhtAddress): RouteMessageAck {
180
- if (this.stopped) {
181
- return createRouteMessageAck(routedMessage, RouteMessageError.STOPPED)
182
- }
183
- const targetId = toDhtAddress(routedMessage.target)
184
- const request = (routedMessage.message!.body as { recursiveOperationRequest: RecursiveOperationRequest }).recursiveOperationRequest
185
- // TODO use options option or named constant?
186
- const closestConnectedNodes = this.getClosestConnectedNodes(targetId, 5)
187
- const dataEntries = (request.operation === RecursiveOperation.FETCH_DATA)
188
- ? Array.from(this.options.localDataStore.values(targetId))
189
- : []
190
- if (request.operation === RecursiveOperation.DELETE_DATA) {
191
- this.options.localDataStore.markAsDeleted(targetId, toNodeId(routedMessage.sourcePeer!))
192
- }
193
- if (areEqualBinaries(this.options.localPeerDescriptor.nodeId, routedMessage.target)) {
194
- // TODO this is also very similar case to what we do at line 255, could simplify the code paths?
195
- this.sendResponse(
196
- routedMessage.routingPath,
197
- routedMessage.sourcePeer!,
198
- request.sessionId,
199
- closestConnectedNodes,
200
- dataEntries,
201
- true
202
- )
203
- return createRouteMessageAck(routedMessage)
204
- } else {
205
- const ack = this.options.router.doRouteMessage(routedMessage, RoutingMode.RECURSIVE, excludedPeer)
206
- if ((ack.error === undefined) || (ack.error === RouteMessageError.NO_TARGETS)) {
207
- const noCloserContactsFound = (ack.error === RouteMessageError.NO_TARGETS) ||
208
- (
209
- closestConnectedNodes.length > 0
210
- && getPreviousPeer(routedMessage)
211
- && !this.isPeerCloserToIdThanSelf(closestConnectedNodes[0], targetId)
212
- )
213
- this.sendResponse(
214
- routedMessage.routingPath,
215
- routedMessage.sourcePeer!,
216
- request.sessionId,
217
- closestConnectedNodes,
218
- dataEntries,
219
- noCloserContactsFound
220
- )
221
- }
222
- return ack
223
- }
224
- }
225
-
226
- private getClosestConnectedNodes(referenceId: DhtAddress, limit: number): PeerDescriptor[] {
227
- const connectedNodes = this.options.connectionsView.getConnections().map((c) => this.options.createDhtNodeRpcRemote(c))
228
- const sorted = new SortedContactList<DhtNodeRpcRemote>({
229
- referenceId,
230
- maxSize: limit,
231
- allowToContainReferenceId: true
232
- })
233
- sorted.addContacts(connectedNodes)
234
- return sorted.getClosestContacts(limit).map((peer) => peer.getPeerDescriptor())
235
- }
236
-
237
- private isPeerCloserToIdThanSelf(peer: PeerDescriptor, nodeIdOrDataKey: DhtAddress): boolean {
238
- const nodeIdOrDataKeyRaw = toDhtAddressRaw(nodeIdOrDataKey)
239
- const distance1 = getDistance(peer.nodeId, nodeIdOrDataKeyRaw)
240
- const distance2 = getDistance(this.options.localPeerDescriptor.nodeId, nodeIdOrDataKeyRaw)
241
- return distance1 < distance2
242
- }
243
-
244
- public stop(): void {
245
- this.stopped = true
246
- this.ongoingSessions.forEach((session, _id) => {
247
- session.stop()
248
- })
249
- this.ongoingSessions.clear()
250
- }
251
- }
@@ -1,34 +0,0 @@
1
- import { Logger } from '@streamr/utils'
2
- import { PeerDescriptor, RouteMessageAck, RouteMessageError, RouteMessageWrapper } from '../../../generated/packages/dht/protos/DhtRpc'
3
- import { IRecursiveOperationRpc } from '../../../generated/packages/dht/protos/DhtRpc.server'
4
- import { createRouteMessageAck } from '../routing/RouterRpcLocal'
5
- import { getPreviousPeer } from '../routing/getPreviousPeer'
6
- import { toNodeId } from '../../identifiers'
7
-
8
- const logger = new Logger(module)
9
-
10
- interface RecursiveOperationRpcLocalOptions {
11
- doRouteRequest: (routedMessage: RouteMessageWrapper) => RouteMessageAck
12
- addContact: (contact: PeerDescriptor, setActive?: boolean) => void
13
- isMostLikelyDuplicate: (requestId: string) => boolean
14
- addToDuplicateDetector: (requestId: string) => void
15
- }
16
-
17
- export class RecursiveOperationRpcLocal implements IRecursiveOperationRpc {
18
-
19
- private readonly options: RecursiveOperationRpcLocalOptions
20
-
21
- constructor(options: RecursiveOperationRpcLocalOptions) {
22
- this.options = options
23
- }
24
-
25
- async routeRequest(routedMessage: RouteMessageWrapper): Promise<RouteMessageAck> {
26
- if (this.options.isMostLikelyDuplicate(routedMessage.requestId)) {
27
- return createRouteMessageAck(routedMessage, RouteMessageError.DUPLICATE)
28
- }
29
- const remoteNodeId = toNodeId(getPreviousPeer(routedMessage) ?? routedMessage.sourcePeer!)
30
- logger.trace(`Received routeRequest call from ${remoteNodeId}`)
31
- this.options.addToDuplicateDetector(routedMessage.requestId)
32
- return this.options.doRouteRequest(routedMessage)
33
- }
34
- }