@streamr/dht 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 (210) 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/src/connection/Connection.ts +0 -28
  25. package/src/connection/ConnectionLockRpcLocal.ts +0 -78
  26. package/src/connection/ConnectionLockRpcRemote.ts +0 -64
  27. package/src/connection/ConnectionLockStates.ts +0 -131
  28. package/src/connection/ConnectionManager.ts +0 -661
  29. package/src/connection/ConnectionsView.ts +0 -8
  30. package/src/connection/ConnectorFacade.ts +0 -217
  31. package/src/connection/Handshaker.ts +0 -209
  32. package/src/connection/IConnection.ts +0 -40
  33. package/src/connection/ManagedConnection.ts +0 -113
  34. package/src/connection/OutputBuffer.ts +0 -28
  35. package/src/connection/PendingConnection.ts +0 -68
  36. package/src/connection/connectivityChecker.ts +0 -108
  37. package/src/connection/connectivityRequestHandler.ts +0 -116
  38. package/src/connection/simulator/Simulator.ts +0 -369
  39. package/src/connection/simulator/SimulatorConnection.ts +0 -137
  40. package/src/connection/simulator/SimulatorConnector.ts +0 -98
  41. package/src/connection/simulator/SimulatorTransport.ts +0 -15
  42. package/src/connection/simulator/pings.ts +0 -42
  43. package/src/connection/webrtc/BrowserWebrtcConnection.ts +0 -242
  44. package/src/connection/webrtc/IWebrtcConnection.ts +0 -24
  45. package/src/connection/webrtc/NodeWebrtcConnection.ts +0 -245
  46. package/src/connection/webrtc/WebrtcConnector.ts +0 -234
  47. package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +0 -108
  48. package/src/connection/webrtc/WebrtcConnectorRpcRemote.ts +0 -60
  49. package/src/connection/webrtc/iceServerAsString.ts +0 -15
  50. package/src/connection/websocket/AbstractWebsocketClientConnection.ts +0 -122
  51. package/src/connection/websocket/AutoCertifierClientFacade.ts +0 -89
  52. package/src/connection/websocket/BrowserWebsocketClientConnection.ts +0 -44
  53. package/src/connection/websocket/NodeWebsocketClientConnection.ts +0 -39
  54. package/src/connection/websocket/WebsocketClientConnector.ts +0 -119
  55. package/src/connection/websocket/WebsocketClientConnectorRpcLocal.ts +0 -38
  56. package/src/connection/websocket/WebsocketClientConnectorRpcRemote.ts +0 -19
  57. package/src/connection/websocket/WebsocketServer.ts +0 -164
  58. package/src/connection/websocket/WebsocketServerConnection.ts +0 -109
  59. package/src/connection/websocket/WebsocketServerConnector.ts +0 -290
  60. package/src/dht/DhtNode.ts +0 -683
  61. package/src/dht/DhtNodeRpcLocal.ts +0 -84
  62. package/src/dht/DhtNodeRpcRemote.ts +0 -107
  63. package/src/dht/ExternalApiRpcLocal.ts +0 -58
  64. package/src/dht/ExternalApiRpcRemote.ts +0 -41
  65. package/src/dht/PeerManager.ts +0 -305
  66. package/src/dht/contact/Contact.ts +0 -19
  67. package/src/dht/contact/ContactList.ts +0 -43
  68. package/src/dht/contact/RandomContactList.ts +0 -56
  69. package/src/dht/contact/RingContactList.ts +0 -143
  70. package/src/dht/contact/RpcRemote.ts +0 -72
  71. package/src/dht/contact/SortedContactList.ts +0 -173
  72. package/src/dht/contact/getClosestNodes.ts +0 -24
  73. package/src/dht/contact/ringIdentifiers.ts +0 -62
  74. package/src/dht/discovery/DiscoverySession.ts +0 -129
  75. package/src/dht/discovery/PeerDiscovery.ts +0 -244
  76. package/src/dht/discovery/RingDiscoverySession.ts +0 -148
  77. package/src/dht/recursive-operation/RecursiveOperationManager.ts +0 -251
  78. package/src/dht/recursive-operation/RecursiveOperationRpcLocal.ts +0 -34
  79. package/src/dht/recursive-operation/RecursiveOperationRpcRemote.ts +0 -43
  80. package/src/dht/recursive-operation/RecursiveOperationSession.ts +0 -231
  81. package/src/dht/recursive-operation/RecursiveOperationSessionRpcLocal.ts +0 -35
  82. package/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.ts +0 -30
  83. package/src/dht/routing/DuplicateDetector.ts +0 -34
  84. package/src/dht/routing/Router.ts +0 -246
  85. package/src/dht/routing/RouterRpcLocal.ts +0 -78
  86. package/src/dht/routing/RouterRpcRemote.ts +0 -80
  87. package/src/dht/routing/RoutingSession.ts +0 -243
  88. package/src/dht/routing/RoutingTablesCache.ts +0 -60
  89. package/src/dht/routing/getPreviousPeer.ts +0 -6
  90. package/src/dht/store/LocalDataStore.ts +0 -84
  91. package/src/dht/store/StoreManager.ts +0 -170
  92. package/src/dht/store/StoreRpcLocal.ts +0 -89
  93. package/src/dht/store/StoreRpcRemote.ts +0 -32
  94. package/src/exports.ts +0 -33
  95. package/src/helpers/AddressTools.ts +0 -28
  96. package/src/helpers/Connectivity.ts +0 -19
  97. package/src/helpers/browser/isBrowserEnvironment.ts +0 -1
  98. package/src/helpers/browser/isBrowserEnvironment_override.ts +0 -3
  99. package/src/helpers/createPeerDescriptor.ts +0 -57
  100. package/src/helpers/createPeerDescriptorSignaturePayload.ts +0 -28
  101. package/src/helpers/debugHelpers.ts +0 -9
  102. package/src/helpers/errors.ts +0 -49
  103. package/src/helpers/offering.ts +0 -15
  104. package/src/helpers/protoClasses.ts +0 -57
  105. package/src/helpers/protoToString.ts +0 -21
  106. package/src/helpers/version.ts +0 -32
  107. package/src/identifiers.ts +0 -29
  108. package/src/rpc-protocol/DhtCallContext.ts +0 -14
  109. package/src/rpc-protocol/DhtRpcOptions.ts +0 -10
  110. package/src/transport/ITransport.ts +0 -37
  111. package/src/transport/ListeningRpcCommunicator.ts +0 -32
  112. package/src/transport/RoutingRpcCommunicator.ts +0 -66
  113. package/src/types/ServiceID.ts +0 -1
  114. package/src/types/textencoding.d.ts +0 -6
  115. package/test/benchmark/Find.test.ts +0 -72
  116. package/test/benchmark/KademliaCorrectness.test.ts +0 -114
  117. package/test/benchmark/RingCorrectness.test.ts +0 -157
  118. package/test/benchmark/SortedContactListBenchmark.test.ts +0 -108
  119. package/test/benchmark/WebsocketServerMemoryLeak.test.ts +0 -41
  120. package/test/benchmark/hybrid-network-simulation/RingContactList.test.ts +0 -71
  121. package/test/end-to-end/GeoIpLayer0.test.ts +0 -55
  122. package/test/end-to-end/Layer0-Layer1.test.ts +0 -93
  123. package/test/end-to-end/Layer0.test.ts +0 -76
  124. package/test/end-to-end/Layer0MixedConnectionTypes.test.ts +0 -110
  125. package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +0 -137
  126. package/test/end-to-end/Layer0Webrtc.test.ts +0 -85
  127. package/test/end-to-end/Layer1-Scale-WebSocket.test.ts +0 -82
  128. package/test/end-to-end/Layer1-Scale-Webrtc.test.ts +0 -76
  129. package/test/end-to-end/RecoveryFromFailedAutoCertification.test.ts +0 -52
  130. package/test/end-to-end/WebsocketConnectionRequest.test.ts +0 -69
  131. package/test/end-to-end/memory-leak.test.ts +0 -80
  132. package/test/integration/ConnectionLocking.test.ts +0 -192
  133. package/test/integration/ConnectionManager.test.ts +0 -528
  134. package/test/integration/ConnectivityChecking.test.ts +0 -53
  135. package/test/integration/DhtJoinPeerDiscovery.test.ts +0 -49
  136. package/test/integration/DhtNode.test.ts +0 -66
  137. package/test/integration/DhtNodeExternalAPI.test.ts +0 -48
  138. package/test/integration/DhtNodeRpcRemote.test.ts +0 -66
  139. package/test/integration/DhtRpc.test.ts +0 -121
  140. package/test/integration/Find.test.ts +0 -45
  141. package/test/integration/GeoIpConnectivityChecking.test.ts +0 -72
  142. package/test/integration/Layer1-scale.test.ts +0 -189
  143. package/test/integration/Mock-Layer1-Layer0.test.ts +0 -85
  144. package/test/integration/MultipleEntryPointJoining.test.ts +0 -105
  145. package/test/integration/ReplicateData.test.ts +0 -104
  146. package/test/integration/RouteMessage.test.ts +0 -230
  147. package/test/integration/RouterRpcRemote.test.ts +0 -77
  148. package/test/integration/SimultaneousConnections.test.ts +0 -316
  149. package/test/integration/Store.test.ts +0 -85
  150. package/test/integration/StoreAndDelete.test.ts +0 -77
  151. package/test/integration/StoreOnDhtWithThreeNodes.test.ts +0 -59
  152. package/test/integration/StoreOnDhtWithTwoNodes.test.ts +0 -51
  153. package/test/integration/StoreRpcRemote.test.ts +0 -54
  154. package/test/integration/WebrtcConnectionManagement.test.ts +0 -191
  155. package/test/integration/WebrtcConnectorRpc.test.ts +0 -125
  156. package/test/integration/Websocket.test.ts +0 -65
  157. package/test/integration/WebsocketClientConnectorRpc.test.ts +0 -69
  158. package/test/integration/WebsocketConnectionManagement.test.ts +0 -191
  159. package/test/integration/rpc-connections-over-webrtc.test.ts +0 -123
  160. package/test/kademlia-simulation/data/nodeids.json +0 -13002
  161. package/test/kademlia-simulation/data/orderedneighbors.json +0 -1001
  162. package/test/types/global.d.ts +0 -1
  163. package/test/unit/AddressTools.test.ts +0 -44
  164. package/test/unit/AutoCertifierClientFacade.test.ts +0 -58
  165. package/test/unit/ConnectionManager.test.ts +0 -65
  166. package/test/unit/ConnectivityHelpers.test.ts +0 -61
  167. package/test/unit/DiscoverySession.test.ts +0 -87
  168. package/test/unit/DuplicateDetector.test.ts +0 -31
  169. package/test/unit/Handshaker.test.ts +0 -169
  170. package/test/unit/ListeningRpcCommunicator.test.ts +0 -52
  171. package/test/unit/LocalDataStore.test.ts +0 -108
  172. package/test/unit/ManagedConnection.test.ts +0 -58
  173. package/test/unit/PeerManager.test.ts +0 -93
  174. package/test/unit/PendingConnection.test.ts +0 -57
  175. package/test/unit/ProtobufMessage.test.ts +0 -21
  176. package/test/unit/RandomContactList.test.ts +0 -58
  177. package/test/unit/RecursiveOperationManager.test.ts +0 -161
  178. package/test/unit/RecursiveOperationSession.test.ts +0 -68
  179. package/test/unit/Router.test.ts +0 -137
  180. package/test/unit/RoutingSession.test.ts +0 -86
  181. package/test/unit/SortedContactList.test.ts +0 -115
  182. package/test/unit/StoreManager.test.ts +0 -146
  183. package/test/unit/StoreRpcLocal.test.ts +0 -167
  184. package/test/unit/WebrtcConnection.test.ts +0 -29
  185. package/test/unit/WebrtcConnector.test.ts +0 -56
  186. package/test/unit/WebsocketClientConnector.test.ts +0 -101
  187. package/test/unit/WebsocketServer.test.ts +0 -66
  188. package/test/unit/WebsocketServerConnector.test.ts +0 -102
  189. package/test/unit/connectivityRequestHandler.test.ts +0 -104
  190. package/test/unit/createPeerDescriptor.test.ts +0 -69
  191. package/test/unit/customMatchers.test.ts +0 -34
  192. package/test/unit/getClosestNodes.test.ts +0 -30
  193. package/test/unit/version.test.ts +0 -18
  194. package/test/unit/webrtcReplaceInternalIpWithExternalIp.test.ts +0 -18
  195. package/test/utils/FakeConnectorFacade.ts +0 -41
  196. package/test/utils/FakeRpcCommunicator.ts +0 -23
  197. package/test/utils/FakeTransport.ts +0 -79
  198. package/test/utils/customMatchers.ts +0 -71
  199. package/test/utils/mock/MockConnection.ts +0 -26
  200. package/test/utils/mock/MockConnectionsView.ts +0 -18
  201. package/test/utils/mock/MockRouter.ts +0 -62
  202. package/test/utils/mock/MockRpcCommunicator.ts +0 -7
  203. package/test/utils/mock/MockTransport.ts +0 -26
  204. package/test/utils/mock/mockDataEntry.ts +0 -38
  205. package/test/utils/topology.ts +0 -79
  206. package/test/utils/utils.ts +0 -268
  207. package/tsconfig.browser.json +0 -17
  208. package/tsconfig.jest.json +0 -25
  209. package/tsconfig.json +0 -3
  210. 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
- }