@streamr/trackerless-network 100.0.0-pretestnet.4 → 100.0.0-rc.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 (241) hide show
  1. package/README.md +57 -0
  2. package/dist/package.json +11 -11
  3. package/dist/src/NetworkNode.d.ts +6 -5
  4. package/dist/src/NetworkNode.js +9 -2
  5. package/dist/src/NetworkNode.js.map +1 -1
  6. package/dist/src/NetworkStack.d.ts +13 -9
  7. package/dist/src/NetworkStack.js +80 -12
  8. package/dist/src/NetworkStack.js.map +1 -1
  9. package/dist/src/exports.d.ts +4 -3
  10. package/dist/src/exports.js +12 -1
  11. package/dist/src/exports.js.map +1 -1
  12. package/dist/src/logic/DeliveryRpcLocal.d.ts +4 -5
  13. package/dist/src/logic/DeliveryRpcLocal.js +6 -5
  14. package/dist/src/logic/DeliveryRpcLocal.js.map +1 -1
  15. package/dist/src/logic/DeliveryRpcRemote.d.ts +5 -4
  16. package/dist/src/logic/DeliveryRpcRemote.js +4 -3
  17. package/dist/src/logic/DeliveryRpcRemote.js.map +1 -1
  18. package/dist/src/logic/DuplicateMessageDetector.d.ts +3 -3
  19. package/dist/src/logic/DuplicateMessageDetector.js +10 -6
  20. package/dist/src/logic/DuplicateMessageDetector.js.map +1 -1
  21. package/dist/src/logic/EntryPointDiscovery.d.ts +8 -5
  22. package/dist/src/logic/EntryPointDiscovery.js +24 -15
  23. package/dist/src/logic/EntryPointDiscovery.js.map +1 -1
  24. package/dist/src/logic/Layer0Node.d.ts +6 -4
  25. package/dist/src/logic/Layer1Node.d.ts +12 -6
  26. package/dist/src/logic/NodeList.d.ts +13 -15
  27. package/dist/src/logic/NodeList.js +18 -15
  28. package/dist/src/logic/NodeList.js.map +1 -1
  29. package/dist/src/logic/RandomGraphNode.d.ts +26 -22
  30. package/dist/src/logic/RandomGraphNode.js +82 -52
  31. package/dist/src/logic/RandomGraphNode.js.map +1 -1
  32. package/dist/src/logic/StreamrNode.d.ts +6 -6
  33. package/dist/src/logic/StreamrNode.js +53 -37
  34. package/dist/src/logic/StreamrNode.js.map +1 -1
  35. package/dist/src/logic/createRandomGraphNode.d.ts +2 -2
  36. package/dist/src/logic/createRandomGraphNode.js +33 -21
  37. package/dist/src/logic/createRandomGraphNode.js.map +1 -1
  38. package/dist/src/logic/formStreamPartDeliveryServiceId.d.ts +2 -1
  39. package/dist/src/logic/formStreamPartDeliveryServiceId.js.map +1 -1
  40. package/dist/src/logic/inspect/InspectSession.d.ts +4 -3
  41. package/dist/src/logic/inspect/InspectSession.js +6 -2
  42. package/dist/src/logic/inspect/InspectSession.js.map +1 -1
  43. package/dist/src/logic/inspect/Inspector.d.ts +11 -16
  44. package/dist/src/logic/inspect/Inspector.js +21 -9
  45. package/dist/src/logic/inspect/Inspector.js.map +1 -1
  46. package/dist/src/logic/neighbor-discovery/HandshakeRpcLocal.d.ts +7 -9
  47. package/dist/src/logic/neighbor-discovery/HandshakeRpcLocal.js +55 -32
  48. package/dist/src/logic/neighbor-discovery/HandshakeRpcLocal.js.map +1 -1
  49. package/dist/src/logic/neighbor-discovery/HandshakeRpcRemote.d.ts +8 -6
  50. package/dist/src/logic/neighbor-discovery/HandshakeRpcRemote.js +25 -16
  51. package/dist/src/logic/neighbor-discovery/HandshakeRpcRemote.js.map +1 -1
  52. package/dist/src/logic/neighbor-discovery/Handshaker.d.ts +9 -15
  53. package/dist/src/logic/neighbor-discovery/Handshaker.js +68 -44
  54. package/dist/src/logic/neighbor-discovery/Handshaker.js.map +1 -1
  55. package/dist/src/logic/neighbor-discovery/NeighborFinder.d.ts +8 -10
  56. package/dist/src/logic/neighbor-discovery/NeighborFinder.js +12 -2
  57. package/dist/src/logic/neighbor-discovery/NeighborFinder.js.map +1 -1
  58. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.d.ts +7 -10
  59. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js +11 -9
  60. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js.map +1 -1
  61. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.d.ts +8 -4
  62. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js +33 -24
  63. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js.map +1 -1
  64. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.d.ts +5 -4
  65. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.js +4 -5
  66. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.js.map +1 -1
  67. package/dist/src/logic/node-info/NodeInfoClient.d.ts +9 -0
  68. package/dist/src/logic/node-info/NodeInfoClient.js +21 -0
  69. package/dist/src/logic/node-info/NodeInfoClient.js.map +1 -0
  70. package/dist/src/logic/node-info/NodeInfoRpcLocal.d.ts +12 -0
  71. package/dist/src/logic/node-info/NodeInfoRpcLocal.js +22 -0
  72. package/dist/src/logic/node-info/NodeInfoRpcLocal.js.map +1 -0
  73. package/dist/src/logic/node-info/NodeInfoRpcRemote.d.ts +6 -0
  74. package/dist/src/logic/node-info/NodeInfoRpcRemote.js +11 -0
  75. package/dist/src/logic/node-info/NodeInfoRpcRemote.js.map +1 -0
  76. package/dist/src/logic/propagation/FifoMapWithTTL.js +7 -3
  77. package/dist/src/logic/propagation/FifoMapWithTTL.js.map +1 -1
  78. package/dist/src/logic/propagation/Propagation.d.ts +4 -4
  79. package/dist/src/logic/propagation/Propagation.js +4 -0
  80. package/dist/src/logic/propagation/Propagation.js.map +1 -1
  81. package/dist/src/logic/propagation/PropagationTaskStore.d.ts +2 -2
  82. package/dist/src/logic/propagation/PropagationTaskStore.js +1 -0
  83. package/dist/src/logic/propagation/PropagationTaskStore.js.map +1 -1
  84. package/dist/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.js +1 -1
  85. package/dist/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.js.map +1 -1
  86. package/dist/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.js +1 -1
  87. package/dist/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.js.map +1 -1
  88. package/dist/src/logic/protocol-integration/stream-message/StreamMessageTranslator.js +87 -53
  89. package/dist/src/logic/protocol-integration/stream-message/StreamMessageTranslator.js.map +1 -1
  90. package/dist/src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils.d.ts +7 -0
  91. package/dist/src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils.js +32 -0
  92. package/dist/src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils.js.map +1 -0
  93. package/dist/src/logic/proxy/ProxyClient.d.ts +8 -6
  94. package/dist/src/logic/proxy/ProxyClient.js +40 -28
  95. package/dist/src/logic/proxy/ProxyClient.js.map +1 -1
  96. package/dist/src/logic/proxy/ProxyConnectionRpcLocal.d.ts +6 -7
  97. package/dist/src/logic/proxy/ProxyConnectionRpcLocal.js +8 -8
  98. package/dist/src/logic/proxy/ProxyConnectionRpcLocal.js.map +1 -1
  99. package/dist/src/logic/proxy/ProxyConnectionRpcRemote.d.ts +3 -3
  100. package/dist/src/logic/proxy/ProxyConnectionRpcRemote.js +1 -1
  101. package/dist/src/logic/proxy/ProxyConnectionRpcRemote.js.map +1 -1
  102. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.d.ts +9 -4
  103. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.js +21 -6
  104. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.js.map +1 -1
  105. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcRemote.d.ts +4 -3
  106. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcRemote.js +13 -3
  107. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcRemote.js.map +1 -1
  108. package/dist/src/logic/utils.js.map +1 -1
  109. package/dist/src/proto/google/protobuf/any.js +8 -8
  110. package/dist/src/proto/google/protobuf/any.js.map +1 -1
  111. package/dist/src/proto/google/protobuf/empty.js +2 -4
  112. package/dist/src/proto/google/protobuf/empty.js.map +1 -1
  113. package/dist/src/proto/google/protobuf/timestamp.js +10 -10
  114. package/dist/src/proto/google/protobuf/timestamp.js.map +1 -1
  115. package/dist/src/proto/packages/dht/protos/DhtRpc.client.d.ts +36 -49
  116. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js +54 -52
  117. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +1 -1
  118. package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +184 -234
  119. package/dist/src/proto/packages/dht/protos/DhtRpc.js +118 -168
  120. package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
  121. package/dist/src/proto/packages/dht/protos/DhtRpc.server.d.ts +20 -29
  122. package/dist/src/proto/packages/proto-rpc/protos/ProtoRpc.js +1 -1
  123. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.d.ts +42 -5
  124. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.js +52 -19
  125. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.js.map +1 -1
  126. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.d.ts +193 -28
  127. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js +129 -20
  128. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js.map +1 -1
  129. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.server.d.ts +20 -3
  130. package/dist/test/benchmark/first-message.js +14 -15
  131. package/dist/test/benchmark/first-message.js.map +1 -1
  132. package/dist/test/utils/utils.d.ts +2 -4
  133. package/dist/test/utils/utils.js +20 -19
  134. package/dist/test/utils/utils.js.map +1 -1
  135. package/jest.config.js +3 -38
  136. package/package.json +11 -11
  137. package/protos/NetworkRpc.proto +57 -12
  138. package/src/NetworkNode.ts +13 -6
  139. package/src/NetworkStack.ts +94 -16
  140. package/src/exports.ts +11 -3
  141. package/src/logic/DeliveryRpcLocal.ts +7 -8
  142. package/src/logic/DeliveryRpcRemote.ts +7 -5
  143. package/src/logic/DuplicateMessageDetector.ts +7 -7
  144. package/src/logic/EntryPointDiscovery.ts +26 -19
  145. package/src/logic/Layer0Node.ts +6 -4
  146. package/src/logic/Layer1Node.ts +21 -6
  147. package/src/logic/NodeList.ts +25 -26
  148. package/src/logic/RandomGraphNode.ts +148 -78
  149. package/src/logic/StreamrNode.ts +58 -41
  150. package/src/logic/createRandomGraphNode.ts +37 -25
  151. package/src/logic/formStreamPartDeliveryServiceId.ts +2 -1
  152. package/src/logic/inspect/InspectSession.ts +8 -4
  153. package/src/logic/inspect/Inspector.ts +34 -24
  154. package/src/logic/neighbor-discovery/HandshakeRpcLocal.ts +72 -38
  155. package/src/logic/neighbor-discovery/HandshakeRpcRemote.ts +32 -20
  156. package/src/logic/neighbor-discovery/Handshaker.ts +90 -75
  157. package/src/logic/neighbor-discovery/NeighborFinder.ts +18 -13
  158. package/src/logic/neighbor-discovery/NeighborUpdateManager.ts +19 -20
  159. package/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.ts +43 -33
  160. package/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.ts +6 -6
  161. package/src/logic/node-info/NodeInfoClient.ts +23 -0
  162. package/src/logic/node-info/NodeInfoRpcLocal.ts +28 -0
  163. package/src/logic/node-info/NodeInfoRpcRemote.ts +11 -0
  164. package/src/logic/propagation/Propagation.ts +7 -6
  165. package/src/logic/propagation/PropagationTaskStore.ts +2 -2
  166. package/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.ts +1 -1
  167. package/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.ts +1 -2
  168. package/src/logic/protocol-integration/stream-message/StreamMessageTranslator.ts +95 -69
  169. package/src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils.ts +37 -0
  170. package/src/logic/proxy/ProxyClient.ts +60 -40
  171. package/src/logic/proxy/ProxyConnectionRpcLocal.ts +15 -19
  172. package/src/logic/proxy/ProxyConnectionRpcRemote.ts +3 -3
  173. package/src/logic/temporary-connection/TemporaryConnectionRpcLocal.ts +30 -10
  174. package/src/logic/temporary-connection/TemporaryConnectionRpcRemote.ts +14 -4
  175. package/src/proto/google/protobuf/any.ts +4 -4
  176. package/src/proto/google/protobuf/empty.ts +2 -4
  177. package/src/proto/google/protobuf/timestamp.ts +4 -4
  178. package/src/proto/packages/dht/protos/DhtRpc.client.ts +50 -66
  179. package/src/proto/packages/dht/protos/DhtRpc.server.ts +21 -30
  180. package/src/proto/packages/dht/protos/DhtRpc.ts +242 -316
  181. package/src/proto/packages/proto-rpc/protos/ProtoRpc.ts +1 -1
  182. package/src/proto/packages/trackerless-network/protos/NetworkRpc.client.ts +49 -7
  183. package/src/proto/packages/trackerless-network/protos/NetworkRpc.server.ts +21 -4
  184. package/src/proto/packages/trackerless-network/protos/NetworkRpc.ts +251 -44
  185. package/test/benchmark/StreamPartIdDataKeyDistribution.test.ts +60 -0
  186. package/test/benchmark/first-message.ts +38 -17
  187. package/test/end-to-end/inspect.test.ts +16 -4
  188. package/test/end-to-end/proxy-and-full-node.test.ts +26 -13
  189. package/test/end-to-end/proxy-connections.test.ts +23 -11
  190. package/test/end-to-end/proxy-key-exchange.test.ts +25 -15
  191. package/test/end-to-end/random-graph-with-real-connections.test.ts +35 -32
  192. package/test/end-to-end/webrtc-full-node-network.test.ts +11 -12
  193. package/test/end-to-end/websocket-full-node-network.test.ts +12 -12
  194. package/test/integration/DeliveryRpcRemote.test.ts +6 -9
  195. package/test/integration/HandshakeRpcRemote.test.ts +6 -8
  196. package/test/integration/Handshakes.test.ts +29 -27
  197. package/test/integration/Inspect.test.ts +0 -2
  198. package/test/integration/NeighborUpdateRpcRemote.test.ts +6 -7
  199. package/test/integration/NetworkNode.test.ts +27 -12
  200. package/test/integration/NetworkRpc.test.ts +3 -5
  201. package/test/integration/NetworkStack.test.ts +2 -2
  202. package/test/integration/NodeInfoRpc.test.ts +104 -0
  203. package/test/integration/Propagation.test.ts +3 -3
  204. package/test/integration/RandomGraphNode-Layer1Node-Latencies.test.ts +24 -25
  205. package/test/integration/RandomGraphNode-Layer1Node.test.ts +26 -24
  206. package/test/integration/StreamrNode.test.ts +4 -16
  207. package/test/integration/joining-streams-on-offline-peers.test.ts +7 -31
  208. package/test/integration/stream-without-default-entrypoints.test.ts +22 -23
  209. package/test/integration/streamEntryPointReplacing.test.ts +94 -0
  210. package/test/unit/DeliveryRpcLocal.test.ts +2 -1
  211. package/test/unit/EntrypointDiscovery.test.ts +11 -8
  212. package/test/unit/GroupKeyResponseTranslator.test.ts +1 -1
  213. package/test/unit/HandshakeRpcLocal.test.ts +80 -28
  214. package/test/unit/Handshaker.test.ts +14 -9
  215. package/test/unit/InspectSession.test.ts +5 -6
  216. package/test/unit/Inspector.test.ts +3 -4
  217. package/test/unit/NeighborFinder.test.ts +12 -9
  218. package/test/unit/NeighborUpdateRpcLocal.test.ts +139 -0
  219. package/test/unit/NodeList.test.ts +77 -80
  220. package/test/unit/Propagation.test.ts +21 -16
  221. package/test/unit/ProxyConnectionRpcRemote.test.ts +18 -12
  222. package/test/unit/RandomGraphNode.test.ts +23 -20
  223. package/test/unit/StreamMessageTranslator.test.ts +10 -8
  224. package/test/unit/StreamPartIDDataKey.test.ts +12 -0
  225. package/test/unit/StreamrNode.test.ts +2 -0
  226. package/test/unit/TemporaryConnectionRpcLocal.test.ts +38 -0
  227. package/test/unit/oldStreamMessageBinaryUtils.test.ts +39 -0
  228. package/test/utils/mock/MockHandshaker.ts +6 -5
  229. package/test/utils/mock/MockLayer0Node.ts +7 -2
  230. package/test/utils/mock/MockLayer1Node.ts +5 -2
  231. package/test/utils/mock/MockNeighborFinder.ts +3 -2
  232. package/test/utils/mock/MockNeighborUpdateManager.ts +3 -2
  233. package/test/utils/mock/Transport.ts +1 -1
  234. package/test/utils/utils.ts +40 -25
  235. package/tsconfig.jest.json +5 -4
  236. package/tsconfig.node.json +2 -2
  237. package/dist/src/identifiers.d.ts +0 -4
  238. package/dist/src/identifiers.js +0 -9
  239. package/dist/src/identifiers.js.map +0 -1
  240. package/src/identifiers.ts +0 -8
  241. package/test/unit/GroupKeyRequestTranslator.test.ts +0 -36
