@streamr/dht 100.0.0-testnet-three.6 → 100.1.0

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 (215) hide show
  1. package/README.md +1 -1
  2. package/dist/package.json +12 -8
  3. package/dist/src/connection/ConnectionLockRpcLocal.d.ts +1 -1
  4. package/dist/src/connection/ConnectionLockRpcRemote.d.ts +1 -1
  5. package/dist/src/connection/ConnectionLockRpcRemote.js +1 -1
  6. package/dist/src/connection/ConnectionLockRpcRemote.js.map +1 -1
  7. package/dist/src/connection/{ConnectionLockHandler.d.ts → ConnectionLockStates.d.ts} +3 -3
  8. package/dist/src/connection/{ConnectionLockHandler.js → ConnectionLockStates.js} +17 -9
  9. package/dist/src/connection/ConnectionLockStates.js.map +1 -0
  10. package/dist/src/connection/ConnectionManager.d.ts +9 -7
  11. package/dist/src/connection/ConnectionManager.js +16 -18
  12. package/dist/src/connection/ConnectionManager.js.map +1 -1
  13. package/dist/src/connection/ConnectorFacade.js +1 -1
  14. package/dist/src/connection/ConnectorFacade.js.map +1 -1
  15. package/dist/src/connection/Handshaker.js +6 -13
  16. package/dist/src/connection/Handshaker.js.map +1 -1
  17. package/dist/src/connection/ManagedConnection.d.ts +2 -2
  18. package/dist/src/connection/ManagedConnection.js +8 -8
  19. package/dist/src/connection/ManagedConnection.js.map +1 -1
  20. package/dist/src/connection/connectivityChecker.d.ts +1 -1
  21. package/dist/src/connection/connectivityChecker.js +8 -8
  22. package/dist/src/connection/connectivityChecker.js.map +1 -1
  23. package/dist/src/connection/connectivityRequestHandler.d.ts +2 -2
  24. package/dist/src/connection/connectivityRequestHandler.js +10 -11
  25. package/dist/src/connection/connectivityRequestHandler.js.map +1 -1
  26. package/dist/src/connection/webrtc/WebrtcConnector.d.ts +1 -0
  27. package/dist/src/connection/webrtc/WebrtcConnector.js +13 -8
  28. package/dist/src/connection/webrtc/WebrtcConnector.js.map +1 -1
  29. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.d.ts +2 -0
  30. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js +4 -6
  31. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js.map +1 -1
  32. package/dist/src/connection/websocket/AbstractWebsocketClientConnection.d.ts +28 -0
  33. package/dist/src/connection/websocket/{ClientWebsocket.js → AbstractWebsocketClientConnection.js} +42 -68
  34. package/dist/src/connection/websocket/AbstractWebsocketClientConnection.js.map +1 -0
  35. package/dist/src/connection/websocket/NodeWebsocketClientConnection.d.ts +7 -0
  36. package/dist/src/connection/websocket/NodeWebsocketClientConnection.js +39 -0
  37. package/dist/src/connection/websocket/NodeWebsocketClientConnection.js.map +1 -0
  38. package/dist/src/connection/websocket/WebsocketConnector.js +26 -23
  39. package/dist/src/connection/websocket/WebsocketConnector.js.map +1 -1
  40. package/dist/src/connection/websocket/WebsocketServer.js +25 -35
  41. package/dist/src/connection/websocket/WebsocketServer.js.map +1 -1
  42. package/dist/src/connection/websocket/{ServerWebsocket.d.ts → WebsocketServerConnection.d.ts} +4 -5
  43. package/dist/src/connection/websocket/{ServerWebsocket.js → WebsocketServerConnection.js} +18 -51
  44. package/dist/src/connection/websocket/WebsocketServerConnection.js.map +1 -0
  45. package/dist/src/dht/DhtNode.d.ts +15 -8
  46. package/dist/src/dht/DhtNode.js +62 -31
  47. package/dist/src/dht/DhtNode.js.map +1 -1
  48. package/dist/src/dht/DhtNodeRpcLocal.d.ts +5 -1
  49. package/dist/src/dht/DhtNodeRpcLocal.js +10 -0
  50. package/dist/src/dht/DhtNodeRpcLocal.js.map +1 -1
  51. package/dist/src/dht/DhtNodeRpcRemote.d.ts +3 -0
  52. package/dist/src/dht/DhtNodeRpcRemote.js +16 -1
  53. package/dist/src/dht/DhtNodeRpcRemote.js.map +1 -1
  54. package/dist/src/dht/ExternalApiRpcLocal.d.ts +2 -2
  55. package/dist/src/dht/ExternalApiRpcLocal.js +3 -3
  56. package/dist/src/dht/ExternalApiRpcLocal.js.map +1 -1
  57. package/dist/src/dht/ExternalApiRpcRemote.d.ts +1 -1
  58. package/dist/src/dht/ExternalApiRpcRemote.js +2 -2
  59. package/dist/src/dht/ExternalApiRpcRemote.js.map +1 -1
  60. package/dist/src/dht/PeerManager.d.ts +15 -3
  61. package/dist/src/dht/PeerManager.js +54 -40
  62. package/dist/src/dht/PeerManager.js.map +1 -1
  63. package/dist/src/dht/contact/RingContactList.d.ts +31 -0
  64. package/dist/src/dht/contact/RingContactList.js +133 -0
  65. package/dist/src/dht/contact/RingContactList.js.map +1 -0
  66. package/dist/src/dht/contact/SortedContactList.d.ts +2 -1
  67. package/dist/src/dht/contact/SortedContactList.js +19 -17
  68. package/dist/src/dht/contact/SortedContactList.js.map +1 -1
  69. package/dist/src/dht/contact/ringIdentifiers.d.ts +16 -0
  70. package/dist/src/dht/contact/ringIdentifiers.js +54 -0
  71. package/dist/src/dht/contact/ringIdentifiers.js.map +1 -0
  72. package/dist/src/dht/discovery/DiscoverySession.js +3 -1
  73. package/dist/src/dht/discovery/DiscoverySession.js.map +1 -1
  74. package/dist/src/dht/discovery/PeerDiscovery.d.ts +6 -2
  75. package/dist/src/dht/discovery/PeerDiscovery.js +41 -4
  76. package/dist/src/dht/discovery/PeerDiscovery.js.map +1 -1
  77. package/dist/src/dht/discovery/RingDiscoverySession.d.ts +29 -0
  78. package/dist/src/dht/discovery/RingDiscoverySession.js +125 -0
  79. package/dist/src/dht/discovery/RingDiscoverySession.js.map +1 -0
  80. package/dist/src/dht/recursive-operation/RecursiveOperationManager.js +1 -1
  81. package/dist/src/dht/recursive-operation/RecursiveOperationManager.js.map +1 -1
  82. package/dist/src/dht/recursive-operation/RecursiveOperationRpcRemote.js +1 -1
  83. package/dist/src/dht/recursive-operation/RecursiveOperationRpcRemote.js.map +1 -1
  84. package/dist/src/dht/recursive-operation/RecursiveOperationSession.js +0 -1
  85. package/dist/src/dht/recursive-operation/RecursiveOperationSession.js.map +1 -1
  86. package/dist/src/dht/routing/Router.d.ts +0 -1
  87. package/dist/src/dht/routing/Router.js +0 -1
  88. package/dist/src/dht/routing/Router.js.map +1 -1
  89. package/dist/src/dht/routing/RouterRpcLocal.d.ts +0 -1
  90. package/dist/src/dht/routing/RouterRpcLocal.js.map +1 -1
  91. package/dist/src/dht/routing/RouterRpcRemote.js +2 -2
  92. package/dist/src/dht/routing/RouterRpcRemote.js.map +1 -1
  93. package/dist/src/dht/routing/RoutingSession.js +2 -2
  94. package/dist/src/dht/routing/RoutingSession.js.map +1 -1
  95. package/dist/src/dht/store/LocalDataStore.js +2 -2
  96. package/dist/src/dht/store/LocalDataStore.js.map +1 -1
  97. package/dist/src/dht/store/StoreManager.js +2 -2
  98. package/dist/src/dht/store/StoreManager.js.map +1 -1
  99. package/dist/src/exports.d.ts +3 -2
  100. package/dist/src/exports.js +3 -3
  101. package/dist/src/exports.js.map +1 -1
  102. package/dist/src/helpers/createPeerDescriptor.d.ts +1 -1
  103. package/dist/src/helpers/createPeerDescriptor.js +2 -1
  104. package/dist/src/helpers/createPeerDescriptor.js.map +1 -1
  105. package/dist/src/helpers/version.d.ts +6 -0
  106. package/dist/src/helpers/version.js +38 -0
  107. package/dist/src/helpers/version.js.map +1 -0
  108. package/dist/src/proto/packages/dht/protos/DhtRpc.client.d.ts +16 -6
  109. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js +11 -4
  110. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +1 -1
  111. package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +98 -87
  112. package/dist/src/proto/packages/dht/protos/DhtRpc.js +45 -49
  113. package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
  114. package/dist/src/proto/packages/dht/protos/DhtRpc.server.d.ts +10 -4
  115. package/dist/src/transport/RoutingRpcCommunicator.js +0 -2
  116. package/dist/src/transport/RoutingRpcCommunicator.js.map +1 -1
  117. package/karma.config.js +4 -1
  118. package/package.json +12 -8
  119. package/protos/DhtRpc.proto +21 -21
  120. package/src/connection/ConnectionLockRpcLocal.ts +1 -1
  121. package/src/connection/ConnectionLockRpcRemote.ts +2 -2
  122. package/src/connection/{ConnectionLockHandler.ts → ConnectionLockStates.ts} +14 -6
  123. package/src/connection/ConnectionManager.ts +21 -22
  124. package/src/connection/ConnectorFacade.ts +1 -2
  125. package/src/connection/Handshaker.ts +7 -15
  126. package/src/connection/ManagedConnection.ts +8 -8
  127. package/src/connection/connectivityChecker.ts +9 -10
  128. package/src/connection/connectivityRequestHandler.ts +16 -16
  129. package/src/connection/webrtc/BrowserWebrtcConnection.ts +18 -0
  130. package/src/connection/webrtc/NodeWebrtcConnection.ts +1 -1
  131. package/src/connection/webrtc/WebrtcConnector.ts +14 -8
  132. package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +5 -5
  133. package/src/connection/websocket/{ClientWebsocket.ts → AbstractWebsocketClientConnection.ts} +57 -70
  134. package/src/connection/websocket/BrowserWebsocketClientConnection.ts +44 -0
  135. package/src/connection/websocket/NodeWebsocketClientConnection.ts +39 -0
  136. package/src/connection/websocket/WebsocketConnector.ts +27 -28
  137. package/src/connection/websocket/WebsocketServer.ts +27 -42
  138. package/src/connection/websocket/{ServerWebsocket.ts → WebsocketServerConnection.ts} +15 -56
  139. package/src/dht/DhtNode.ts +85 -50
  140. package/src/dht/DhtNodeRpcLocal.ts +16 -0
  141. package/src/dht/DhtNodeRpcRemote.ts +19 -1
  142. package/src/dht/ExternalApiRpcLocal.ts +5 -5
  143. package/src/dht/ExternalApiRpcRemote.ts +4 -4
  144. package/src/dht/PeerManager.ts +70 -44
  145. package/src/dht/contact/RingContactList.ts +151 -0
  146. package/src/dht/contact/SortedContactList.ts +22 -18
  147. package/src/dht/contact/ringIdentifiers.ts +62 -0
  148. package/src/dht/discovery/DiscoverySession.ts +3 -1
  149. package/src/dht/discovery/PeerDiscovery.ts +45 -6
  150. package/src/dht/discovery/RingDiscoverySession.ts +162 -0
  151. package/src/dht/recursive-operation/RecursiveOperationManager.ts +1 -1
  152. package/src/dht/recursive-operation/RecursiveOperationRpcRemote.ts +1 -1
  153. package/src/dht/recursive-operation/RecursiveOperationSession.ts +1 -3
  154. package/src/dht/routing/Router.ts +0 -2
  155. package/src/dht/routing/RouterRpcLocal.ts +0 -1
  156. package/src/dht/routing/RouterRpcRemote.ts +2 -2
  157. package/src/dht/routing/RoutingSession.ts +2 -2
  158. package/src/dht/store/LocalDataStore.ts +1 -1
  159. package/src/dht/store/StoreManager.ts +2 -2
  160. package/src/exports.ts +3 -2
  161. package/src/helpers/createPeerDescriptor.ts +2 -1
  162. package/src/helpers/version.ts +32 -0
  163. package/src/proto/packages/dht/protos/DhtRpc.client.ts +22 -9
  164. package/src/proto/packages/dht/protos/DhtRpc.server.ts +10 -4
  165. package/src/proto/packages/dht/protos/DhtRpc.ts +122 -100
  166. package/src/transport/RoutingRpcCommunicator.ts +1 -2
  167. package/test/benchmark/Find.test.ts +3 -4
  168. package/test/benchmark/KademliaCorrectness.test.ts +14 -8
  169. package/test/benchmark/RingCorrectness.test.ts +157 -0
  170. package/test/benchmark/WebsocketServerMemoryLeak.test.ts +2 -2
  171. package/test/benchmark/hybrid-network-simulation/RingContactList.test.ts +72 -0
  172. package/test/data/generateGroundTruthData.ts +2 -2
  173. package/test/end-to-end/memory-leak.test.ts +1 -2
  174. package/test/integration/ConnectionManager.test.ts +28 -10
  175. package/test/integration/ConnectivityChecking.test.ts +3 -15
  176. package/test/integration/DhtNodeExternalAPI.test.ts +6 -6
  177. package/test/integration/Find.test.ts +6 -6
  178. package/test/integration/Layer1-scale.test.ts +0 -1
  179. package/test/integration/ReplicateData.test.ts +4 -4
  180. package/test/integration/RouteMessage.test.ts +1 -6
  181. package/test/integration/RouterRpcRemote.test.ts +1 -3
  182. package/test/integration/SimultaneousConnections.test.ts +9 -10
  183. package/test/integration/Store.test.ts +4 -4
  184. package/test/integration/StoreAndDelete.test.ts +5 -5
  185. package/test/integration/StoreOnDhtWithThreeNodes.test.ts +5 -5
  186. package/test/integration/StoreOnDhtWithTwoNodes.test.ts +3 -3
  187. package/test/integration/WebrtcConnectionManagement.test.ts +3 -9
  188. package/test/integration/Websocket.test.ts +2 -2
  189. package/test/integration/WebsocketConnectionManagement.test.ts +1 -6
  190. package/test/integration/rpc-connections-over-webrpc.test.ts +1 -2
  191. package/test/unit/PeerManager.test.ts +44 -10
  192. package/test/unit/RecursiveOperationManager.test.ts +14 -8
  193. package/test/unit/RecursiveOperationSession.test.ts +1 -1
  194. package/test/unit/Router.test.ts +0 -3
  195. package/test/unit/RoutingSession.test.ts +1 -2
  196. package/test/unit/connectivityRequestHandler.test.ts +5 -9
  197. package/test/unit/createPeerDescriptor.test.ts +12 -6
  198. package/test/unit/version.test.ts +18 -0
  199. package/test/utils/utils.ts +60 -47
  200. package/tsconfig.browser.json +2 -1
  201. package/tsconfig.jest.json +4 -2
  202. package/tsconfig.node.json +4 -2
  203. package/dist/src/connection/ConnectionLockHandler.js.map +0 -1
  204. package/dist/src/connection/websocket/ClientWebsocket.d.ts +0 -17
  205. package/dist/src/connection/websocket/ClientWebsocket.js.map +0 -1
  206. package/dist/src/connection/websocket/ServerWebsocket.js.map +0 -1
  207. package/dist/src/helpers/MapWithTtl.d.ts +0 -14
  208. package/dist/src/helpers/MapWithTtl.js +0 -60
  209. package/dist/src/helpers/MapWithTtl.js.map +0 -1
  210. package/dist/src/helpers/versionCompatibility.d.ts +0 -2
  211. package/dist/src/helpers/versionCompatibility.js +0 -18
  212. package/dist/src/helpers/versionCompatibility.js.map +0 -1
  213. package/src/helpers/MapWithTtl.ts +0 -71
  214. package/src/helpers/versionCompatibility.ts +0 -13
  215. package/test/unit/versionCompatibility.test.ts +0 -16
