@streamr/dht 100.2.1 → 100.2.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 (118) hide show
  1. package/dist/package.json +6 -6
  2. package/dist/src/connection/ConnectionLockStates.js +4 -6
  3. package/dist/src/connection/ConnectionLockStates.js.map +1 -1
  4. package/dist/src/connection/ConnectionManager.d.ts +1 -0
  5. package/dist/src/connection/ConnectionManager.js +8 -2
  6. package/dist/src/connection/ConnectionManager.js.map +1 -1
  7. package/dist/src/connection/ManagedConnection.js +7 -9
  8. package/dist/src/connection/ManagedConnection.js.map +1 -1
  9. package/dist/src/connection/connectivityChecker.js +0 -3
  10. package/dist/src/connection/connectivityChecker.js.map +1 -1
  11. package/dist/src/connection/websocket/WebsocketConnector.js +1 -1
  12. package/dist/src/connection/websocket/WebsocketConnector.js.map +1 -1
  13. package/dist/src/dht/DhtNode.d.ts +10 -7
  14. package/dist/src/dht/DhtNode.js +51 -32
  15. package/dist/src/dht/DhtNode.js.map +1 -1
  16. package/dist/src/dht/DhtNodeRpcLocal.d.ts +2 -2
  17. package/dist/src/dht/DhtNodeRpcLocal.js +5 -4
  18. package/dist/src/dht/DhtNodeRpcLocal.js.map +1 -1
  19. package/dist/src/dht/DhtNodeRpcRemote.js +1 -0
  20. package/dist/src/dht/DhtNodeRpcRemote.js.map +1 -1
  21. package/dist/src/dht/PeerManager.d.ts +14 -14
  22. package/dist/src/dht/PeerManager.js +23 -59
  23. package/dist/src/dht/PeerManager.js.map +1 -1
  24. package/dist/src/dht/contact/ContactList.d.ts +2 -2
  25. package/dist/src/dht/contact/RandomContactList.js +2 -2
  26. package/dist/src/dht/contact/RandomContactList.js.map +1 -1
  27. package/dist/src/dht/contact/RingContactList.d.ts +2 -5
  28. package/dist/src/dht/contact/RingContactList.js +3 -11
  29. package/dist/src/dht/contact/RingContactList.js.map +1 -1
  30. package/dist/src/dht/contact/SortedContactList.d.ts +4 -1
  31. package/dist/src/dht/contact/SortedContactList.js +4 -5
  32. package/dist/src/dht/contact/SortedContactList.js.map +1 -1
  33. package/dist/src/dht/contact/getClosestContacts.d.ts +7 -0
  34. package/dist/src/dht/contact/getClosestContacts.js +18 -0
  35. package/dist/src/dht/contact/getClosestContacts.js.map +1 -0
  36. package/dist/src/dht/discovery/DiscoverySession.d.ts +8 -8
  37. package/dist/src/dht/discovery/DiscoverySession.js +30 -35
  38. package/dist/src/dht/discovery/DiscoverySession.js.map +1 -1
  39. package/dist/src/dht/discovery/PeerDiscovery.d.ts +1 -2
  40. package/dist/src/dht/discovery/PeerDiscovery.js +6 -8
  41. package/dist/src/dht/discovery/PeerDiscovery.js.map +1 -1
  42. package/dist/src/dht/discovery/RingDiscoverySession.d.ts +4 -4
  43. package/dist/src/dht/discovery/RingDiscoverySession.js +13 -13
  44. package/dist/src/dht/discovery/RingDiscoverySession.js.map +1 -1
  45. package/dist/src/dht/recursive-operation/RecursiveOperationManager.d.ts +2 -2
  46. package/dist/src/dht/recursive-operation/RecursiveOperationManager.js +15 -15
  47. package/dist/src/dht/recursive-operation/RecursiveOperationManager.js.map +1 -1
  48. package/dist/src/dht/recursive-operation/RecursiveOperationSession.d.ts +1 -1
  49. package/dist/src/dht/recursive-operation/RecursiveOperationSession.js +11 -13
  50. package/dist/src/dht/recursive-operation/RecursiveOperationSession.js.map +1 -1
  51. package/dist/src/dht/recursive-operation/RecursiveOperationSessionRpcLocal.js +1 -1
  52. package/dist/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.d.ts +1 -1
  53. package/dist/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.js +2 -2
  54. package/dist/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.js.map +1 -1
  55. package/dist/src/dht/routing/Router.d.ts +1 -2
  56. package/dist/src/dht/routing/Router.js +2 -3
  57. package/dist/src/dht/routing/Router.js.map +1 -1
  58. package/dist/src/dht/routing/RoutingSession.d.ts +1 -2
  59. package/dist/src/dht/routing/RoutingSession.js +2 -2
  60. package/dist/src/dht/routing/RoutingSession.js.map +1 -1
  61. package/dist/src/dht/store/StoreRpcLocal.js +3 -3
  62. package/dist/src/dht/store/StoreRpcLocal.js.map +1 -1
  63. package/dist/src/proto/packages/dht/protos/DhtRpc.client.d.ts +8 -0
  64. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js +4 -0
  65. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +1 -1
  66. package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +10 -2
  67. package/dist/src/proto/packages/dht/protos/DhtRpc.js +1 -1
  68. package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
  69. package/dist/src/proto/packages/dht/protos/DhtRpc.server.d.ts +4 -0
  70. package/dist/src/transport/ITransport.d.ts +3 -0
  71. package/dist/src/transport/ITransport.js.map +1 -1
  72. package/package.json +6 -6
  73. package/protos/DhtRpc.proto +7 -1
  74. package/src/connection/ConnectionLockStates.ts +3 -5
  75. package/src/connection/ConnectionManager.ts +9 -2
  76. package/src/connection/ManagedConnection.ts +11 -14
  77. package/src/connection/connectivityChecker.ts +0 -2
  78. package/src/connection/webrtc/BrowserWebrtcConnection.ts +0 -1
  79. package/src/connection/websocket/WebsocketConnector.ts +1 -1
  80. package/src/dht/DhtNode.ts +63 -44
  81. package/src/dht/DhtNodeRpcLocal.ts +7 -6
  82. package/src/dht/DhtNodeRpcRemote.ts +1 -0
  83. package/src/dht/PeerManager.ts +38 -73
  84. package/src/dht/contact/ContactList.ts +2 -2
  85. package/src/dht/contact/RandomContactList.ts +2 -3
  86. package/src/dht/contact/RingContactList.ts +6 -16
  87. package/src/dht/contact/SortedContactList.ts +9 -10
  88. package/src/dht/contact/getClosestContacts.ts +22 -0
  89. package/src/dht/discovery/DiscoverySession.ts +35 -45
  90. package/src/dht/discovery/PeerDiscovery.ts +6 -9
  91. package/src/dht/discovery/RingDiscoverySession.ts +13 -13
  92. package/src/dht/recursive-operation/RecursiveOperationManager.ts +16 -16
  93. package/src/dht/recursive-operation/RecursiveOperationSession.ts +11 -13
  94. package/src/dht/recursive-operation/RecursiveOperationSessionRpcLocal.ts +1 -1
  95. package/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.ts +2 -2
  96. package/src/dht/routing/Router.ts +3 -5
  97. package/src/dht/routing/RoutingSession.ts +3 -4
  98. package/src/dht/store/StoreRpcLocal.ts +3 -3
  99. package/src/proto/packages/dht/protos/DhtRpc.client.ts +8 -0
  100. package/src/proto/packages/dht/protos/DhtRpc.server.ts +4 -0
  101. package/src/proto/packages/dht/protos/DhtRpc.ts +11 -3
  102. package/src/transport/ITransport.ts +3 -0
  103. package/test/end-to-end/Layer0MixedConnectionTypes.test.ts +3 -5
  104. package/test/integration/DhtNode.test.ts +81 -0
  105. package/test/integration/Layer1-scale.test.ts +1 -1
  106. package/test/integration/ScaleDownDht.test.ts +7 -4
  107. package/test/unit/DiscoverySession.test.ts +85 -0
  108. package/test/unit/PeerManager.test.ts +3 -17
  109. package/test/unit/RecursiveOperationManager.test.ts +5 -3
  110. package/test/unit/Router.test.ts +2 -2
  111. package/test/unit/RoutingSession.test.ts +2 -2
  112. package/test/unit/SortedContactList.test.ts +4 -4
  113. package/test/unit/getClosestContacts.test.ts +28 -0
  114. package/test/utils/FakeTransport.ts +34 -7
  115. package/test/utils/mock/Router.ts +0 -3
  116. package/test/utils/mock/Transport.ts +10 -0
  117. package/test/utils/topology.ts +80 -0
  118. package/test/RandomGraphSimulation.ts +0 -53