@@ -1,26 +1,38 @@
1
- import { Empty } from '../../proto/google/protobuf/empty'
2
- import { InterleaveNotice, StreamPartHandshakeRequest, StreamPartHandshakeResponse } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
1
+ import {
2
+ InterleaveRequest,
3
+ InterleaveResponse,
4
+ StreamPartHandshakeRequest,
5
+ StreamPartHandshakeResponse
6
+ } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
3
7
  import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
4
8
  import { NodeList } from '../NodeList'
5
- import { ConnectionLocker, DhtCallContext, PeerDescriptor } from '@streamr/dht'
9
+ import {
10
+ DhtAddress,
11
+ DhtAddressRaw,
12
+ DhtCallContext,
13
+ PeerDescriptor,
14
+ getDhtAddressFromRaw,
15
+ getNodeIdFromPeerDescriptor
16
+ } from '@streamr/dht'
6
17
  import { IHandshakeRpc } from '../../proto/packages/trackerless-network/protos/NetworkRpc.server'
7
18
  import { HandshakeRpcRemote } from './HandshakeRpcRemote'
8
19
  import { DeliveryRpcRemote } from '../DeliveryRpcRemote'
9
- import { NodeID, getNodeIdFromPeerDescriptor } from '../../identifiers'
10
- import { binaryToHex } from '@streamr/utils'
20
+ import { Logger } from '@streamr/utils'
11
21
  import { StreamPartID } from '@streamr/protocol'