@@ -8,7 +8,7 @@ import {
8
8
  import { EventEmitter } from 'eventemitter3'
9
9
  import { sample } from 'lodash'
10
10
  import { MarkRequired } from 'ts-essentials'
11
- import { ConnectionManager, PortRange, TlsCertificate } from '../connection/ConnectionManager'
11
+ import { ConnectionLocker, ConnectionManager, PortRange, TlsCertificate } from '../connection/ConnectionManager'
12
12
  import { DefaultConnectorFacade, DefaultConnectorFacadeConfig } from '../connection/ConnectorFacade'
13
13
  import { IceServer } from '../connection/webrtc/WebrtcConnector'
14
14
  import { isBrowserEnvironment } from '../helpers/browser/isBrowserEnvironment'
@@ -17,10 +17,12 @@ import { Any } from '../proto/google/protobuf/any'
17
17
  import {
18
18
  ClosestPeersRequest,
19
19
  ClosestPeersResponse,
20
+ ClosestRingPeersRequest,
21
+ ClosestRingPeersResponse,
20
22
  ConnectivityResponse,
21
23
  DataEntry,
22
- ExternalFindDataRequest,
23
- ExternalFindDataResponse,
24
+ ExternalFetchDataRequest,
25
+ ExternalFetchDataResponse,
24
26
  ExternalStoreDataRequest,
25
27
  ExternalStoreDataResponse,
26
28
  LeaveNotice,
@@ -40,18 +42,23 @@ import { ExternalApiRpcLocal } from './ExternalApiRpcLocal'
40
42
  import { ExternalApiRpcRemote } from './ExternalApiRpcRemote'
41
43
  import { PeerManager } from './PeerManager'
42
44
  import { PeerDiscovery } from './discovery/PeerDiscovery'
43
- import { RecursiveOperationManager, RecursiveOperationResult } from './recursive-operation/RecursiveOperationManager'
45
+ import { RecursiveOperationManager } from './recursive-operation/RecursiveOperationManager'
44
46
  import { Router } from './routing/Router'
45
47
  import { LocalDataStore } from './store/LocalDataStore'
46
48
  import { StoreManager } from './store/StoreManager'
47
49
  import { StoreRpcRemote } from './store/StoreRpcRemote'
48
50
  import { createPeerDescriptor } from '../helpers/createPeerDescriptor'
51
+ import { RingIdRaw } from './contact/ringIdentifiers'
52
+ import { getLocalRegion } from '@streamr/cdn-location'
53
+ import { RingContacts } from './contact/RingContactList'
49
54
 
50
55
  export interface DhtNodeEvents {
51
56
  contactAdded: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
52
57
  contactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
53
58
  randomContactAdded: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
54
59
  randomContactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
60
+ ringContactAdded: (peerDescriptor: PeerDescriptor, closestPeers: RingContacts) => void
61
+ ringContactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: RingContacts) => void
55
62
  }
56
63
 
57
64
  export interface DhtNodeOptions {
@@ -67,6 +74,7 @@ export interface DhtNodeOptions {
67
74
  storeMaxTtl?: number
68
75
  networkConnectivityTimeout?: number
69
76
  storageRedundancyFactor?: number
77
+ region?: number
70
78
 
71
79
  transport?: ITransport
72
80
  peerDescriptor?: PeerDescriptor
@@ -122,10 +130,10 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
122
130
  private recursiveOperationManager?: RecursiveOperationManager
123
131
  private peerDiscovery?: PeerDiscovery
124
132
  private peerManager?: PeerManager
125
- public connectionManager?: ConnectionManager
133
+ public connectionLocker?: ConnectionLocker
134
+ private region?: number
126
135
  private started = false
127
136
  private abortController = new AbortController()
128
-
129
137
  constructor(conf: DhtNodeOptions) {
130
138
  super()
131
139
  this.config = merge({
@@ -150,7 +158,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
150
158
 
151
159
  private validateConfig(): void {
152
160
  const expectedNodeIdLength = KADEMLIA_ID_LENGTH_IN_BYTES * 2
153
- if (this.config.nodeId !== undefined ) {
161
+ if (this.config.nodeId !== undefined) {
154
162
  if (!/^[0-9a-fA-F]+$/.test(this.config.nodeId)) {
155
163
  throw new Error('Invalid nodeId, the nodeId should be a hex string')
156
164
  } else if (this.config.nodeId.length !== expectedNodeIdLength) {
@@ -177,12 +185,20 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
177
185
  this.config.peerDescriptor.websocket = undefined
178
186
  }
179
187
  }
188
+ if (this.region !== undefined) {
189
+ this.region = this.config.region
190
+ } else if (this.config.peerDescriptor?.region !== undefined) {
191
+ this.region = this.config.peerDescriptor.region
192
+ } else {
193
+ this.region = await getLocalRegion()
194
+ }
195
+
180
196
  // If transport is given, do not create a ConnectionManager
181
197
  if (this.config.transport) {
182
198
  this.transport = this.config.transport
183
199
  this.localPeerDescriptor = this.transport.getLocalPeerDescriptor()
184
200
  if (this.config.transport instanceof ConnectionManager) {
185
- this.connectionManager = this.config.transport
201
+ this.connectionLocker = this.config.transport
186
202
  }
187
203
  } else {
188
204
  const connectorFacadeConfig: DefaultConnectorFacadeConfig = {
@@ -221,7 +237,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
221
237
  metricsContext: this.config.metricsContext
222
238
  })
223
239
  await connectionManager.start()
224
- this.connectionManager = connectionManager
240
+ this.connectionLocker = connectionManager
225
241
  this.transport = connectionManager
226
242
  }
227
243
 
@@ -242,14 +258,13 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
242
258
  joinTimeout: this.config.dhtJoinTimeout,
243
259
  serviceId: this.config.serviceId,
244
260
  parallelism: this.config.joinParallelism,
245
- connectionManager: this.connectionManager,
261
+ connectionLocker: this.connectionLocker,
246
262
  peerManager: this.peerManager!
247
263
  })
248
264
  this.router = new Router({
249
265
  rpcCommunicator: this.rpcCommunicator,
250
266
  connections: this.peerManager!.connections,
251
267
  localPeerDescriptor: this.localPeerDescriptor!,
252
- addContact: (contact: PeerDescriptor, setActive?: boolean) => this.peerManager!.addContact([contact], setActive),
253
268
  handleMessage: (message: Message) => this.handleMessageFromRouter(message),
254
269
  })
255
270
  this.recursiveOperationManager = new RecursiveOperationManager({
@@ -259,7 +274,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
259
274
  connections: this.peerManager!.connections,
260
275
  localPeerDescriptor: this.localPeerDescriptor!,
261
276
  serviceId: this.config.serviceId,
262
- addContact: (contact: PeerDescriptor) => this.peerManager!.addContact([contact]),
277
+ addContact: (contact: PeerDescriptor) => this.peerManager!.addContact(contact),
263
278
  localDataStore: this.localDataStore
264
279
  })
265
280
  this.storeManager = new StoreManager({
@@ -294,10 +309,12 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
294
309
  numberOfNodesPerKBucket: this.config.numberOfNodesPerKBucket,
295
310
  maxContactListSize: this.config.maxNeighborListSize,
296
311
  localNodeId: this.getNodeId(),
297
- connectionManager: this.connectionManager!,
312
+ localPeerDescriptor: this.localPeerDescriptor!,
313
+ connectionLocker: this.connectionLocker!,
298
314
  peerDiscoveryQueryBatchSize: this.config.peerDiscoveryQueryBatchSize,
299
- isLayer0: (this.connectionManager !== undefined),
300
- createDhtNodeRpcRemote: (peerDescriptor: PeerDescriptor) => this.createDhtNodeRpcRemote(peerDescriptor)
315
+ isLayer0: (this.connectionLocker !== undefined),
316
+ createDhtNodeRpcRemote: (peerDescriptor: PeerDescriptor) => this.createDhtNodeRpcRemote(peerDescriptor),
317
+ lockId: this.config.serviceId
301
318
  })
302
319
  this.peerManager.on('contactRemoved', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) => {
303
320
  this.emit('contactRemoved', peerDescriptor, activeContacts)
@@ -311,6 +328,12 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
311
328
  this.peerManager.on('randomContactAdded', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) =>
312
329
  this.emit('randomContactAdded', peerDescriptor, activeContacts)
313
330
  )
331
+ this.peerManager.on('ringContactRemoved', (peerDescriptor: PeerDescriptor, activeContacts: RingContacts) => {
332
+ this.emit('ringContactRemoved', peerDescriptor, activeContacts)
333
+ })
334
+ this.peerManager.on('ringContactAdded', (peerDescriptor: PeerDescriptor, activeContacts: RingContacts) => {
335
+ this.emit('ringContactAdded', peerDescriptor, activeContacts)
336
+ })
314
337
  this.peerManager.on('kBucketEmpty', () => {
315
338
  if (!this.peerDiscovery!.isJoinOngoing()
316
339
  && this.config.entryPoints
@@ -349,26 +372,31 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
349
372
  return this.peerManager!.getClosestNeighborsTo(nodeId, limit)
350
373
  .map((dhtPeer: DhtNodeRpcRemote) => dhtPeer.getPeerDescriptor())
351
374
  },
352
- addContact: (contact: PeerDescriptor) => this.peerManager!.addContact([contact]),
375
+ getClosestRingPeersTo: (ringIdRaw: RingIdRaw, limit: number) => {
376
+ return this.getClosestRingContactsTo(ringIdRaw, limit)
377
+ },
378
+ addContact: (contact: PeerDescriptor) => this.peerManager!.addContact(contact),
353
379
  removeContact: (nodeId: DhtAddress) => this.removeContact(nodeId)
354
380
  })
355
381
  this.rpcCommunicator!.registerRpcMethod(ClosestPeersRequest, ClosestPeersResponse, 'getClosestPeers',
356
382
  (req: ClosestPeersRequest, context) => dhtNodeRpcLocal.getClosestPeers(req, context))
383
+ this.rpcCommunicator!.registerRpcMethod(ClosestRingPeersRequest, ClosestRingPeersResponse, 'getClosestRingPeers',
384
+ (req: ClosestRingPeersRequest, context) => dhtNodeRpcLocal.getClosestRingPeers(req, context))
357
385
  this.rpcCommunicator!.registerRpcMethod(PingRequest, PingResponse, 'ping',
358
386
  (req: PingRequest, context) => dhtNodeRpcLocal.ping(req, context))
359
387
  this.rpcCommunicator!.registerRpcNotification(LeaveNotice, 'leaveNotice',
360
388
  (_req: LeaveNotice, context) => dhtNodeRpcLocal.leaveNotice(context))
361
389
  const externalApiRpcLocal = new ExternalApiRpcLocal({
362
390
  executeRecursiveOperation: (key: DhtAddress, operation: RecursiveOperation, excludedPeer: DhtAddress) => {
363
- return this.executeRecursiveOperation(key, operation, excludedPeer)
391
+ return this.recursiveOperationManager!.execute(key, operation, excludedPeer)
364
392
  },
365
393
  storeDataToDht: (key: DhtAddress, data: Any, creator?: DhtAddress) => this.storeDataToDht(key, data, creator)
366
394
  })
367
395
  this.rpcCommunicator!.registerRpcMethod(
368
- ExternalFindDataRequest,
369
- ExternalFindDataResponse,
370
- 'externalFindData',
371
- (req: ExternalFindDataRequest, context: ServerCallContext) => externalApiRpcLocal.externalFindData(req, context),
396
+ ExternalFetchDataRequest,
397
+ ExternalFetchDataResponse,
398
+ 'externalFetchData',
399
+ (req: ExternalFetchDataRequest, context: ServerCallContext) => externalApiRpcLocal.externalFetchData(req, context),
372
400
  { timeout: 10000 } // TODO use config option or named constant?
373
401
  )
374
402
  this.rpcCommunicator!.registerRpcMethod(
@@ -389,8 +417,6 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
389
417
  private handleMessageFromRouter(message: Message): void {
390
418
  if (message.serviceId === this.config.serviceId) {
391
419
  this.rpcCommunicator?.handleMessageFromPeer(message)
392
- } else if (this.connectionManager?.handleIncomingMessage(message)) {
393
- // message was handled by connectionManager
394
420
  } else {
395
421
  this.emit('message', message)
396
422
  }
@@ -400,7 +426,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
400
426
  if (this.config.peerDescriptor !== undefined) {
401
427
  this.localPeerDescriptor = this.config.peerDescriptor
402
428
  } else {
403
- this.localPeerDescriptor = createPeerDescriptor(connectivityResponse, this.config.nodeId)
429
+ this.localPeerDescriptor = createPeerDescriptor(connectivityResponse, this.region!, this.config.nodeId)
404
430
  }
405
431
  return this.localPeerDescriptor
406
432
  }
@@ -408,8 +434,15 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
408
434
  public getClosestContacts(limit?: number): PeerDescriptor[] {
409
435
  return this.peerManager!.getClosestContactsTo(
410
436
  this.getNodeId(),
411
- limit).map((peer) => peer.getPeerDescriptor()
412
- )
437
+ limit).map((peer) => peer.getPeerDescriptor())
438
+ }
439
+
440
+ public getClosestRingContactsTo(ringIdRaw: RingIdRaw, limit?: number): RingContacts {
441
+ const closest = this.peerManager!.getClosestRingContactsTo(ringIdRaw, limit)
442
+ return {
443
+ left: closest.left.map((dhtPeer: DhtNodeRpcRemote) => dhtPeer.getPeerDescriptor()),
444
+ right: closest.right.map((dhtPeer: DhtNodeRpcRemote) => dhtPeer.getPeerDescriptor())
445
+ }
413
446
  }
414
447
 
415
448
  public getNodeId(): DhtAddress {
@@ -448,25 +481,22 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
448
481
  await this.peerDiscovery!.joinDht(entryPointDescriptors, doAdditionalDistantPeerDiscovery, retry)
449
482
  }
450
483
 
451
- // TODO make this private and unify the public API of find/fetch/store/delete methods
452
- // (we already have storeDataToDht etc. here)
453
- public async executeRecursiveOperation(
454
- key: DhtAddress,
455
- operation: RecursiveOperation,
456
- excludedPeer?: DhtAddress
457
- ): Promise<RecursiveOperationResult> {
458
- return this.recursiveOperationManager!.execute(key, operation, excludedPeer)
484
+ public async joinRing(): Promise<void> {
485
+ if (!this.started) {
486
+ throw new Error('Cannot join ring before calling start() on DhtNode')
487
+ }
488
+ await this.peerDiscovery!.joinRing()
459
489
  }
460
490
 
461
491
  public async storeDataToDht(key: DhtAddress, data: Any, creator?: DhtAddress): Promise<PeerDescriptor[]> {
462
492
  const connectedEntryPoints = this.getConnectedEntryPoints()
463
493
  if (this.peerDiscovery!.isJoinOngoing() && connectedEntryPoints.length > 0) {
464
- return this.storeDataViaPeer(key, data, sample(connectedEntryPoints)!)
494
+ return this.storeDataToDhtViaPeer(key, data, sample(connectedEntryPoints)!)
465
495
  }
466
496
  return this.storeManager!.storeDataToDht(key, data, creator ?? this.getNodeId())
467
497
  }
468
498
 
469
- public async storeDataViaPeer(key: DhtAddress, data: Any, peer: PeerDescriptor): Promise<PeerDescriptor[]> {
499
+ public async storeDataToDhtViaPeer(key: DhtAddress, data: Any, peer: PeerDescriptor): Promise<PeerDescriptor[]> {
470
500
  const rpcRemote = new ExternalApiRpcRemote(
471
501
  this.localPeerDescriptor!,
472
502
  peer,
@@ -476,29 +506,34 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
476
506
  return await rpcRemote.storeData(key, data)
477
507
  }
478
508
 
479
- public async getDataFromDht(key: DhtAddress): Promise<DataEntry[]> {
509
+ public async fetchDataFromDht(key: DhtAddress): Promise<DataEntry[]> {
480
510
  const connectedEntryPoints = this.getConnectedEntryPoints()
481
511
  if (this.peerDiscovery!.isJoinOngoing() && connectedEntryPoints.length > 0) {
482
- return this.findDataViaPeer(key, sample(connectedEntryPoints)!)
512
+ return this.fetchDataFromDhtViaPeer(key, sample(connectedEntryPoints)!)
483
513
  }
484
514
  const result = await this.recursiveOperationManager!.execute(key, RecursiveOperation.FETCH_DATA)
485
515
  return result.dataEntries ?? [] // TODO is this fallback needed?
486
516
  }
487
517
 
488
- public async deleteDataFromDht(key: DhtAddress, waitForCompletion: boolean): Promise<void> {
489
- if (!this.abortController.signal.aborted) {
490
- await this.recursiveOperationManager!.execute(key, RecursiveOperation.DELETE_DATA, undefined, waitForCompletion)
491
- }
492
- }
493
-
494
- public async findDataViaPeer(key: DhtAddress, peer: PeerDescriptor): Promise<DataEntry[]> {
518
+ public async fetchDataFromDhtViaPeer(key: DhtAddress, peer: PeerDescriptor): Promise<DataEntry[]> {
495
519
  const rpcRemote = new ExternalApiRpcRemote(
496
520
  this.localPeerDescriptor!,
497
521
  peer,
498
522
  this.rpcCommunicator!,
499
523
  ExternalApiRpcClient
500
524
  )
501
- return await rpcRemote.externalFindData(key)
525
+ return await rpcRemote.externalFetchData(key)
526
+ }
527
+
528
+ public async deleteDataFromDht(key: DhtAddress, waitForCompletion: boolean): Promise<void> {
529
+ if (!this.abortController.signal.aborted) {
530
+ await this.recursiveOperationManager!.execute(key, RecursiveOperation.DELETE_DATA, undefined, waitForCompletion)
531
+ }
532
+ }
533
+
534
+ async findClosestNodesFromDht(key: DhtAddress): Promise<PeerDescriptor[]> {
535
+ const result = await this.recursiveOperationManager!.execute(key, RecursiveOperation.FIND_CLOSEST_NODES)
536
+ return result.closestNodes
502
537
  }
503
538
 
504
539
  public getTransport(): ITransport {
@@ -522,15 +557,15 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
522
557
  }
523
558
 
524
559
  public getLocalLockedConnectionCount(): number {
525
- return this.connectionManager!.getLocalLockedConnectionCount()
560
+ return this.connectionLocker!.getLocalLockedConnectionCount()
526
561
  }
527
562
 
528
563
  public getRemoteLockedConnectionCount(): number {
529
- return this.connectionManager!.getRemoteLockedConnectionCount()
564
+ return this.connectionLocker!.getRemoteLockedConnectionCount()
530
565
  }
531
566
 
532
567
  public getWeakLockedConnectionCount(): number {
533
- return this.connectionManager!.getWeakLockedConnectionCount()
568
+ return this.connectionLocker!.getWeakLockedConnectionCount()
534
569
  }
535
570
 
536
571
  public async waitForNetworkConnectivity(): Promise<void> {
@@ -566,7 +601,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
566
601
  await this.transport!.stop()
567
602
  }
568
603
  this.transport = undefined
569
- this.connectionManager = undefined
604
+ this.connectionLocker = undefined
570
605
  this.removeAllListeners()
571
606
  }
572
607
 
@@ -4,6 +4,8 @@ import { Empty } from '../proto/google/protobuf/empty'
4
4
  import {
5
5
  ClosestPeersRequest,
6
6
  ClosestPeersResponse,
7
+ ClosestRingPeersRequest,
8
+ ClosestRingPeersResponse,
7
9
  PeerDescriptor,
8
10
  PingRequest,
9
11
  PingResponse
@@ -11,10 +13,13 @@ import {
11
13
  import { IDhtNodeRpc } from '../proto/packages/dht/protos/DhtRpc.server'
12
14
  import { DhtCallContext } from '../rpc-protocol/DhtCallContext'
13
15
  import { DhtAddress, getDhtAddressFromRaw, getNodeIdFromPeerDescriptor } from '../identifiers'
16
+ import { RingIdRaw } from './contact/ringIdentifiers'
17
+ import { RingContacts } from './contact/RingContactList'
14
18
 
15
19
  interface DhtNodeRpcLocalConfig {
16
20
  peerDiscoveryQueryBatchSize: number
17
21
  getClosestPeersTo: (nodeId: DhtAddress, limit: number) => PeerDescriptor[]
22
+ getClosestRingPeersTo: (id: RingIdRaw, limit: number) => RingContacts
18
23
  addContact: (contact: PeerDescriptor) => void
19
24
  removeContact: (nodeId: DhtAddress) => void
20
25
  }
@@ -38,6 +43,17 @@ export class DhtNodeRpcLocal implements IDhtNodeRpc {
38
43
  return response
39
44
  }
40
45
 
46
+ async getClosestRingPeers(request: ClosestRingPeersRequest, context: ServerCallContext): Promise<ClosestRingPeersResponse> {
47
+ this.config.addContact((context as DhtCallContext).incomingSourceDescriptor!)
48
+ const closestPeers = this.config.getClosestRingPeersTo(request.ringId as RingIdRaw, this.config.peerDiscoveryQueryBatchSize)
49
+ const response = {
50
+ leftPeers: closestPeers.left,
51
+ rightPeers: closestPeers.right,
52
+ requestId: request.requestId
53
+ }
54
+ return response
55
+ }
56
+
41
57
  async ping(request: PingRequest, context: ServerCallContext): Promise<PingResponse> {
42
58
  logger.trace('received ping request: ' + getNodeIdFromPeerDescriptor((context as DhtCallContext).incomingSourceDescriptor!))
43
59
  setImmediate(() => {
@@ -4,6 +4,7 @@ import { v4 } from 'uuid'
4
4
  import { DhtAddress, DhtAddressRaw, getNodeIdFromPeerDescriptor, getRawFromDhtAddress } from '../identifiers'
5
5
  import {
6
6
  ClosestPeersRequest,
7
+ ClosestRingPeersRequest,
7
8
  PeerDescriptor,
8
9
  PingRequest
9
10
  } from '../proto/packages/dht/protos/DhtRpc'
@@ -11,6 +12,8 @@ import { DhtNodeRpcClient } from '../proto/packages/dht/protos/DhtRpc.client'
11
12
  import { ServiceID } from '../types/ServiceID'
12
13
  import { RpcRemote } from './contact/RpcRemote'
13
14
  import { DhtCallContext } from '../rpc-protocol/DhtCallContext'
15
+ import { RingIdRaw } from './contact/ringIdentifiers'
16
+ import { RingContacts } from './contact/RingContactList'
14
17
 
15
18
  const logger = new Logger(module)
16
19
 
@@ -55,6 +58,21 @@ export class DhtNodeRpcRemote extends RpcRemote<DhtNodeRpcClient> implements KBu
55
58
  }
56
59
  }
57
60
 
61
+ async getClosestRingPeers(ringIdRaw: RingIdRaw): Promise<RingContacts> {
62
+ logger.trace(`Requesting getClosestRingPeers on ${this.serviceId} from ${this.getNodeId()}`)
63
+ const request: ClosestRingPeersRequest = {
64
+ ringId: ringIdRaw,
65
+ requestId: v4()
66
+ }
67
+ try {
68
+ const response = await this.getClient().getClosestRingPeers(request, this.formDhtRpcOptions())
69
+ return { left: response.leftPeers ?? [], right: response.rightPeers ?? [] }
70
+ } catch (err) {
71
+ logger.trace(`getClosestRingPeers error ${this.serviceId}`, { err })
72
+ throw err
73
+ }
74
+ }
75
+
58
76
  async ping(): Promise<boolean> {
59
77
  logger.trace(`Requesting ping on ${this.serviceId} from ${this.getNodeId()}`)
60
78
  const request: PingRequest = {
@@ -67,7 +85,7 @@ export class DhtNodeRpcRemote extends RpcRemote<DhtNodeRpcClient> implements KBu
67
85
  return true
68
86
  }
69
87
  } catch (err) {
70
- logger.trace(`ping failed on ${this.serviceId} to ${this.getNodeId()}: ${err}`)
88
+ logger.trace(`ping failed on ${this.serviceId} to ${this.getNodeId()}`, { err })
71
89
  }
72
90
  return false
73
91
  }
@@ -1,7 +1,7 @@
1
1
  import { IExternalApiRpc } from '../proto/packages/dht/protos/DhtRpc.server'
2
2
  import {
3
- ExternalFindDataRequest,
4
- ExternalFindDataResponse,
3
+ ExternalFetchDataRequest,
4
+ ExternalFetchDataResponse,
5
5
  ExternalStoreDataRequest,
6
6
  ExternalStoreDataResponse,
7
7
  RecursiveOperation,
@@ -35,14 +35,14 @@ export class ExternalApiRpcLocal implements IExternalApiRpc {
35
35
  this.config = config
36
36
  }
37
37
 
38
- async externalFindData(findDataRequest: ExternalFindDataRequest, context: ServerCallContext): Promise<ExternalFindDataResponse> {
38
+ async externalFetchData(request: ExternalFetchDataRequest, context: ServerCallContext): Promise<ExternalFetchDataResponse> {
39
39
  const senderPeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
40
40
  const result = await this.config.executeRecursiveOperation(
41
- getDhtAddressFromRaw(findDataRequest.key),
41
+ getDhtAddressFromRaw(request.key),
42
42
  RecursiveOperation.FETCH_DATA,
43
43
  getNodeIdFromPeerDescriptor(senderPeerDescriptor)
44
44
  )
45
- return ExternalFindDataResponse.create({ entries: result.dataEntries ?? [] })
45
+ return ExternalFetchDataResponse.create({ entries: result.dataEntries ?? [] })
46
46
  }
47
47
 
48
48
  async externalStoreData(request: ExternalStoreDataRequest, context: ServerCallContext): Promise<ExternalStoreDataResponse> {
@@ -1,13 +1,13 @@
1
1
  import { DhtAddress, getRawFromDhtAddress } from '../identifiers'
2
2
  import { Any } from '../proto/google/protobuf/any'
3
- import { DataEntry, ExternalFindDataRequest, ExternalStoreDataRequest, PeerDescriptor } from '../proto/packages/dht/protos/DhtRpc'
3
+ import { DataEntry, ExternalFetchDataRequest, ExternalStoreDataRequest, PeerDescriptor } from '../proto/packages/dht/protos/DhtRpc'
4
4
  import { ExternalApiRpcClient } from '../proto/packages/dht/protos/DhtRpc.client'
5
5
  import { RpcRemote } from './contact/RpcRemote'
6
6
 
7
7
  export class ExternalApiRpcRemote extends RpcRemote<ExternalApiRpcClient> {
8
8
 
9
- async externalFindData(key: DhtAddress): Promise<DataEntry[]> {
10
- const request: ExternalFindDataRequest = {
9
+ async externalFetchData(key: DhtAddress): Promise<DataEntry[]> {
10
+ const request: ExternalFetchDataRequest = {
11
11
  key: getRawFromDhtAddress(key)
12
12
  }
13
13
  const options = this.formDhtRpcOptions({
@@ -15,7 +15,7 @@ export class ExternalApiRpcRemote extends RpcRemote<ExternalApiRpcClient> {
15
15
  timeout: 10000
16
16
  })
17
17
  try {
18
- const data = await this.getClient().externalFindData(request, options)
18
+ const data = await this.getClient().externalFetchData(request, options)
19
19
  return data.entries
20
20
  } catch (err) {
21
21
  return []