@@ -9,7 +9,9 @@ import "google/protobuf/timestamp.proto";
9
9
  import "packages/proto-rpc/protos/ProtoRpc.proto";
10
10
 
11
11
  service DhtNodeRpc {
12
+ // TODO rename to getClosestNeighbors (breaking change)
12
13
  rpc getClosestPeers (ClosestPeersRequest) returns (ClosestPeersResponse);
14
+ // TODO rename to getClosestRingContacts (breaking change)
13
15
  rpc getClosestRingPeers (ClosestRingPeersRequest) returns (ClosestRingPeersResponse);
14
16
  rpc ping (PingRequest) returns (PingResponse);
15
17
  rpc leaveNotice (LeaveNotice) returns (google.protobuf.Empty);
@@ -92,21 +94,25 @@ message DataEntry {
92
94
  bool deleted = 8;
93
95
  }
94
96
 
97
+ // TODO rename to ClosestNeighborsRequest
95
98
  message ClosestPeersRequest {
96
99
  bytes nodeId = 1;
97
100
  string requestId = 2;
98
101
  }
99
102
 
103
+ // TODO rename to ClosestNeighborsResponse
100
104
  message ClosestPeersResponse {
101
105
  repeated PeerDescriptor peers = 1;
102
106
  string requestId = 2;
103
107
  }
104
108
 
109
+ // TODO rename to ClosestRingContactsRequest
105
110
  message ClosestRingPeersRequest {
106
111
  bytes ringId = 1;
107
112
  string requestId = 2;
108
113
  }
109
114
 
115
+ // TODO rename to ClosestRingContactsResponse
110
116
  message ClosestRingPeersResponse {
111
117
  repeated PeerDescriptor leftPeers = 1;
112
118
  repeated PeerDescriptor rightPeers = 2;
@@ -125,7 +131,7 @@ enum RecursiveOperation {
125
131
  }
126
132
 
127
133
  message RecursiveOperationResponse {
128
- repeated PeerDescriptor closestConnectedPeers = 1;
134
+ repeated PeerDescriptor closestConnectedNodes = 1;
129
135
  repeated DataEntry dataEntries = 2;
130
136
  bool noCloserNodesFound = 3;
131
137
  repeated PeerDescriptor routingPath = 4;
@@ -36,12 +36,10 @@ export class ConnectionLockStates {
36
36
  public isRemoteLocked(id: DhtAddress, lockId?: LockID): boolean {
37
37
  if (lockId === undefined) {
38
38
  return this.remoteLocks.has(id)
39
+ } else if (this.remoteLocks.has(id) && this.remoteLocks.get(id)!.has(lockId)) {
40
+ return true
39
41
  } else {
40
- if (this.remoteLocks.has(id) && this.remoteLocks.get(id)!.has(lockId)) {
41
- return true
42
- } else {
43
- return false
44
- }
42
+ return false
45
43
  }
46
44
  }
47
45
 
@@ -304,7 +304,13 @@ export class ConnectionManager extends EventEmitter<TransportEvents> implements
304
304
  }
305
305
 
306
306
  public hasConnection(nodeId: DhtAddress): boolean {
307
- return this.connections.has(nodeId)
307
+ // TODO if we remove filtering in getConnections, this can just be this.connection.has(nodeId)
308
+ return this.getConnections().some((c) => getNodeIdFromPeerDescriptor(c) == nodeId)
309
+ }
310
+
311
+ public getConnectionCount(): number {
312
+ // TODO if we remove filtering in getConnections, this can just be this.connection.length
313
+ return this.getConnections().length
308
314
  }
309
315
 
310
316
  public hasLocalLockedConnection(nodeId: DhtAddress): boolean {
@@ -509,7 +515,6 @@ export class ConnectionManager extends EventEmitter<TransportEvents> implements
509
515
  // eslint-disable-next-line promise/catch-or-return
510
516
  waitForEvent3<ManagedConnectionEvents>(connection, 'disconnected', 2000).then(() => {
511
517
  logger.trace('disconnected event received in gracefullyDisconnectAsync()')
512
- return
513
518
  })
514
519
  .catch((e) => {
515
520
  logger.trace('force-closing connection after timeout ' + e)
@@ -546,6 +551,8 @@ export class ConnectionManager extends EventEmitter<TransportEvents> implements
546
551
 
547
552
  public getConnections(): PeerDescriptor[] {
548
553
  return Array.from(this.connections.values())
554
+ // TODO is this filtering needed? (if it is, should we do the same filtering e.g.
555
+ // in getConnection() or in other methods which access this.connections directly?)
549
556
  .filter((managedConnection: ManagedConnection) => managedConnection.isHandshakeCompleted())
550
557
  .map((managedConnection: ManagedConnection) => managedConnection.getPeerDescriptor()!)
551
558
  }
@@ -96,21 +96,18 @@ export class ManagedConnection extends EventEmitter<Events> {
96
96
  })
97
97
  outgoingConnection.once('disconnected', this.onDisconnected)
98
98
 
99
- } else {
100
- if (incomingConnection) {
101
- this.handshaker = new Handshaker(this.localPeerDescriptor, incomingConnection)
102
- this.handshaker.on('handshakeRequest', (
103
- sourcePeerDescriptor: PeerDescriptor,
104
- version: string,
105
- targetPeerDescriptor?: PeerDescriptor
106
- ) => {
107
- this.setRemotePeerDescriptor(sourcePeerDescriptor)
108
- this.emit('handshakeRequest', sourcePeerDescriptor, version, targetPeerDescriptor)
109
- })
110
-
111
- incomingConnection.on('disconnected', this.onDisconnected)
99
+ } else if (incomingConnection) {
100
+ this.handshaker = new Handshaker(this.localPeerDescriptor, incomingConnection)
101
+ this.handshaker.on('handshakeRequest', (
102
+ sourcePeerDescriptor: PeerDescriptor,
103
+ version: string,
104
+ targetPeerDescriptor?: PeerDescriptor
105
+ ) => {
106
+ this.setRemotePeerDescriptor(sourcePeerDescriptor)
107
+ this.emit('handshakeRequest', sourcePeerDescriptor, version, targetPeerDescriptor)
108
+ })
112
109
 
113
- }
110
+ incomingConnection.on('disconnected', this.onDisconnected)
114
111
  }
115
112
  }
116
113
 
@@ -87,8 +87,6 @@ export const sendConnectivityRequest = async (
87
87
  } else {
88
88
  reject(`Unsupported version: ${remoteVersion}`)
89
89
  }
90
- } else {
91
- return
92
90
  }
93
91
  } catch (err) {
94
92
  logger.trace('Could not parse message', { err })
@@ -119,7 +119,6 @@ export class NodeWebrtcConnection extends EventEmitter<Events> implements IWebrt
119
119
 
120
120
  public addRemoteCandidate(candidate: string, mid: string): void {
121
121
  this.peerConnection?.addIceCandidate({ candidate: candidate, sdpMid: mid })
122
- .then(() => { return })
123
122
  .catch((err) => {
124
123
  logger.warn('Failed to add ICE candidate', { err })
125
124
  })
@@ -154,6 +154,7 @@ export class WebsocketConnector {
154
154
  // The localPeerDescriptor can be undefined here as the WS server is used for connectivity checks
155
155
  // before the localPeerDescriptor is set during start.
156
156
  // Handshaked connections should be rejected before the localPeerDescriptor is set.
157
+ // eslint-disable-next-line no-lonely-if
157
158
  if (this.localPeerDescriptor !== undefined) {
158
159
  this.attachHandshaker(connection)
159
160
  } else {
@@ -275,7 +276,6 @@ export class WebsocketConnector {
275
276
  )
276
277
  remoteConnector.requestConnection().then(() => {
277
278
  logger.trace('Sent WebsocketConnectionRequest notification to peer', { targetPeerDescriptor })
278
- return
279
279
  }, (err) => {
280
280
  logger.debug('Failed to send WebsocketConnectionRequest notification to peer ', {
281
281
  error: err, targetPeerDescriptor
@@ -53,12 +53,12 @@ import { getLocalRegion } from '@streamr/cdn-location'
53
53
  import { RingContacts } from './contact/RingContactList'
54
54
 
55
55
  export interface DhtNodeEvents {
56
- contactAdded: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
57
- contactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
58
- randomContactAdded: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
59
- randomContactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
60
- ringContactAdded: (peerDescriptor: PeerDescriptor, closestPeers: RingContacts) => void
61
- ringContactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: RingContacts) => void
56
+ closestContactAdded: (peerDescriptor: PeerDescriptor) => void
57
+ closestContactRemoved: (peerDescriptor: PeerDescriptor) => void
58
+ randomContactAdded: (peerDescriptor: PeerDescriptor) => void
59
+ randomContactRemoved: (peerDescriptor: PeerDescriptor) => void
60
+ ringContactAdded: (peerDescriptor: PeerDescriptor) => void
61
+ ringContactRemoved: (peerDescriptor: PeerDescriptor) => void
62
62
  }
63
63
 
64
64
  export interface DhtNodeOptions {
@@ -241,7 +241,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
241
241
 
242
242
  this.rpcCommunicator = new RoutingRpcCommunicator(
243
243
  this.config.serviceId,
244
- this.transport.send,
244
+ (msg, opts) => this.transport!.send(msg, opts),
245
245
  { rpcRequestTimeout: this.config.rpcRequestTimeout }
246
246
  )
247
247
 
@@ -252,7 +252,6 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
252
252
  this.peerDiscovery = new PeerDiscovery({
253
253
  localPeerDescriptor: this.localPeerDescriptor!,
254
254
  joinNoProgressLimit: this.config.joinNoProgressLimit,
255
- peerDiscoveryQueryBatchSize: this.config.peerDiscoveryQueryBatchSize,
256
255
  joinTimeout: this.config.dhtJoinTimeout,
257
256
  serviceId: this.config.serviceId,
258
257
  parallelism: this.config.joinParallelism,
@@ -261,19 +260,19 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
261
260
  })
262
261
  this.router = new Router({
263
262
  rpcCommunicator: this.rpcCommunicator,
264
- connections: this.peerManager!.connections,
265
263
  localPeerDescriptor: this.localPeerDescriptor!,
266
264
  handleMessage: (message: Message) => this.handleMessageFromRouter(message),
265
+ getConnections: () => this.getConnections()
267
266
  })
268
267
  this.recursiveOperationManager = new RecursiveOperationManager({
269
268
  rpcCommunicator: this.rpcCommunicator,
270
269
  router: this.router,
271
270
  sessionTransport: this,
272
- connections: this.peerManager!.connections,
273
271
  localPeerDescriptor: this.localPeerDescriptor!,
274
272
  serviceId: this.config.serviceId,
273
+ localDataStore: this.localDataStore,
275
274
  addContact: (contact: PeerDescriptor) => this.peerManager!.addContact(contact),
276
- localDataStore: this.localDataStore
275
+ createDhtNodeRpcRemote: (peerDescriptor: PeerDescriptor) => this.createDhtNodeRpcRemote(peerDescriptor),
277
276
  })
278
277
  this.storeManager = new StoreManager({
279
278
  rpcCommunicator: this.rpcCommunicator,
@@ -296,7 +295,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
296
295
  )
297
296
  }
298
297
  })
299
- this.on('contactAdded', (peerDescriptor: PeerDescriptor) => {
298
+ this.on('closestContactAdded', (peerDescriptor: PeerDescriptor) => {
300
299
  this.storeManager!.onContactAdded(peerDescriptor)
301
300
  })
302
301
  this.bindRpcLocalMethods()
@@ -309,28 +308,27 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
309
308
  localNodeId: this.getNodeId(),
310
309
  localPeerDescriptor: this.localPeerDescriptor!,
311
310
  connectionLocker: this.connectionLocker,
312
- peerDiscoveryQueryBatchSize: this.config.peerDiscoveryQueryBatchSize,
313
- isLayer0: (this.connectionLocker !== undefined),
311
+ lockId: this.config.serviceId,
314
312
  createDhtNodeRpcRemote: (peerDescriptor: PeerDescriptor) => this.createDhtNodeRpcRemote(peerDescriptor),
315
- lockId: this.config.serviceId
313
+ hasConnection: (nodeId: DhtAddress) => this.transport!.hasConnection(nodeId)
316
314
  })
317
- this.peerManager.on('contactRemoved', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) => {
318
- this.emit('contactRemoved', peerDescriptor, activeContacts)
315
+ this.peerManager.on('closestContactRemoved', (peerDescriptor: PeerDescriptor) => {
316
+ this.emit('closestContactRemoved', peerDescriptor)
319
317
  })
320
- this.peerManager.on('contactAdded', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) =>
321
- this.emit('contactAdded', peerDescriptor, activeContacts)
318
+ this.peerManager.on('closestContactAdded', (peerDescriptor: PeerDescriptor) =>
319
+ this.emit('closestContactAdded', peerDescriptor)
322
320
  )
323
- this.peerManager.on('randomContactRemoved', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) =>
324
- this.emit('randomContactRemoved', peerDescriptor, activeContacts)
321
+ this.peerManager.on('randomContactRemoved', (peerDescriptor: PeerDescriptor) =>
322
+ this.emit('randomContactRemoved', peerDescriptor)
325
323
  )
326
- this.peerManager.on('randomContactAdded', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) =>
327
- this.emit('randomContactAdded', peerDescriptor, activeContacts)
324
+ this.peerManager.on('randomContactAdded', (peerDescriptor: PeerDescriptor) =>
325
+ this.emit('randomContactAdded', peerDescriptor)
328
326
  )
329
- this.peerManager.on('ringContactRemoved', (peerDescriptor: PeerDescriptor, activeContacts: RingContacts) => {
330
- this.emit('ringContactRemoved', peerDescriptor, activeContacts)
327
+ this.peerManager.on('ringContactRemoved', (peerDescriptor: PeerDescriptor) => {
328
+ this.emit('ringContactRemoved', peerDescriptor)
331
329
  })
332
- this.peerManager.on('ringContactAdded', (peerDescriptor: PeerDescriptor, activeContacts: RingContacts) => {
333
- this.emit('ringContactAdded', peerDescriptor, activeContacts)
330
+ this.peerManager.on('ringContactAdded', (peerDescriptor: PeerDescriptor) => {
331
+ this.emit('ringContactAdded', peerDescriptor)
334
332
  })
335
333
  this.peerManager.on('kBucketEmpty', () => {
336
334
  if (!this.peerDiscovery!.isJoinOngoing()
@@ -348,18 +346,22 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
348
346
  }
349
347
  })
350
348
  this.transport!.on('connected', (peerDescriptor: PeerDescriptor) => {
351
- this.peerManager!.onContactConnected(peerDescriptor)
352
349
  this.router!.onNodeConnected(peerDescriptor)
353
350
  this.emit('connected', peerDescriptor)
354
351
  })
355
352
  this.transport!.on('disconnected', (peerDescriptor: PeerDescriptor, gracefulLeave: boolean) => {
356
- this.peerManager!.onContactDisconnected(getNodeIdFromPeerDescriptor(peerDescriptor), gracefulLeave)
353
+ const isLayer0 = (this.connectionLocker !== undefined)
354
+ if (isLayer0) {
355
+ const nodeId = getNodeIdFromPeerDescriptor(peerDescriptor)
356
+ if (gracefulLeave) {
357
+ this.peerManager!.removeContact(nodeId)
358
+ } else {
359
+ this.peerManager!.removeNeighbor(nodeId)
360
+ }
361
+ }
357
362
  this.router!.onNodeDisconnected(peerDescriptor)
358
363
  this.emit('disconnected', peerDescriptor, gracefulLeave)
359
364
  })
360
- this.transport!.getConnections().forEach((peer) => {
361
- this.peerManager!.onContactConnected(peer)
362
- })
363
365
  }
364
366
 
365
367
  private bindRpcLocalMethods(): void {
@@ -368,11 +370,11 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
368
370
  }
369
371
  const dhtNodeRpcLocal = new DhtNodeRpcLocal({
370
372
  peerDiscoveryQueryBatchSize: this.config.peerDiscoveryQueryBatchSize,
371
- getClosestPeersTo: (nodeId: DhtAddress, limit: number) => {
373
+ getClosestNeighborsTo: (nodeId: DhtAddress, limit: number) => {
372
374
  return this.peerManager!.getClosestNeighborsTo(nodeId, limit)
373
375
  .map((dhtPeer: DhtNodeRpcRemote) => dhtPeer.getPeerDescriptor())
374
376
  },
375
- getClosestRingPeersTo: (ringIdRaw: RingIdRaw, limit: number) => {
377
+ getClosestRingContactsTo: (ringIdRaw: RingIdRaw, limit: number) => {
376
378
  return this.getClosestRingContactsTo(ringIdRaw, limit)
377
379
  },
378
380
  addContact: (contact: PeerDescriptor) => this.peerManager!.addContact(contact),
@@ -432,9 +434,22 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
432
434
  }
433
435
 
434
436
  public getClosestContacts(limit?: number): PeerDescriptor[] {
435
- return this.peerManager!.getClosestContactsTo(
436
- this.getNodeId(),
437
- limit).map((peer) => peer.getPeerDescriptor())
437
+ return this.peerManager!.getClosestContacts()
438
+ .getClosestContacts(limit)
439
+ .map((peer) => peer.getPeerDescriptor())
440
+ }
441
+
442
+ // TODO remove defaultContactQueryLimit parameter from RandomContactList#getContacts and use explicit value here?
443
+ getRandomContacts(): PeerDescriptor[] {
444
+ return this.peerManager!.getRandomContacts().getContacts().map((c) => c.getPeerDescriptor())
445
+ }
446
+
447
+ getRingContacts(): RingContacts {
448
+ const contacts = this.peerManager!.getRingContacts().getClosestContacts()
449
+ return {
450
+ left: contacts.left.map((c) => c.getPeerDescriptor()),
451
+ right: contacts.right.map((c) => c.getPeerDescriptor())
452
+ }
438
453
  }
439
454
 
440
455
  public getClosestRingContactsTo(ringIdRaw: RingIdRaw, limit?: number): RingContacts {
@@ -470,7 +485,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
470
485
 
471
486
  private getConnectedEntryPoints(): PeerDescriptor[] {
472
487
  return this.config.entryPoints !== undefined ? this.config.entryPoints.filter((entryPoint) =>
473
- this.peerManager!.connections.has(getNodeIdFromPeerDescriptor(entryPoint))
488
+ this.transport!.hasConnection(getNodeIdFromPeerDescriptor(entryPoint))
474
489
  ) : []
475
490
  }
476
491
 
@@ -544,16 +559,20 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
544
559
  return this.localPeerDescriptor!
545
560
  }
546
561
 
547
- public getConnections(): PeerDescriptor[] {
548
- return Array.from(this.peerManager!.connections.values()).map((peer) => peer.getPeerDescriptor())
549
- }
550
-
551
562
  public getNeighbors(): PeerDescriptor[] {
552
563
  return this.started ? this.peerManager!.getNeighbors() : []
553
564
  }
554
565
 
566
+ public getConnections(): PeerDescriptor[] {
567
+ return this.transport!.getConnections()
568
+ }
569
+
555
570
  public getConnectionCount(): number {
556
- return this.peerManager!.getConnectionCount()
571
+ return this.transport!.getConnectionCount()
572
+ }
573
+
574
+ public hasConnection(nodeId: DhtAddress): boolean {
575
+ return this.transport!.hasConnection(nodeId)
557
576
  }
558
577
 
559
578
  public getLocalLockedConnectionCount(): number {
@@ -573,7 +592,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
573
592
  if (!this.peerManager) {
574
593
  return false
575
594
  } else {
576
- return (this.peerManager.getConnectionCount() > 0)
595
+ return (this.getConnectionCount() > 0)
577
596
  }
578
597
  }, this.config.networkConnectivityTimeout, 100, this.abortController.signal)
579
598
  }
@@ -18,8 +18,8 @@ import { RingContacts } from './contact/RingContactList'
18
18
 
19
19
  interface DhtNodeRpcLocalConfig {
20
20
  peerDiscoveryQueryBatchSize: number
21
- getClosestPeersTo: (nodeId: DhtAddress, limit: number) => PeerDescriptor[]
22
- getClosestRingPeersTo: (id: RingIdRaw, limit: number) => RingContacts
21
+ getClosestNeighborsTo: (nodeId: DhtAddress, limit: number) => PeerDescriptor[]
22
+ getClosestRingContactsTo: (id: RingIdRaw, limit: number) => RingContacts
23
23
  addContact: (contact: PeerDescriptor) => void
24
24
  removeContact: (nodeId: DhtAddress) => void
25
25
  }
@@ -37,18 +37,19 @@ export class DhtNodeRpcLocal implements IDhtNodeRpc {
37
37
  async getClosestPeers(request: ClosestPeersRequest, context: ServerCallContext): Promise<ClosestPeersResponse> {
38
38
  this.config.addContact((context as DhtCallContext).incomingSourceDescriptor!)
39
39
  const response = {
40
- peers: this.config.getClosestPeersTo(getDhtAddressFromRaw(request.nodeId), this.config.peerDiscoveryQueryBatchSize),
40
+ peers: this.config.getClosestNeighborsTo(getDhtAddressFromRaw(request.nodeId), this.config.peerDiscoveryQueryBatchSize),
41
41
  requestId: request.requestId
42
42
  }
43
43
  return response
44
44
  }
45
45
 
46
+ // TODO rename to getClosestRingContacts
46
47
  async getClosestRingPeers(request: ClosestRingPeersRequest, context: ServerCallContext): Promise<ClosestRingPeersResponse> {
47
48
  this.config.addContact((context as DhtCallContext).incomingSourceDescriptor!)
48
- const closestPeers = this.config.getClosestRingPeersTo(request.ringId as RingIdRaw, this.config.peerDiscoveryQueryBatchSize)
49
+ const closestContacts = this.config.getClosestRingContactsTo(request.ringId as RingIdRaw, this.config.peerDiscoveryQueryBatchSize)
49
50
  const response = {
50
- leftPeers: closestPeers.left,
51
- rightPeers: closestPeers.right,
51
+ leftPeers: closestContacts.left,
52
+ rightPeers: closestContacts.right,
52
53
  requestId: request.requestId
53
54
  }
54
55
  return response
@@ -58,6 +58,7 @@ export class DhtNodeRpcRemote extends RpcRemote<DhtNodeRpcClient> implements KBu
58
58
  }
59
59
  }
60
60
 
61
+ // TODO rename to getClosestRingContacts (breaking change)
61
62
  async getClosestRingPeers(ringIdRaw: RingIdRaw): Promise<RingContacts> {
62
63
  logger.trace(`Requesting getClosestRingPeers on ${this.serviceId} from ${this.getNodeId()}`)
63
64
  const request: ClosestRingPeersRequest = {
@@ -7,11 +7,11 @@ import {
7
7
  } from '../proto/packages/dht/protos/DhtRpc'
8
8
  import { DhtNodeRpcRemote } from './DhtNodeRpcRemote'
9
9
  import { RandomContactList } from './contact/RandomContactList'
10
- import { SortedContactList } from './contact/SortedContactList'
10
+ import { ReadonlySortedContactList, SortedContactList } from './contact/SortedContactList'
11
11
  import { ConnectionLocker } from '../connection/ConnectionManager'
12
12
  import EventEmitter from 'eventemitter3'
13
13
  import { DhtAddress, DhtAddressRaw, getNodeIdFromPeerDescriptor, getRawFromDhtAddress } from '../identifiers'
14
- import { RingContactList, RingContacts } from './contact/RingContactList'
14
+ import { RingContactList } from './contact/RingContactList'
15
15
  import { RingIdRaw, getRingIdRawFromPeerDescriptor } from './contact/ringIdentifiers'
16
16
  import { LockID } from '../connection/ConnectionLockStates'
17
17
 
@@ -20,22 +20,21 @@ const logger = new Logger(module)
20
20
  interface PeerManagerConfig {
21
21
  numberOfNodesPerKBucket: number
22
22
  maxContactListSize: number
23
- peerDiscoveryQueryBatchSize: number
24
23
  localNodeId: DhtAddress
25
24
  localPeerDescriptor: PeerDescriptor
26
25
  connectionLocker?: ConnectionLocker
27
- isLayer0: boolean
28
26
  lockId: LockID
29
27
  createDhtNodeRpcRemote: (peerDescriptor: PeerDescriptor) => DhtNodeRpcRemote
28
+ hasConnection: (nodeId: DhtAddress) => boolean
30
29
  }
31
30
 
32
31
  export interface PeerManagerEvents {
33
- contactAdded: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
34
- contactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
35
- randomContactAdded: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
36
- randomContactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
37
- ringContactAdded: (peerDescriptor: PeerDescriptor, closestPeers: RingContacts) => void
38
- ringContactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: RingContacts) => void
32
+ closestContactAdded: (peerDescriptor: PeerDescriptor) => void
33
+ closestContactRemoved: (peerDescriptor: PeerDescriptor) => void
34
+ randomContactAdded: (peerDescriptor: PeerDescriptor) => void
35
+ randomContactRemoved: (peerDescriptor: PeerDescriptor) => void
36
+ ringContactAdded: (peerDescriptor: PeerDescriptor) => void
37
+ ringContactRemoved: (peerDescriptor: PeerDescriptor) => void
39
38
  kBucketEmpty: () => void
40
39
  }
41
40
 
@@ -52,8 +51,6 @@ export class PeerManager extends EventEmitter<PeerManagerEvents> {
52
51
  // * 'contacts' are all non-unresponsive nodes that we know about
53
52
 
54
53
  private neighbors: KBucket<DhtNodeRpcRemote>
55
- // Nodes that are connected to this node on Layer0
56
- public readonly connections: Map<DhtAddress, DhtNodeRpcRemote> = new Map()
57
54
  private closestContacts: SortedContactList<DhtNodeRpcRemote>
58
55
  private activeContacts: Set<DhtAddress>
59
56
  private ringContacts: RingContactList<DhtNodeRpcRemote>
@@ -70,11 +67,11 @@ export class PeerManager extends EventEmitter<PeerManagerEvents> {
70
67
  numberOfNodesToPing: this.config.numberOfNodesPerKBucket
71
68
  })
72
69
  this.ringContacts = new RingContactList<DhtNodeRpcRemote>(getRingIdRawFromPeerDescriptor(this.config.localPeerDescriptor))
73
- this.ringContacts.on('ringContactAdded', (peerDescriptor: PeerDescriptor, closestPeers: RingContacts) => {
74
- this.emit('ringContactAdded', peerDescriptor, closestPeers)
70
+ this.ringContacts.on('contactAdded', (contact: DhtNodeRpcRemote) => {
71
+ this.emit('ringContactAdded', contact.getPeerDescriptor())
75
72
  })
76
- this.ringContacts.on('ringContactRemoved', (peerDescriptor: PeerDescriptor, closestPeers: RingContacts) => {
77
- this.emit('ringContactRemoved', peerDescriptor, closestPeers)
73
+ this.ringContacts.on('contactRemoved', (contact: DhtNodeRpcRemote) => {
74
+ this.emit('ringContactRemoved', contact.getPeerDescriptor())
78
75
  })
79
76
  this.neighbors.on('ping', (oldContacts: DhtNodeRpcRemote[], newContact: DhtNodeRpcRemote) => this.onKBucketPing(oldContacts, newContact))
80
77
  this.neighbors.on('removed', (contact: DhtNodeRpcRemote) => this.onKBucketRemoved(getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())))
@@ -87,23 +84,23 @@ export class PeerManager extends EventEmitter<PeerManagerEvents> {
87
84
  maxSize: this.config.maxContactListSize,
88
85
  allowToContainReferenceId: false
89
86
  })
90
- this.closestContacts.on('contactRemoved', (removedContact: DhtNodeRpcRemote, activeContacts: DhtNodeRpcRemote[]) => {
87
+ this.closestContacts.on('contactRemoved', (contact: DhtNodeRpcRemote) => {
91
88
  if (this.stopped) {
92
89
  return
93
90
  }
94
- this.emit('contactRemoved', removedContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
95
- this.randomContacts.addContact(this.config.createDhtNodeRpcRemote(removedContact.getPeerDescriptor()))
91
+ this.emit('closestContactRemoved', contact.getPeerDescriptor())
92
+ this.randomContacts.addContact(this.config.createDhtNodeRpcRemote(contact.getPeerDescriptor()))
96
93
  })
97
- this.closestContacts.on('contactAdded', (contactAdded: DhtNodeRpcRemote, activeContacts: DhtNodeRpcRemote[]) =>
98
- this.emit('contactAdded', contactAdded.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
94
+ this.closestContacts.on('contactAdded', (contact: DhtNodeRpcRemote) =>
95
+ this.emit('closestContactAdded', contact.getPeerDescriptor())
99
96
  )
100
97
  this.activeContacts = new Set()
101
98
  this.randomContacts = new RandomContactList(this.config.localNodeId, this.config.maxContactListSize)
102
- this.randomContacts.on('contactRemoved', (removedContact: DhtNodeRpcRemote, activeContacts: DhtNodeRpcRemote[]) =>
103
- this.emit('randomContactRemoved', removedContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
99
+ this.randomContacts.on('contactRemoved', (removedContact: DhtNodeRpcRemote) =>
100
+ this.emit('randomContactRemoved', removedContact.getPeerDescriptor())
104
101
  )
105
- this.randomContacts.on('contactAdded', (contactAdded: DhtNodeRpcRemote, activeContacts: DhtNodeRpcRemote[]) =>
106
- this.emit('randomContactAdded', contactAdded.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
102
+ this.randomContacts.on('contactAdded', (contactAdded: DhtNodeRpcRemote) =>
103
+ this.emit('randomContactAdded', contactAdded.getPeerDescriptor())
107
104
  )
108
105
  }
109
106
 
@@ -143,7 +140,7 @@ export class PeerManager extends EventEmitter<PeerManagerEvents> {
143
140
  const nodeId = getNodeIdFromPeerDescriptor(peerDescriptor)
144
141
  // Important to lock here, before the ping result is known
145
142
  this.config.connectionLocker?.weakLockConnection(nodeId, this.config.lockId)
146
- if (this.connections.has(contact.getNodeId())) {
143
+ if (this.config.hasConnection(contact.getNodeId())) {
147
144
  logger.trace(`Added new contact ${nodeId}`)
148
145
  } else { // open connection by pinging
149
146
  logger.trace('starting ping ' + nodeId)
@@ -156,7 +153,6 @@ export class PeerManager extends EventEmitter<PeerManagerEvents> {
156
153
  this.removeContact(nodeId)
157
154
  this.addClosestContactToBucket()
158
155
  }
159
- return
160
156
  }).catch((_e) => {
161
157
  this.config.connectionLocker?.weakUnlockConnection(nodeId, this.config.lockId)
162
158
  this.removeContact(nodeId)
@@ -185,35 +181,6 @@ export class PeerManager extends EventEmitter<PeerManagerEvents> {
185
181
  return undefined
186
182
  }
187
183
 
188
- onContactConnected(peerDescriptor: PeerDescriptor): void {
189
- const nodeId = getNodeIdFromPeerDescriptor(peerDescriptor)
190
- if (nodeId === this.config.localNodeId) {
191
- logger.error('handleConnected() to self')
192
- }
193
- const rpcRemote = this.config.createDhtNodeRpcRemote(peerDescriptor)
194
- if (!this.connections.has(nodeId)) {
195
- this.connections.set(nodeId, rpcRemote)
196
- logger.trace('connectionschange add ' + this.connections.size)
197
- } else {
198
- logger.trace('new connection not set to connections, there is already a connection with the peer ID')
199
- }
200
- logger.trace('connected: ' + nodeId + ' ' + this.connections.size)
201
- }
202
-
203
- onContactDisconnected(nodeId: DhtAddress, gracefulLeave: boolean): void {
204
- logger.trace('disconnected: ' + nodeId)
205
- this.connections.delete(nodeId)
206
- if (this.config.isLayer0) {
207
- this.neighbors.remove(getRawFromDhtAddress(nodeId))
208
- if (gracefulLeave === true) {
209
- logger.trace(nodeId + ' ' + 'onTransportDisconnected with gracefulLeave ' + gracefulLeave)
210
- this.removeContact(nodeId)
211
- } else {
212
- logger.trace(nodeId + ' ' + 'onTransportDisconnected with gracefulLeave ' + gracefulLeave)
213
- }
214
- }
215
- }
216
-
217
184
  removeContact(nodeId: DhtAddress): void {
218
185
  if (this.stopped) {
219
186
  return
@@ -226,6 +193,10 @@ export class PeerManager extends EventEmitter<PeerManagerEvents> {
226
193
  this.randomContacts.removeContact(nodeId)
227
194
  }
228
195
 
196
+ removeNeighbor(nodeId: DhtAddress): void {
197
+ this.neighbors.remove(getRawFromDhtAddress(nodeId))
198
+ }
199
+
229
200
  stop(): void {
230
201
  this.stopped = true
231
202
  this.neighbors.toArray().forEach((rpcRemote: DhtNodeRpcRemote) => {
@@ -239,7 +210,6 @@ export class PeerManager extends EventEmitter<PeerManagerEvents> {
239
210
  })
240
211
  this.closestContacts.stop()
241
212
  this.randomContacts.stop()
242
- this.connections.clear()
243
213
  }
244
214
 
245
215
  getClosestNeighborsTo(referenceId: DhtAddress, limit?: number, excludedNodeIds?: Set<DhtAddress>): DhtNodeRpcRemote[] {
@@ -253,18 +223,8 @@ export class PeerManager extends EventEmitter<PeerManagerEvents> {
253
223
  return closest.getClosestContacts()
254
224
  }
255
225
 
256
- // TODO reduce copy-paste?
257
- getClosestContactsTo(referenceId: DhtAddress, limit?: number, excludedNodeIds?: Set<DhtAddress>): DhtNodeRpcRemote[] {
258
- const closest = new SortedContactList<DhtNodeRpcRemote>({
259
- referenceId,
260
- allowToContainReferenceId: true,
261
- excludedNodeIds,
262
- maxSize: limit
263
- })
264
- for (const contact of this.closestContacts.getAllContactsInUndefinedOrder()) {
265
- closest.addContact(contact)
266
- }
267
- return closest.getClosestContacts()
226
+ getClosestContacts(): ReadonlySortedContactList<DhtNodeRpcRemote> {
227
+ return this.closestContacts
268
228
  }
269
229
 
270
230
  getClosestRingContactsTo(
@@ -279,15 +239,20 @@ export class PeerManager extends EventEmitter<PeerManagerEvents> {
279
239
  this.ringContacts.getAllContacts().map((contact) => closest.addContact(contact))
280
240
  return closest.getClosestContacts(limit ?? 8)
281
241
  }
242
+
243
+ getRandomContacts(): RandomContactList<DhtNodeRpcRemote> {
244
+ return this.randomContacts
245
+ }
246
+
247
+ getRingContacts(): RingContactList<DhtNodeRpcRemote> {
248
+ return this.ringContacts
249
+ }
282
250
 
251
+ // TODO rename getNearbyContactsCount
283
252
  getContactCount(excludedNodeIds?: Set<DhtAddress>): number {
284
253
  return this.closestContacts.getSize(excludedNodeIds)
285
254
  }
286
255
 
287
- getConnectionCount(): number {
288
- return this.connections.size
289
- }
290
-
291
256
  getNeighborCount(): number {
292
257
  return this.neighbors.count()
293
258
  }