12
22
 
13
23
  interface HandshakeRpcLocalConfig {
14
24
  streamPartId: StreamPartID
15
- targetNeighbors: NodeList
16
- connectionLocker: ConnectionLocker
17
- ongoingHandshakes: Set<NodeID>
25
+ neighbors: NodeList
26
+ ongoingHandshakes: Set<DhtAddress>
27
+ ongoingInterleaves: Set<DhtAddress>
18
28
  maxNeighborCount: number
19
29
  createRpcRemote: (target: PeerDescriptor) => HandshakeRpcRemote
20
30
  createDeliveryRpcRemote: (peerDescriptor: PeerDescriptor) => DeliveryRpcRemote
21
- handshakeWithInterleaving: (target: PeerDescriptor, senderId: NodeID) => Promise<boolean>
31
+ handshakeWithInterleaving: (target: PeerDescriptor, senderId: DhtAddress) => Promise<boolean>
22
32
  }
23
33
 
34
+ const logger = new Logger(module)
35
+
24
36
  export class HandshakeRpcLocal implements IHandshakeRpc {
25
37
 
26
38
  private readonly config: HandshakeRpcLocalConfig
@@ -35,14 +47,22 @@ export class HandshakeRpcLocal implements IHandshakeRpc {
35
47
 
36
48
  private handleRequest(request: StreamPartHandshakeRequest, context: ServerCallContext): StreamPartHandshakeResponse {
37
49
  const senderDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
38
- const getInterleaveSourceIds = () => (request.interleaveSourceId !== undefined) ? [binaryToHex(request.interleaveSourceId) as NodeID] : []
39
- if (this.config.targetNeighbors.hasNode(senderDescriptor)
40
- || this.config.ongoingHandshakes.has(getNodeIdFromPeerDescriptor(senderDescriptor))
50
+ const getInterleaveSourceIds = () => (request.interleaveSourceId !== undefined) ? [getDhtAddressFromRaw(request.interleaveSourceId)] : []
51
+ const senderNodeId = getNodeIdFromPeerDescriptor(senderDescriptor)
52
+ if (this.config.ongoingInterleaves.has(senderNodeId)) {
53
+ return this.rejectHandshake(request)
54
+ } else if (this.config.neighbors.has(senderNodeId)
55
+ || this.config.ongoingHandshakes.has(senderNodeId)
41
56
  ) {
42
57
  return this.acceptHandshake(request, senderDescriptor)
43
- } else if (this.config.targetNeighbors.size() + this.config.ongoingHandshakes.size < this.config.maxNeighborCount) {
58
+ } else if (this.config.neighbors.size() + this.config.ongoingHandshakes.size < this.config.maxNeighborCount) {
44
59
  return this.acceptHandshake(request, senderDescriptor)
45
- } else if (this.config.targetNeighbors.size(getInterleaveSourceIds()) >= 2) {
60
+ } else if (
61
+ this.config.neighbors.size(getInterleaveSourceIds()) - this.config.ongoingInterleaves.size >= 2
62
+ && this.config.neighbors.size() <= this.config.maxNeighborCount
63
+ ) {
64
+ // Do not accept the handshakes requests if the target neighbor count can potentially drop below 2
65
+ // due to interleaving. This ensures that a stable number of connections is kept during high churn.
46
66
  return this.acceptHandshakeWithInterleaving(request, senderDescriptor)
47
67
  } else {
48
68
  return this.rejectHandshake(request)
@@ -54,8 +74,7 @@ export class HandshakeRpcLocal implements IHandshakeRpc {
54
74
  requestId: request.requestId,
55
75
  accepted: true
56
76
  }
57
- this.config.targetNeighbors.add(this.config.createDeliveryRpcRemote(requester))
58
- this.config.connectionLocker.lockConnection(requester, this.config.streamPartId)
77
+ this.config.neighbors.add(this.config.createDeliveryRpcRemote(requester))
59
78
  return res
60
79
  }
61
80
 
@@ -69,38 +88,53 @@ export class HandshakeRpcLocal implements IHandshakeRpc {
69
88
  }
70
89
 
71
90
  private acceptHandshakeWithInterleaving(request: StreamPartHandshakeRequest, requester: PeerDescriptor): StreamPartHandshakeResponse {
72
- const exclude = request.neighborIds.map((id: Uint8Array) => binaryToHex(id) as NodeID)
91
+ const exclude: DhtAddress[] = []
92
+ request.neighborIds.forEach((id: DhtAddressRaw) => exclude.push(getDhtAddressFromRaw(id)))
93
+ this.config.ongoingInterleaves.forEach((id) => exclude.push(id))
73
94
  exclude.push(getNodeIdFromPeerDescriptor(requester))
74
95
  if (request.interleaveSourceId !== undefined) {
75
- exclude.push(binaryToHex(request.interleaveSourceId) as NodeID)
96
+ exclude.push(getDhtAddressFromRaw(request.interleaveSourceId))
76
97
  }
77
- const furthest = this.config.targetNeighbors.getFurthest(exclude)
78
- const furthestPeerDescriptor = furthest ? furthest.getPeerDescriptor() : undefined
79
- if (furthest) {
80
- const remote = this.config.createRpcRemote(furthest.getPeerDescriptor())
81
- remote.interleaveNotice(requester)
82
- this.config.targetNeighbors.remove(furthest.getPeerDescriptor())
83
- this.config.connectionLocker.unlockConnection(furthestPeerDescriptor!, this.config.streamPartId)
98
+ const last = this.config.neighbors.getLast(exclude)
99
+ const lastPeerDescriptor = last ? last.getPeerDescriptor() : undefined
100
+ if (last) {
101
+ const nodeId = getNodeIdFromPeerDescriptor(last.getPeerDescriptor())
102
+ const remote = this.config.createRpcRemote(last.getPeerDescriptor())
103
+ this.config.ongoingInterleaves.add(nodeId)
104
+ // Run this with then catch instead of setImmediate to avoid changes in state
105
+ // eslint-disable-next-line promise/catch-or-return
106
+ remote.interleaveRequest(requester).then((response) => {
107
+ // If response is accepted, remove the last node from the target neighbors
108
+ // and unlock the connection
109
+ // If response is not accepted, keep the last node as a neighbor
110
+ if (response.accepted) {
111
+ this.config.neighbors.remove(getNodeIdFromPeerDescriptor(lastPeerDescriptor!))
112
+ }
113
+ return
114
+ }).catch(() => {
115
+ // no-op: InterleaveRequest cannot reject
116
+ }).finally(() => {
117
+ this.config.ongoingInterleaves.delete(nodeId)
118
+ })
84
119
  }
85
- this.config.targetNeighbors.add(this.config.createDeliveryRpcRemote(requester))
86
- this.config.connectionLocker.lockConnection(requester, this.config.streamPartId)
120
+ this.config.neighbors.add(this.config.createDeliveryRpcRemote(requester))
87
121
  return {
88
122
  requestId: request.requestId,
89
123
  accepted: true,
90
- interleaveTargetDescriptor: furthestPeerDescriptor
124
+ interleaveTargetDescriptor: lastPeerDescriptor
91
125
  }
92
126
  }
93
127
 
94
- async interleaveNotice(message: InterleaveNotice, context: ServerCallContext): Promise<Empty> {
95
- if (message.streamPartId === this.config.streamPartId) {
96
- const senderPeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
97
- const senderId = getNodeIdFromPeerDescriptor(senderPeerDescriptor)
98
- if (this.config.targetNeighbors.hasNodeById(senderId)) {
99
- this.config.connectionLocker.unlockConnection(senderPeerDescriptor, this.config.streamPartId)
100
- this.config.targetNeighbors.remove(senderPeerDescriptor)
101
- }
102
- this.config.handshakeWithInterleaving(message.interleaveTargetDescriptor!, senderId).catch((_e) => {})
128
+ async interleaveRequest(message: InterleaveRequest, context: ServerCallContext): Promise<InterleaveResponse> {
129
+ const senderPeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
130
+ const senderId = getNodeIdFromPeerDescriptor(senderPeerDescriptor)
131
+ try {
132
+ await this.config.handshakeWithInterleaving(message.interleaveTargetDescriptor!, senderId)
133
+ this.config.neighbors.remove(senderId)
134
+ return { accepted: true }
135
+ } catch (err) {
136
+ logger.debug(`interleaveRequest to ${getNodeIdFromPeerDescriptor(message.interleaveTargetDescriptor!)} failed: ${err}`)
137
+ return { accepted: false }
103
138
  }
104
- return Empty
105
139
  }
106
140
  }
@@ -1,9 +1,9 @@
1
- import { PeerDescriptor, Remote } from '@streamr/dht'
2
- import { Logger, hexToBinary } from '@streamr/utils'
1
+ import { DhtAddress, PeerDescriptor, RpcRemote, getNodeIdFromPeerDescriptor, getRawFromDhtAddress } from '@streamr/dht'
2
+ import { Logger } from '@streamr/utils'
3
3
  import { v4 } from 'uuid'
4
- import { NodeID, getNodeIdFromPeerDescriptor } from '../../identifiers'
5
- import { InterleaveNotice, StreamPartHandshakeRequest } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
6
- import { IHandshakeRpcClient } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
4
+ import { InterleaveRequest, InterleaveResponse, StreamPartHandshakeRequest } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
5
+ import { HandshakeRpcClient } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
6
+ import { StreamPartID } from '@streamr/protocol'
7
7
 
8
8
  const logger = new Logger(module)
9
9
 
@@ -12,19 +12,22 @@ interface HandshakeResponse {
12
12
  interleaveTargetDescriptor?: PeerDescriptor
13
13
  }
14
14
 
15
- export class HandshakeRpcRemote extends Remote<IHandshakeRpcClient> {
15
+ export const INTERLEAVE_REQUEST_TIMEOUT = 15000
16
+
17
+ export class HandshakeRpcRemote extends RpcRemote<HandshakeRpcClient> {
16
18
 
17
19
  async handshake(
18
- neighborIds: NodeID[],
19
- concurrentHandshakeTargetId?: NodeID,
20
- interleaveSourceId?: NodeID
20
+ streamPartId: StreamPartID,
21
+ neighborIds: DhtAddress[],
22
+ concurrentHandshakeTargetId?: DhtAddress,
23
+ interleaveSourceId?: DhtAddress
21
24
  ): Promise<HandshakeResponse> {
22
25
  const request: StreamPartHandshakeRequest = {
23
- streamPartId: this.getServiceId(),
26
+ streamPartId,
24
27
  requestId: v4(),
25
- neighborIds: neighborIds.map((id) => hexToBinary(id)),
26
- concurrentHandshakeTargetId: (concurrentHandshakeTargetId !== undefined) ? hexToBinary(concurrentHandshakeTargetId) : undefined,
27
- interleaveSourceId: (interleaveSourceId !== undefined) ? hexToBinary(interleaveSourceId) : undefined
28
+ neighborIds: neighborIds.map((id) => getRawFromDhtAddress(id)),
29
+ concurrentHandshakeTargetId: (concurrentHandshakeTargetId !== undefined) ? getRawFromDhtAddress(concurrentHandshakeTargetId) : undefined,
30
+ interleaveSourceId: (interleaveSourceId !== undefined) ? getRawFromDhtAddress(interleaveSourceId) : undefined
28
31
  }
29
32
  try {
30
33
  const response = await this.getClient().handshake(request, this.formDhtRpcOptions())
@@ -40,16 +43,25 @@ export class HandshakeRpcRemote extends Remote<IHandshakeRpcClient> {
40
43
  }
41
44
  }
42
45
 
43
- interleaveNotice(originatorDescriptor: PeerDescriptor): void {
44
- const notification: InterleaveNotice = {
45
- streamPartId: this.getServiceId(),
46
+ async interleaveRequest(originatorDescriptor: PeerDescriptor): Promise<InterleaveResponse> {
47
+ const request: InterleaveRequest = {
46
48
  interleaveTargetDescriptor: originatorDescriptor
47
49
  }
48
50
  const options = this.formDhtRpcOptions({
49
- notification: true
50
- })
51
- this.getClient().interleaveNotice(notification, options).catch(() => {
52
- logger.debug('Failed to send interleaveNotice')
51
+ connect: false,
52
+ timeout: INTERLEAVE_REQUEST_TIMEOUT
53
53
  })
54
+ try {
55
+ const res = await this.getClient().interleaveRequest(request, options)
56
+ return {
57
+ accepted: res.accepted
58
+ }
59
+ } catch (err) {
60
+ logger.debug(`interleaveRequest to ${getNodeIdFromPeerDescriptor(this.getPeerDescriptor())} failed: ${err}`)
61
+ return {
62
+ accepted: false
63
+ }
64
+ }
65
+
54
66
  }
55
67
  }
@@ -1,32 +1,32 @@
1
- import { ConnectionLocker, PeerDescriptor } from '@streamr/dht'
1
+ import { DhtAddress, PeerDescriptor, ListeningRpcCommunicator, getNodeIdFromPeerDescriptor } from '@streamr/dht'
2
2
  import { NodeList } from '../NodeList'
3
3
  import { DeliveryRpcRemote } from '../DeliveryRpcRemote'
4
- import { ProtoRpcClient, RpcCommunicator, toProtoRpcClient } from '@streamr/proto-rpc'
5
4
  import {
6
- HandshakeRpcClient,
7
- IHandshakeRpcClient, DeliveryRpcClient
5
+ DeliveryRpcClient, HandshakeRpcClient
8
6
  } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
9
7
  import {
10
- InterleaveNotice,
8
+ InterleaveRequest,
9
+ InterleaveResponse,
11
10
  StreamPartHandshakeRequest,
12
11
  StreamPartHandshakeResponse
13
12
  } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
14
13
  import { Logger } from '@streamr/utils'
15
14
  import { IHandshakeRpc } from '../../proto/packages/trackerless-network/protos/NetworkRpc.server'
16
- import { HandshakeRpcRemote } from './HandshakeRpcRemote'
15
+ import { HandshakeRpcRemote, INTERLEAVE_REQUEST_TIMEOUT } from './HandshakeRpcRemote'
17
16
  import { HandshakeRpcLocal } from './HandshakeRpcLocal'
18
- import { NodeID, getNodeIdFromPeerDescriptor } from '../../identifiers'
19
17
  import { StreamPartID } from '@streamr/protocol'
20
18
 
21
19
  interface HandshakerConfig {
22
20
  localPeerDescriptor: PeerDescriptor
23
21
  streamPartId: StreamPartID
24
- connectionLocker: ConnectionLocker
25
- targetNeighbors: NodeList
22
+ neighbors: NodeList
23
+ leftNodeView: NodeList
24
+ rightNodeView: NodeList
26
25
  nearbyNodeView: NodeList
27
26
  randomNodeView: NodeList
28
- rpcCommunicator: RpcCommunicator
27
+ rpcCommunicator: ListeningRpcCommunicator
29
28
  maxNeighborCount: number
29
+ ongoingHandshakes: Set<DhtAddress>
30
30
  rpcRequestTimeout?: number
31
31
  }
32
32
 
@@ -34,75 +34,93 @@ const logger = new Logger(module)
34
34
 
35
35
  const PARALLEL_HANDSHAKE_COUNT = 2
36
36
 
37
- export interface IHandshaker {
38
- attemptHandshakesOnContacts(excludedIds: NodeID[]): Promise<NodeID[]>
39
- getOngoingHandshakes(): Set<NodeID>
40
- }
41
-
42
- export class Handshaker implements IHandshaker {
37
+ export class Handshaker {
43
38
 
44
- private readonly ongoingHandshakes: Set<NodeID> = new Set()
45
39
  private config: HandshakerConfig
46
- private readonly client: ProtoRpcClient<IHandshakeRpcClient>
47
40
  private readonly rpcLocal: IHandshakeRpc
48
41
 
49
42
  constructor(config: HandshakerConfig) {
50
43
  this.config = config
51
- this.client = toProtoRpcClient(new HandshakeRpcClient(this.config.rpcCommunicator.getRpcClientTransport()))
52
44
  this.rpcLocal = new HandshakeRpcLocal({
53
45
  streamPartId: this.config.streamPartId,
54
- targetNeighbors: this.config.targetNeighbors,
55
- connectionLocker: this.config.connectionLocker,
56
- ongoingHandshakes: this.ongoingHandshakes,
46
+ neighbors: this.config.neighbors,
47
+ ongoingHandshakes: this.config.ongoingHandshakes,
48
+ ongoingInterleaves: new Set(),
57
49
  maxNeighborCount: this.config.maxNeighborCount,
58
- handshakeWithInterleaving: (target: PeerDescriptor, senderId: NodeID) => this.handshakeWithInterleaving(target, senderId),
50
+ handshakeWithInterleaving: (target: PeerDescriptor, senderId: DhtAddress) => this.handshakeWithInterleaving(target, senderId),
59
51
  createRpcRemote: (target: PeerDescriptor) => this.createRpcRemote(target),
60
52
  createDeliveryRpcRemote: (target: PeerDescriptor) => this.createDeliveryRpcRemote(target)
61
53
  })
62
- this.config.rpcCommunicator.registerRpcNotification(InterleaveNotice, 'interleaveNotice',
63
- (req: InterleaveNotice, context) => this.rpcLocal.interleaveNotice(req, context))
54
+ this.config.rpcCommunicator.registerRpcMethod(InterleaveRequest, InterleaveResponse, 'interleaveRequest',
55
+ (req: InterleaveRequest, context) => this.rpcLocal.interleaveRequest(req, context), { timeout: INTERLEAVE_REQUEST_TIMEOUT })
64
56
  this.config.rpcCommunicator.registerRpcMethod(StreamPartHandshakeRequest, StreamPartHandshakeResponse, 'handshake',
65
57
  (req: StreamPartHandshakeRequest, context) => this.rpcLocal.handshake(req, context))
66
58
  }
67
59
 
68
- async attemptHandshakesOnContacts(excludedIds: NodeID[]): Promise<NodeID[]> {
69
- if (this.config.targetNeighbors.size() + this.ongoingHandshakes.size < this.config.maxNeighborCount - 2) {
60
+ async attemptHandshakesOnContacts(excludedIds: DhtAddress[]): Promise<DhtAddress[]> {
61
+ // TODO use config option or named constant? or why the value 2?
62
+ if (this.config.neighbors.size() + this.config.ongoingHandshakes.size < this.config.maxNeighborCount - 2) {
70
63
  logger.trace(`Attempting parallel handshakes with ${PARALLEL_HANDSHAKE_COUNT} targets`)
71
64
  return this.selectParallelTargetsAndHandshake(excludedIds)
72
- } else if (this.config.targetNeighbors.size() + this.ongoingHandshakes.size < this.config.maxNeighborCount) {
65
+ } else if (this.config.neighbors.size() + this.config.ongoingHandshakes.size < this.config.maxNeighborCount) {
73
66
  logger.trace(`Attempting handshake with new target`)
74
67
  return this.selectNewTargetAndHandshake(excludedIds)
75
68
  }
76
69
  return excludedIds
77
70
  }
78
71
 
79
- private async selectParallelTargetsAndHandshake(excludedIds: NodeID[]): Promise<NodeID[]> {
80
- const exclude = excludedIds.concat(this.config.targetNeighbors.getIds())
81
- const targetNeighbors = this.selectParallelTargets(exclude)
82
- targetNeighbors.forEach((contact) => this.ongoingHandshakes.add(getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())))
83
- return this.doParallelHandshakes(targetNeighbors, exclude)
72
+ private async selectParallelTargetsAndHandshake(excludedIds: DhtAddress[]): Promise<DhtAddress[]> {
73
+ const exclude = excludedIds.concat(this.config.neighbors.getIds())
74
+ const neighbors = this.selectParallelTargets(exclude)
75
+ neighbors.forEach((contact) => this.config.ongoingHandshakes.add(getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())))
76
+ return this.doParallelHandshakes(neighbors, exclude)
84
77
  }
85
78
 
86
- private selectParallelTargets(excludedIds: NodeID[]): HandshakeRpcRemote[] {
87
- const targetNeighbors = this.config.nearbyNodeView.getClosestAndFurthest(excludedIds)
88
- while (targetNeighbors.length < PARALLEL_HANDSHAKE_COUNT && this.config.randomNodeView.size(excludedIds) > 0) {
89
- const random = this.config.randomNodeView.getRandom(excludedIds)
79
+ private selectParallelTargets(excludedIds: DhtAddress[]): HandshakeRpcRemote[] {
80
+ const neighbors: Map<DhtAddress, DeliveryRpcRemote> = new Map()
81
+ // First add the closest left and then right contacts from the ring if possible.
82
+ const left = this.config.leftNodeView.getFirst([...excludedIds, ...Array.from(neighbors.keys())] as DhtAddress[])
83
+ const right = this.config.rightNodeView.getFirst([...excludedIds, ...Array.from(neighbors.keys())] as DhtAddress[])
84
+ if (left) {
85
+ neighbors.set(getNodeIdFromPeerDescriptor(left.getPeerDescriptor()), left)
86
+ }
87
+ if (right) {
88
+ neighbors.set(getNodeIdFromPeerDescriptor(right.getPeerDescriptor()), right)
89
+ }
90
+ // If there is still room add the closest contact based on the kademlia metric
91
+ if (neighbors.size < PARALLEL_HANDSHAKE_COUNT) {
92
+ const first = this.config.nearbyNodeView.getFirst([...excludedIds, ...Array.from(neighbors.keys())] as DhtAddress[])
93
+ if (first) {
94
+ neighbors.set(getNodeIdFromPeerDescriptor(first.getPeerDescriptor()), first)
95
+ }
96
+ }
97
+ const getExcludedFromRandomView = () => [
98
+ ...excludedIds,
99
+ ...Array.from(neighbors.values()).map((neighbor) => getNodeIdFromPeerDescriptor(neighbor.getPeerDescriptor()))
100
+ ]
101
+ // If there is still room add a random contact until PARALLEL_HANDSHAKE_COUNT is reached
102
+ while (
103
+ neighbors.size < PARALLEL_HANDSHAKE_COUNT
104
+ && this.config.randomNodeView.size(getExcludedFromRandomView()) > 0
105
+ ) {
106
+ const random = this.config.randomNodeView.getRandom([...excludedIds, ...Array.from(neighbors.keys())] as DhtAddress[])
90
107
  if (random) {
91
- targetNeighbors.push(random)
108
+ neighbors.set(getNodeIdFromPeerDescriptor(random.getPeerDescriptor()), random)
92
109
  }
93
110
  }
94
- return targetNeighbors.map((neighbor) => this.createRpcRemote(neighbor.getPeerDescriptor()))
111
+ return Array.from(neighbors.values()).map((neighbor) => this.createRpcRemote(neighbor.getPeerDescriptor()))
95
112
  }
96
113
 
97
- private async doParallelHandshakes(targets: HandshakeRpcRemote[], excludedIds: NodeID[]): Promise<NodeID[]> {
114
+ private async doParallelHandshakes(targets: HandshakeRpcRemote[], excludedIds: DhtAddress[]): Promise<DhtAddress[]> {
98
115
  const results = await Promise.allSettled(
99
116
  Array.from(targets.values()).map(async (target: HandshakeRpcRemote, i) => {
100
117
  const otherNode = i === 0 ? targets[1] : targets[0]
118
+ // TODO better check (currently this condition is always true)
101
119
  const otherNodeId = otherNode ? getNodeIdFromPeerDescriptor(otherNode.getPeerDescriptor()) : undefined
102
120
  return this.handshakeWithTarget(target, otherNodeId)
103
121
  })
104
122
  )
105
- results.map((res, i) => {
123
+ results.forEach((res, i) => {
106
124
  if (res.status !== 'fulfilled' || !res.value) {
107
125
  excludedIds.push(getNodeIdFromPeerDescriptor(targets[i].getPeerDescriptor()))
108
126
  }
@@ -110,56 +128,53 @@ export class Handshaker implements IHandshaker {
110
128
  return excludedIds
111
129
  }
112
130
 
113
- private async selectNewTargetAndHandshake(excludedIds: NodeID[]): Promise<NodeID[]> {
114
- const exclude = excludedIds.concat(this.config.targetNeighbors.getIds())
115
- const targetNeighbor = this.config.nearbyNodeView.getClosest(exclude) ?? this.config.randomNodeView.getRandom(exclude)
116
- if (targetNeighbor) {
117
- const accepted = await this.handshakeWithTarget(this.createRpcRemote(targetNeighbor.getPeerDescriptor()))
131
+ private async selectNewTargetAndHandshake(excludedIds: DhtAddress[]): Promise<DhtAddress[]> {
132
+ const exclude = excludedIds.concat(this.config.neighbors.getIds())
133
+ const neighbor = this.config.leftNodeView.getFirst(exclude)
134
+ ?? this.config.rightNodeView.getFirst(exclude)
135
+ ?? this.config.nearbyNodeView.getFirst(exclude)
136
+ ?? this.config.randomNodeView.getRandom(exclude)
137
+ if (neighbor) {
138
+ const accepted = await this.handshakeWithTarget(this.createRpcRemote(neighbor.getPeerDescriptor()))
118
139
  if (!accepted) {
119
- excludedIds.push(getNodeIdFromPeerDescriptor(targetNeighbor.getPeerDescriptor()))
140
+ excludedIds.push(getNodeIdFromPeerDescriptor(neighbor.getPeerDescriptor()))
120
141
  }
121
142
  }
122
143
  return excludedIds
123
144
  }
124
145
 
125
- private async handshakeWithTarget(targetNeighbor: HandshakeRpcRemote, concurrentNodeId?: NodeID): Promise<boolean> {
126
- const targetNodeId = getNodeIdFromPeerDescriptor(targetNeighbor.getPeerDescriptor())
127
- this.ongoingHandshakes.add(targetNodeId)
128
- const result = await targetNeighbor.handshake(
129
- this.config.targetNeighbors.getIds(),
146
+ private async handshakeWithTarget(neighbor: HandshakeRpcRemote, concurrentNodeId?: DhtAddress): Promise<boolean> {
147
+ const targetNodeId = getNodeIdFromPeerDescriptor(neighbor.getPeerDescriptor())
148
+ this.config.ongoingHandshakes.add(targetNodeId)
149
+ const result = await neighbor.handshake(
150
+ this.config.streamPartId,
151
+ this.config.neighbors.getIds(),
130
152
  concurrentNodeId
131
153
  )
132
154
  if (result.accepted) {
133
- this.config.targetNeighbors.add(this.createDeliveryRpcRemote(targetNeighbor.getPeerDescriptor()))
134
- this.config.connectionLocker.lockConnection(targetNeighbor.getPeerDescriptor(), this.config.streamPartId)
155
+ this.config.neighbors.add(this.createDeliveryRpcRemote(neighbor.getPeerDescriptor()))
135
156
  }
136
157
  if (result.interleaveTargetDescriptor) {
137
158
  await this.handshakeWithInterleaving(result.interleaveTargetDescriptor, targetNodeId)
138
159
  }
139
- this.ongoingHandshakes.delete(targetNodeId)
160
+ this.config.ongoingHandshakes.delete(targetNodeId)
140
161
  return result.accepted
141
162
  }
142
163
 
143
- private async handshakeWithInterleaving(target: PeerDescriptor, interleaveSourceId: NodeID): Promise<boolean> {
144
- const targetNeighbor = new HandshakeRpcRemote(
145
- this.config.localPeerDescriptor,
146
- target,
164
+ private async handshakeWithInterleaving(target: PeerDescriptor, interleaveSourceId: DhtAddress): Promise<boolean> {
165
+ const neighbor = this.createRpcRemote(target)
166
+ const targetNodeId = getNodeIdFromPeerDescriptor(neighbor.getPeerDescriptor())
167
+ this.config.ongoingHandshakes.add(targetNodeId)
168
+ const result = await neighbor.handshake(
147
169
  this.config.streamPartId,
148
- this.client,
149
- this.config.rpcRequestTimeout
150
- )
151
- const targetNodeId = getNodeIdFromPeerDescriptor(targetNeighbor.getPeerDescriptor())
152
- this.ongoingHandshakes.add(targetNodeId)
153
- const result = await targetNeighbor.handshake(
154
- this.config.targetNeighbors.getIds(),
170
+ this.config.neighbors.getIds(),
155
171
  undefined,
156
172
  interleaveSourceId
157
173
  )
158
174
  if (result.accepted) {
159
- this.config.targetNeighbors.add(this.createDeliveryRpcRemote(targetNeighbor.getPeerDescriptor()))
160
- this.config.connectionLocker.lockConnection(targetNeighbor.getPeerDescriptor(), this.config.streamPartId)
175
+ this.config.neighbors.add(this.createDeliveryRpcRemote(neighbor.getPeerDescriptor()))
161
176
  }
162
- this.ongoingHandshakes.delete(targetNodeId)
177
+ this.config.ongoingHandshakes.delete(targetNodeId)
163
178
  return result.accepted
164
179
  }
165
180
 
@@ -167,8 +182,8 @@ export class Handshaker implements IHandshaker {
167
182
  return new HandshakeRpcRemote(
168
183
  this.config.localPeerDescriptor,
169
184
  targetPeerDescriptor,
170
- this.config.streamPartId,
171
- this.client,
185
+ this.config.rpcCommunicator,
186
+ HandshakeRpcClient,
172
187
  this.config.rpcRequestTimeout
173
188
  )
174
189
  }
@@ -177,14 +192,14 @@ export class Handshaker implements IHandshaker {
177
192
  return new DeliveryRpcRemote(
178
193
  this.config.localPeerDescriptor,
179
194
  targetPeerDescriptor,
180
- this.config.streamPartId,
181
- toProtoRpcClient(new DeliveryRpcClient(this.config.rpcCommunicator.getRpcClientTransport())),
195
+ this.config.rpcCommunicator,
196
+ DeliveryRpcClient,
182
197
  this.config.rpcRequestTimeout
183
198
  )
184
199
  }
185
200
 
186
- getOngoingHandshakes(): Set<NodeID> {
187
- return this.ongoingHandshakes
201
+ getOngoingHandshakes(): Set<DhtAddress> {
202
+ return this.config.ongoingHandshakes
188
203
  }
189
204
 
190
205
  }
@@ -1,24 +1,21 @@
1
1
  import { setAbortableTimeout } from '@streamr/utils'
2
2
  import { NodeList } from '../NodeList'
3
- import { NodeID } from '../../identifiers'
3
+ import { DhtAddress } from '@streamr/dht'
4
4
 
5
5
  interface FindNeighborsSessionConfig {
6
- targetNeighbors: NodeList
6
+ neighbors: NodeList
7
7
  nearbyNodeView: NodeList
8
- doFindNeighbors: (excludedNodes: NodeID[]) => Promise<NodeID[]>
8
+ leftNodeView: NodeList
9
+ rightNodeView: NodeList
10
+ randomNodeView: NodeList
11
+ doFindNeighbors: (excludedNodes: DhtAddress[]) => Promise<DhtAddress[]>
9
12
  minCount: number
10
13
  }
11
14
 
12
15
  const INITIAL_WAIT = 100
13
16
  const INTERVAL = 250
14
17
 
15
- export interface INeighborFinder {
16
- start(excluded?: NodeID[]): void
17
- stop(): void
18
- isRunning(): boolean
19
- }
20
-
21
- export class NeighborFinder implements INeighborFinder {
18
+ export class NeighborFinder {
22
19
  private readonly abortController: AbortController
23
20
  private readonly config: FindNeighborsSessionConfig
24
21
  private running = false
@@ -28,12 +25,19 @@ export class NeighborFinder implements INeighborFinder {
28
25
  this.abortController = new AbortController()
29
26
  }
30
27
 
31
- private async findNeighbors(excluded: NodeID[]): Promise<void> {
28
+ private async findNeighbors(excluded: DhtAddress[]): Promise<void> {
32
29
  if (!this.running) {
33
30
  return
34
31
  }
35
32
  const newExcludes = await this.config.doFindNeighbors(excluded)
36
- if (this.config.targetNeighbors.size() < this.config.minCount && newExcludes.length < this.config.nearbyNodeView.size()) {
33
+ const uniqueContactCount = new Set([
34
+ ...this.config.nearbyNodeView.getIds(),
35
+ ...this.config.leftNodeView.getIds(),
36
+ ...this.config.rightNodeView.getIds(),
37
+ ...this.config.randomNodeView.getIds()
38
+ ]).size
39
+ if (this.config.neighbors.size() < this.config.minCount && newExcludes.length < uniqueContactCount) {
40
+ // TODO should we catch possible promise rejection?
37
41
  setAbortableTimeout(() => this.findNeighbors(newExcludes), INTERVAL, this.abortController.signal)
38
42
  } else {
39
43
  this.running = false
@@ -44,11 +48,12 @@ export class NeighborFinder implements INeighborFinder {
44
48
  return this.running
45
49
  }
46
50
 
47
- start(excluded: NodeID[] = []): void {
51
+ start(excluded: DhtAddress[] = []): void {
48
52
  if (this.running) {
49
53
  return
50
54
  }
51
55
  this.running = true
56
+ // TODO should we catch possible promise rejection?
52
57
  setAbortableTimeout(() => this.findNeighbors(excluded), INITIAL_WAIT, this.abortController.signal)
53
58
  }
54
59