@streamr/dht 0.0.1-tatum.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 (344) hide show
  1. package/.eslintignore +5 -0
  2. package/.eslintrc +3 -0
  3. package/README.md +38 -0
  4. package/dist/src/connection/Connection.d.ts +11 -0
  5. package/dist/src/connection/Connection.js +23 -0
  6. package/dist/src/connection/Connection.js.map +1 -0
  7. package/dist/src/connection/ConnectionLockHandler.d.ts +23 -0
  8. package/dist/src/connection/ConnectionLockHandler.js +94 -0
  9. package/dist/src/connection/ConnectionLockHandler.js.map +1 -0
  10. package/dist/src/connection/ConnectionManager.d.ts +94 -0
  11. package/dist/src/connection/ConnectionManager.js +554 -0
  12. package/dist/src/connection/ConnectionManager.js.map +1 -0
  13. package/dist/src/connection/ConnectivityChecker.d.ts +17 -0
  14. package/dist/src/connection/ConnectivityChecker.js +187 -0
  15. package/dist/src/connection/ConnectivityChecker.js.map +1 -0
  16. package/dist/src/connection/Handshaker.d.ts +19 -0
  17. package/dist/src/connection/Handshaker.js +77 -0
  18. package/dist/src/connection/Handshaker.js.map +1 -0
  19. package/dist/src/connection/IConnection.d.ts +38 -0
  20. package/dist/src/connection/IConnection.js +19 -0
  21. package/dist/src/connection/IConnection.js.map +1 -0
  22. package/dist/src/connection/IConnectionSource.d.ts +4 -0
  23. package/dist/src/connection/IConnectionSource.js +3 -0
  24. package/dist/src/connection/IConnectionSource.js.map +1 -0
  25. package/dist/src/connection/ManagedConnection.d.ts +60 -0
  26. package/dist/src/connection/ManagedConnection.js +352 -0
  27. package/dist/src/connection/ManagedConnection.js.map +1 -0
  28. package/dist/src/connection/ManagedWebRtcConnection.d.ts +7 -0
  29. package/dist/src/connection/ManagedWebRtcConnection.js +20 -0
  30. package/dist/src/connection/ManagedWebRtcConnection.js.map +1 -0
  31. package/dist/src/connection/RemoteConnectionLocker.d.ts +14 -0
  32. package/dist/src/connection/RemoteConnectionLocker.js +93 -0
  33. package/dist/src/connection/RemoteConnectionLocker.js.map +1 -0
  34. package/dist/src/connection/Simulator/Simulator.d.ts +42 -0
  35. package/dist/src/connection/Simulator/Simulator.js +325 -0
  36. package/dist/src/connection/Simulator/Simulator.js.map +1 -0
  37. package/dist/src/connection/Simulator/SimulatorConnection.d.ts +19 -0
  38. package/dist/src/connection/Simulator/SimulatorConnection.js +118 -0
  39. package/dist/src/connection/Simulator/SimulatorConnection.js.map +1 -0
  40. package/dist/src/connection/Simulator/SimulatorConnector.d.ts +17 -0
  41. package/dist/src/connection/Simulator/SimulatorConnector.js +72 -0
  42. package/dist/src/connection/Simulator/SimulatorConnector.js.map +1 -0
  43. package/dist/src/connection/Simulator/SimulatorTransport.d.ts +6 -0
  44. package/dist/src/connection/Simulator/SimulatorTransport.js +11 -0
  45. package/dist/src/connection/Simulator/SimulatorTransport.js.map +1 -0
  46. package/dist/src/connection/Simulator/pings.d.ts +21 -0
  47. package/dist/src/connection/Simulator/pings.js +61 -0
  48. package/dist/src/connection/Simulator/pings.js.map +1 -0
  49. package/dist/src/connection/WebRTC/IWebRtcConnection.d.ts +20 -0
  50. package/dist/src/connection/WebRTC/IWebRtcConnection.js +9 -0
  51. package/dist/src/connection/WebRTC/IWebRtcConnection.js.map +1 -0
  52. package/dist/src/connection/WebRTC/NodeWebRtcConnection.d.ts +47 -0
  53. package/dist/src/connection/WebRTC/NodeWebRtcConnection.js +233 -0
  54. package/dist/src/connection/WebRTC/NodeWebRtcConnection.js.map +1 -0
  55. package/dist/src/connection/WebRTC/RemoteWebrtcConnector.d.ts +12 -0
  56. package/dist/src/connection/WebRTC/RemoteWebrtcConnector.js +74 -0
  57. package/dist/src/connection/WebRTC/RemoteWebrtcConnector.js.map +1 -0
  58. package/dist/src/connection/WebRTC/WebRtcConnector.d.ts +47 -0
  59. package/dist/src/connection/WebRTC/WebRtcConnector.js +227 -0
  60. package/dist/src/connection/WebRTC/WebRtcConnector.js.map +1 -0
  61. package/dist/src/connection/WebRTC/iceServerAsString.d.ts +2 -0
  62. package/dist/src/connection/WebRTC/iceServerAsString.js +18 -0
  63. package/dist/src/connection/WebRTC/iceServerAsString.js.map +1 -0
  64. package/dist/src/connection/WebSocket/ClientWebSocket.d.ts +15 -0
  65. package/dist/src/connection/WebSocket/ClientWebSocket.js +113 -0
  66. package/dist/src/connection/WebSocket/ClientWebSocket.js.map +1 -0
  67. package/dist/src/connection/WebSocket/RemoteWebSocketConnector.d.ts +9 -0
  68. package/dist/src/connection/WebSocket/RemoteWebSocketConnector.js +63 -0
  69. package/dist/src/connection/WebSocket/RemoteWebSocketConnector.js.map +1 -0
  70. package/dist/src/connection/WebSocket/ServerWebSocket.d.ts +18 -0
  71. package/dist/src/connection/WebSocket/ServerWebSocket.js +103 -0
  72. package/dist/src/connection/WebSocket/ServerWebSocket.js.map +1 -0
  73. package/dist/src/connection/WebSocket/WebSocketConnector.d.ts +31 -0
  74. package/dist/src/connection/WebSocket/WebSocketConnector.js +202 -0
  75. package/dist/src/connection/WebSocket/WebSocketConnector.js.map +1 -0
  76. package/dist/src/connection/WebSocket/WebSocketServer.d.ts +9 -0
  77. package/dist/src/connection/WebSocket/WebSocketServer.js +101 -0
  78. package/dist/src/connection/WebSocket/WebSocketServer.js.map +1 -0
  79. package/dist/src/dht/DhtNode.d.ts +153 -0
  80. package/dist/src/dht/DhtNode.js +599 -0
  81. package/dist/src/dht/DhtNode.js.map +1 -0
  82. package/dist/src/dht/DhtPeer.d.ts +18 -0
  83. package/dist/src/dht/DhtPeer.js +74 -0
  84. package/dist/src/dht/DhtPeer.js.map +1 -0
  85. package/dist/src/dht/ExternalApi.d.ts +8 -0
  86. package/dist/src/dht/ExternalApi.js +26 -0
  87. package/dist/src/dht/ExternalApi.js.map +1 -0
  88. package/dist/src/dht/RemoteExternalApi.d.ts +6 -0
  89. package/dist/src/dht/RemoteExternalApi.js +26 -0
  90. package/dist/src/dht/RemoteExternalApi.js.map +1 -0
  91. package/dist/src/dht/contact/Contact.d.ts +22 -0
  92. package/dist/src/dht/contact/Contact.js +25 -0
  93. package/dist/src/dht/contact/Contact.js.map +1 -0
  94. package/dist/src/dht/contact/RandomContactList.d.ts +20 -0
  95. package/dist/src/dht/contact/RandomContactList.js +78 -0
  96. package/dist/src/dht/contact/RandomContactList.js.map +1 -0
  97. package/dist/src/dht/contact/Remote.d.ts +15 -0
  98. package/dist/src/dht/contact/Remote.js +24 -0
  99. package/dist/src/dht/contact/Remote.js.map +1 -0
  100. package/dist/src/dht/contact/SortedContactList.d.ts +35 -0
  101. package/dist/src/dht/contact/SortedContactList.js +156 -0
  102. package/dist/src/dht/contact/SortedContactList.js.map +1 -0
  103. package/dist/src/dht/discovery/DiscoverySession.d.ts +36 -0
  104. package/dist/src/dht/discovery/DiscoverySession.js +116 -0
  105. package/dist/src/dht/discovery/DiscoverySession.js.map +1 -0
  106. package/dist/src/dht/discovery/PeerDiscovery.d.ts +42 -0
  107. package/dist/src/dht/discovery/PeerDiscovery.js +157 -0
  108. package/dist/src/dht/discovery/PeerDiscovery.js.map +1 -0
  109. package/dist/src/dht/find/RecursiveFindSession.d.ts +46 -0
  110. package/dist/src/dht/find/RecursiveFindSession.js +142 -0
  111. package/dist/src/dht/find/RecursiveFindSession.js.map +1 -0
  112. package/dist/src/dht/find/RecursiveFinder.d.ts +54 -0
  113. package/dist/src/dht/find/RecursiveFinder.js +180 -0
  114. package/dist/src/dht/find/RecursiveFinder.js.map +1 -0
  115. package/dist/src/dht/find/RemoteRecursiveFindSession.d.ts +6 -0
  116. package/dist/src/dht/find/RemoteRecursiveFindSession.js +25 -0
  117. package/dist/src/dht/find/RemoteRecursiveFindSession.js.map +1 -0
  118. package/dist/src/dht/routing/DuplicateDetector.d.ts +13 -0
  119. package/dist/src/dht/routing/DuplicateDetector.js +41 -0
  120. package/dist/src/dht/routing/DuplicateDetector.js.map +1 -0
  121. package/dist/src/dht/routing/RemoteRouter.d.ts +8 -0
  122. package/dist/src/dht/routing/RemoteRouter.js +106 -0
  123. package/dist/src/dht/routing/RemoteRouter.js.map +1 -0
  124. package/dist/src/dht/routing/Router.d.ts +60 -0
  125. package/dist/src/dht/routing/Router.js +207 -0
  126. package/dist/src/dht/routing/Router.js.map +1 -0
  127. package/dist/src/dht/routing/RoutingSession.d.ts +42 -0
  128. package/dist/src/dht/routing/RoutingSession.js +178 -0
  129. package/dist/src/dht/routing/RoutingSession.js.map +1 -0
  130. package/dist/src/dht/store/DataStore.d.ts +45 -0
  131. package/dist/src/dht/store/DataStore.js +244 -0
  132. package/dist/src/dht/store/DataStore.js.map +1 -0
  133. package/dist/src/dht/store/LocalDataStore.d.ts +19 -0
  134. package/dist/src/dht/store/LocalDataStore.js +104 -0
  135. package/dist/src/dht/store/LocalDataStore.js.map +1 -0
  136. package/dist/src/dht/store/RemoteStore.d.ts +8 -0
  137. package/dist/src/dht/store/RemoteStore.js +44 -0
  138. package/dist/src/dht/store/RemoteStore.js.map +1 -0
  139. package/dist/src/exports.d.ts +19 -0
  140. package/dist/src/exports.js +41 -0
  141. package/dist/src/exports.js.map +1 -0
  142. package/dist/src/helpers/AddressTools.d.ts +2 -0
  143. package/dist/src/helpers/AddressTools.js +31 -0
  144. package/dist/src/helpers/AddressTools.js.map +1 -0
  145. package/dist/src/helpers/PeerID.d.ts +25 -0
  146. package/dist/src/helpers/PeerID.js +84 -0
  147. package/dist/src/helpers/PeerID.js.map +1 -0
  148. package/dist/src/helpers/UUID.d.ts +7 -0
  149. package/dist/src/helpers/UUID.js +32 -0
  150. package/dist/src/helpers/UUID.js.map +1 -0
  151. package/dist/src/helpers/debugHelpers.d.ts +3 -0
  152. package/dist/src/helpers/debugHelpers.js +11 -0
  153. package/dist/src/helpers/debugHelpers.js.map +1 -0
  154. package/dist/src/helpers/errors.d.ts +72 -0
  155. package/dist/src/helpers/errors.js +95 -0
  156. package/dist/src/helpers/errors.js.map +1 -0
  157. package/dist/src/helpers/peerIdFromPeerDescriptor.d.ts +5 -0
  158. package/dist/src/helpers/peerIdFromPeerDescriptor.js +17 -0
  159. package/dist/src/helpers/peerIdFromPeerDescriptor.js.map +1 -0
  160. package/dist/src/helpers/protoClasses.d.ts +2 -0
  161. package/dist/src/helpers/protoClasses.js +35 -0
  162. package/dist/src/helpers/protoClasses.js.map +1 -0
  163. package/dist/src/helpers/protoToString.d.ts +2 -0
  164. package/dist/src/helpers/protoToString.js +20 -0
  165. package/dist/src/helpers/protoToString.js.map +1 -0
  166. package/dist/src/proto/google/protobuf/any.d.ts +173 -0
  167. package/dist/src/proto/google/protobuf/any.js +155 -0
  168. package/dist/src/proto/google/protobuf/any.js.map +1 -0
  169. package/dist/src/proto/google/protobuf/empty.d.ts +32 -0
  170. package/dist/src/proto/google/protobuf/empty.js +34 -0
  171. package/dist/src/proto/google/protobuf/empty.js.map +1 -0
  172. package/dist/src/proto/google/protobuf/timestamp.d.ts +149 -0
  173. package/dist/src/proto/google/protobuf/timestamp.js +136 -0
  174. package/dist/src/proto/google/protobuf/timestamp.js.map +1 -0
  175. package/dist/src/proto/packages/dht/protos/DhtRpc.client.d.ts +320 -0
  176. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js +245 -0
  177. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +1 -0
  178. package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +1089 -0
  179. package/dist/src/proto/packages/dht/protos/DhtRpc.js +710 -0
  180. package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -0
  181. package/dist/src/proto/packages/dht/protos/DhtRpc.server.d.ts +145 -0
  182. package/dist/src/proto/packages/dht/protos/DhtRpc.server.js +3 -0
  183. package/dist/src/proto/packages/dht/protos/DhtRpc.server.js.map +1 -0
  184. package/dist/src/proto/packages/proto-rpc/protos/ProtoRpc.d.ts +87 -0
  185. package/dist/src/proto/packages/proto-rpc/protos/ProtoRpc.js +66 -0
  186. package/dist/src/proto/packages/proto-rpc/protos/ProtoRpc.js.map +1 -0
  187. package/dist/src/proto/tests.d.ts +39 -0
  188. package/dist/src/proto/tests.js +34 -0
  189. package/dist/src/proto/tests.js.map +1 -0
  190. package/dist/src/rpc-protocol/DhtCallContext.d.ts +12 -0
  191. package/dist/src/rpc-protocol/DhtCallContext.js +8 -0
  192. package/dist/src/rpc-protocol/DhtCallContext.js.map +1 -0
  193. package/dist/src/rpc-protocol/DhtRpcOptions.d.ts +8 -0
  194. package/dist/src/rpc-protocol/DhtRpcOptions.js +3 -0
  195. package/dist/src/rpc-protocol/DhtRpcOptions.js.map +1 -0
  196. package/dist/src/transport/ITransport.d.ts +22 -0
  197. package/dist/src/transport/ITransport.js +3 -0
  198. package/dist/src/transport/ITransport.js.map +1 -0
  199. package/dist/src/transport/ListeningRpcCommunicator.d.ts +6 -0
  200. package/dist/src/transport/ListeningRpcCommunicator.js +14 -0
  201. package/dist/src/transport/ListeningRpcCommunicator.js.map +1 -0
  202. package/dist/src/transport/RoutingRpcCommunicator.d.ts +8 -0
  203. package/dist/src/transport/RoutingRpcCommunicator.js +52 -0
  204. package/dist/src/transport/RoutingRpcCommunicator.js.map +1 -0
  205. package/jest.config.js +2 -0
  206. package/karma.config.js +20 -0
  207. package/package.json +64 -0
  208. package/proto.sh +3 -0
  209. package/protos/DhtRpc.proto +330 -0
  210. package/protos/tests.proto +16 -0
  211. package/src/connection/Connection.ts +23 -0
  212. package/src/connection/ConnectionLockHandler.ts +105 -0
  213. package/src/connection/ConnectionManager.ts +676 -0
  214. package/src/connection/ConnectivityChecker.ts +173 -0
  215. package/src/connection/Handshaker.ts +92 -0
  216. package/src/connection/IConnection.ts +47 -0
  217. package/src/connection/IConnectionSource.ts +6 -0
  218. package/src/connection/ManagedConnection.ts +398 -0
  219. package/src/connection/ManagedWebRtcConnection.ts +27 -0
  220. package/src/connection/RemoteConnectionLocker.ts +88 -0
  221. package/src/connection/Simulator/Simulator.ts +399 -0
  222. package/src/connection/Simulator/SimulatorConnection.ts +137 -0
  223. package/src/connection/Simulator/SimulatorConnector.ts +104 -0
  224. package/src/connection/Simulator/SimulatorTransport.ts +9 -0
  225. package/src/connection/Simulator/pings.ts +42 -0
  226. package/src/connection/WebRTC/BrowserWebRtcConnection.ts +227 -0
  227. package/src/connection/WebRTC/IWebRtcConnection.ts +24 -0
  228. package/src/connection/WebRTC/NodeWebRtcConnection.ts +256 -0
  229. package/src/connection/WebRTC/RemoteWebrtcConnector.ts +93 -0
  230. package/src/connection/WebRTC/WebRtcConnector.ts +306 -0
  231. package/src/connection/WebRTC/iceServerAsString.ts +15 -0
  232. package/src/connection/WebSocket/ClientWebSocket.ts +118 -0
  233. package/src/connection/WebSocket/RemoteWebSocketConnector.ts +49 -0
  234. package/src/connection/WebSocket/ServerWebSocket.ts +119 -0
  235. package/src/connection/WebSocket/WebSocketConnector.ts +264 -0
  236. package/src/connection/WebSocket/WebSocketServer.ts +97 -0
  237. package/src/dht/DhtNode.ts +776 -0
  238. package/src/dht/DhtPeer.ts +96 -0
  239. package/src/dht/ExternalApi.ts +29 -0
  240. package/src/dht/RemoteExternalApi.ts +25 -0
  241. package/src/dht/contact/Contact.ts +36 -0
  242. package/src/dht/contact/RandomContactList.ts +92 -0
  243. package/src/dht/contact/Remote.ts +40 -0
  244. package/src/dht/contact/SortedContactList.ts +196 -0
  245. package/src/dht/discovery/DiscoverySession.ts +150 -0
  246. package/src/dht/discovery/PeerDiscovery.ts +162 -0
  247. package/src/dht/find/RecursiveFindSession.ts +178 -0
  248. package/src/dht/find/RecursiveFinder.ts +272 -0
  249. package/src/dht/find/RemoteRecursiveFindSession.ts +33 -0
  250. package/src/dht/routing/DuplicateDetector.ts +53 -0
  251. package/src/dht/routing/RemoteRouter.ts +115 -0
  252. package/src/dht/routing/Router.ts +266 -0
  253. package/src/dht/routing/RoutingSession.ts +222 -0
  254. package/src/dht/store/DataStore.ts +321 -0
  255. package/src/dht/store/LocalDataStore.ts +114 -0
  256. package/src/dht/store/RemoteStore.ts +58 -0
  257. package/src/exports.ts +19 -0
  258. package/src/helpers/AddressTools.ts +26 -0
  259. package/src/helpers/PeerID.ts +95 -0
  260. package/src/helpers/UUID.ts +30 -0
  261. package/src/helpers/debugHelpers.ts +9 -0
  262. package/src/helpers/errors.ts +49 -0
  263. package/src/helpers/peerIdFromPeerDescriptor.ts +14 -0
  264. package/src/helpers/protoClasses.ts +63 -0
  265. package/src/helpers/protoToString.ts +21 -0
  266. package/src/proto/google/protobuf/any.ts +319 -0
  267. package/src/proto/google/protobuf/empty.ts +84 -0
  268. package/src/proto/google/protobuf/timestamp.ts +281 -0
  269. package/src/proto/packages/dht/protos/DhtRpc.client.ts +373 -0
  270. package/src/proto/packages/dht/protos/DhtRpc.server.ts +148 -0
  271. package/src/proto/packages/dht/protos/DhtRpc.ts +1399 -0
  272. package/src/proto/packages/proto-rpc/protos/ProtoRpc.ts +108 -0
  273. package/src/proto/tests.ts +52 -0
  274. package/src/rpc-protocol/DhtCallContext.ts +15 -0
  275. package/src/rpc-protocol/DhtRpcOptions.ts +9 -0
  276. package/src/transport/ITransport.ts +31 -0
  277. package/src/transport/ListeningRpcCommunicator.ts +14 -0
  278. package/src/transport/RoutingRpcCommunicator.ts +59 -0
  279. package/src/types/glogal.d.ts +1 -0
  280. package/src/types/textencoding.d.ts +7 -0
  281. package/test/RandomGraphSimulation.ts +52 -0
  282. package/test/benchmark/KademliaCorrectness.test.ts +115 -0
  283. package/test/benchmark/RecursiveFind.test.ts +87 -0
  284. package/test/benchmark/any.test.ts +28 -0
  285. package/test/benchmark/kademlia-simulation/Contact.ts +32 -0
  286. package/test/benchmark/kademlia-simulation/KademliaSimulation.ts +94 -0
  287. package/test/benchmark/kademlia-simulation/SimulationNode.ts +125 -0
  288. package/test/data/generateGroundTruthData.ts +70 -0
  289. package/test/end-to-end/Layer0-Layer1.test.ts +87 -0
  290. package/test/end-to-end/Layer0.test.ts +60 -0
  291. package/test/end-to-end/Layer0MixedConnectionTypes.test.ts +94 -0
  292. package/test/end-to-end/Layer0WebRTC-Layer1.test.ts +134 -0
  293. package/test/end-to-end/Layer0WebRTC.test.ts +98 -0
  294. package/test/end-to-end/Layer1-Scale-WebRTC.test.ts +69 -0
  295. package/test/end-to-end/Layer1-Scale-WebSocket.test.ts +73 -0
  296. package/test/end-to-end/WebSocketConnectionRequest.test.ts +62 -0
  297. package/test/integration/ConnectionLocking.test.ts +166 -0
  298. package/test/integration/ConnectionManager.test.ts +291 -0
  299. package/test/integration/DhtNodeExternalAPI.test.ts +43 -0
  300. package/test/integration/DhtPeer.test.ts +73 -0
  301. package/test/integration/DhtRpc.test.ts +131 -0
  302. package/test/integration/DhtWithMockConnectionLatencies.test.ts +46 -0
  303. package/test/integration/DhtWithMockConnections.test.ts +46 -0
  304. package/test/integration/DhtWithRealConnectionLatencies.test.ts +47 -0
  305. package/test/integration/Layer1-scale.test.ts +200 -0
  306. package/test/integration/MigrateData.test.ts +203 -0
  307. package/test/integration/Mock-Layer1-Layer0.test.ts +106 -0
  308. package/test/integration/MultipleEntryPointJoining.test.ts +105 -0
  309. package/test/integration/RecursiveFind.test.ts +50 -0
  310. package/test/integration/RemoteRouter.test.ts +83 -0
  311. package/test/integration/RemoteStore.test.ts +66 -0
  312. package/test/integration/RouteMessage.test.ts +254 -0
  313. package/test/integration/RpcErrors.test.ts +153 -0
  314. package/test/integration/ScaleDownDht.test.ts +66 -0
  315. package/test/integration/SimultaneousConnections.test.ts +308 -0
  316. package/test/integration/Store.test.ts +72 -0
  317. package/test/integration/StoreAndDelete.test.ts +93 -0
  318. package/test/integration/StoreOnDhtWithTwoNodes.test.ts +71 -0
  319. package/test/integration/WebRtcConnectionManagement.test.ts +205 -0
  320. package/test/integration/WebRtcConnectorRpc.test.ts +145 -0
  321. package/test/integration/WebSocket.test.ts +64 -0
  322. package/test/integration/WebSocketConnectionManagement.test.ts +131 -0
  323. package/test/integration/WebSocketConnectorRpc.test.ts +86 -0
  324. package/test/kademlia-simulation/data/nodeids.json +13002 -0
  325. package/test/kademlia-simulation/data/orderedneighbors.json +1001 -0
  326. package/test/unit/AddressTools.test.ts +40 -0
  327. package/test/unit/DuplicateDetector.test.ts +29 -0
  328. package/test/unit/LocalDataStore.test.ts +107 -0
  329. package/test/unit/PeerID.test.ts +22 -0
  330. package/test/unit/ProtobufMessage.test.ts +21 -0
  331. package/test/unit/RandomContactList.test.ts +87 -0
  332. package/test/unit/RecursiveFinder.test.ts +112 -0
  333. package/test/unit/Router.test.ts +124 -0
  334. package/test/unit/SortedContactList.test.ts +127 -0
  335. package/test/unit/UUID.test.ts +49 -0
  336. package/test/unit/WebSocketServer.test.ts +42 -0
  337. package/test/utils/mock/RecursiveFinder.ts +19 -0
  338. package/test/utils/mock/Router.ts +53 -0
  339. package/test/utils/mock/Transport.ts +26 -0
  340. package/test/utils/utils.ts +311 -0
  341. package/tsconfig.browser.json +15 -0
  342. package/tsconfig.jest.json +19 -0
  343. package/tsconfig.json +3 -0
  344. package/tsconfig.node.json +18 -0
@@ -0,0 +1,96 @@
1
+ import { IDhtRpcServiceClient } from '../proto/packages/dht/protos/DhtRpc.client'
2
+ import {
3
+ ClosestPeersRequest,
4
+ LeaveNotice,
5
+ PeerDescriptor,
6
+ PingRequest
7
+ } from '../proto/packages/dht/protos/DhtRpc'
8
+ import { v4 } from 'uuid'
9
+ import { DhtRpcOptions } from '../rpc-protocol/DhtRpcOptions'
10
+ import { Logger } from '@streamr/utils'
11
+ import { ProtoRpcClient } from '@streamr/proto-rpc'
12
+ import { Remote } from './contact/Remote'
13
+
14
+ const logger = new Logger(module)
15
+
16
+ // Fields required by objects stored in the k-bucket library
17
+ export interface KBucketContact {
18
+ id: Uint8Array
19
+ vectorClock: number
20
+ }
21
+
22
+ export class DhtPeer extends Remote<IDhtRpcServiceClient> implements KBucketContact {
23
+ private static counter = 0
24
+ public vectorClock: number
25
+ public readonly id: Uint8Array
26
+ constructor(
27
+ ownPeerDescriptor: PeerDescriptor,
28
+ peerDescriptor: PeerDescriptor,
29
+ client: ProtoRpcClient<IDhtRpcServiceClient>,
30
+ serviceId: string
31
+ ) {
32
+ super(ownPeerDescriptor, peerDescriptor, client, serviceId)
33
+ this.id = this.peerId.value
34
+ this.vectorClock = DhtPeer.counter++
35
+ }
36
+
37
+ async getClosestPeers(kademliaId: Uint8Array): Promise<PeerDescriptor[]> {
38
+ logger.trace(`Requesting getClosestPeers on ${this.serviceId} from ${this.peerId.toKey()}`)
39
+ const request: ClosestPeersRequest = {
40
+ kademliaId: kademliaId,
41
+ requestId: v4()
42
+ }
43
+ const options: DhtRpcOptions = {
44
+ sourceDescriptor: this.ownPeerDescriptor,
45
+ targetDescriptor: this.peerDescriptor
46
+ }
47
+ try {
48
+ const peers = await this.client.getClosestPeers(request, options)
49
+ return peers.peers
50
+ } catch (err) {
51
+ logger.trace(`getClosestPeers error ${this.serviceId}`, { err })
52
+ throw err
53
+ }
54
+ }
55
+
56
+ async ping(): Promise<boolean> {
57
+ logger.trace(`Requesting ping on ${this.serviceId} from ${this.peerId.toKey()}`)
58
+ const request: PingRequest = {
59
+ requestId: v4()
60
+ }
61
+ const options: DhtRpcOptions = {
62
+ sourceDescriptor: this.ownPeerDescriptor,
63
+ targetDescriptor: this.peerDescriptor,
64
+ timeout: 10000
65
+ }
66
+ try {
67
+ const pong = await this.client.ping(request, options)
68
+ if (pong.requestId === request.requestId) {
69
+ return true
70
+ }
71
+ } catch (err) {
72
+ logger.debug(`ping failed on ${this.serviceId} to ${this.peerId.toKey()}: ${err}`)
73
+ }
74
+ return false
75
+ }
76
+
77
+ leaveNotice(): void {
78
+ logger.trace(`Sending leaveNotice on ${this.serviceId} from ${this.peerId.toKey()}`)
79
+ const request: LeaveNotice = {
80
+ serviceId: this.serviceId
81
+ }
82
+ const options: DhtRpcOptions = {
83
+ sourceDescriptor: this.ownPeerDescriptor,
84
+ targetDescriptor: this.peerDescriptor,
85
+ notification: true
86
+ }
87
+ this.client.leaveNotice(request, options).catch((e) => {
88
+ logger.trace('Failed to send leaveNotice' + e)
89
+ })
90
+ }
91
+
92
+ getPeerDescriptor(): PeerDescriptor {
93
+ return this.peerDescriptor
94
+ }
95
+
96
+ }
@@ -0,0 +1,29 @@
1
+ import { DhtNode } from '../exports'
2
+ import { FindDataRequest, FindDataResponse, FindMode } from '../proto/packages/dht/protos/DhtRpc'
3
+ import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
4
+
5
+ export class ExternalApi {
6
+
7
+ private readonly dhtNode: DhtNode
8
+
9
+ constructor(dhtNode: DhtNode) {
10
+ this.dhtNode = dhtNode
11
+ const rpcCommunicator = this.dhtNode.getRpcCommunicator!()
12
+ rpcCommunicator.registerRpcMethod(FindDataRequest, FindDataResponse, 'findData',
13
+ (req: FindDataRequest, context) => this.findData(req, context), { timeout: 15000 })
14
+ }
15
+
16
+ // IDHTRpcService method for external findRecursive calls
17
+ async findData(findDataRequest: FindDataRequest, _context: ServerCallContext): Promise<FindDataResponse> {
18
+ const result = await this.dhtNode.startRecursiveFind(findDataRequest.kademliaId, FindMode.DATA, findDataRequest.requestor)
19
+ if (result.dataEntries) {
20
+ return FindDataResponse.create({ dataEntries: result.dataEntries })
21
+ } else {
22
+ return FindDataResponse.create({
23
+ dataEntries: [],
24
+ error: 'Could not find data with the given key'
25
+ })
26
+ }
27
+ }
28
+
29
+ }
@@ -0,0 +1,25 @@
1
+ import { DhtRpcOptions } from '../exports'
2
+ import { DataEntry, FindDataRequest } from '../proto/packages/dht/protos/DhtRpc'
3
+ import { IExternalApiServiceClient } from '../proto/packages/dht/protos/DhtRpc.client'
4
+ import { Remote } from './contact/Remote'
5
+
6
+ export class RemoteExternalApi extends Remote<IExternalApiServiceClient> {
7
+
8
+ async findData(idToFind: Uint8Array): Promise<DataEntry[]> {
9
+ const request: FindDataRequest = {
10
+ kademliaId: idToFind,
11
+ requestor: this.ownPeerDescriptor,
12
+ }
13
+ const options: DhtRpcOptions = {
14
+ sourceDescriptor: this.ownPeerDescriptor,
15
+ targetDescriptor: this.peerDescriptor,
16
+ timeout: 10000
17
+ }
18
+ try {
19
+ const data = await this.client.findData(request, options)
20
+ return data.dataEntries
21
+ } catch (err) {
22
+ return []
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,36 @@
1
+ import { PeerID } from '../../helpers/PeerID'
2
+ import { PeerDescriptor } from '../../proto/packages/dht/protos/DhtRpc'
3
+ import { peerIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
4
+
5
+ export class ContactState<TContact> {
6
+ public contacted = false
7
+ public active = false
8
+ public contact: TContact
9
+
10
+ constructor(contact: TContact) {
11
+ this.contact = contact
12
+ }
13
+ }
14
+
15
+ export interface IContact { getPeerId: () => PeerID, getPeerDescriptor: () => PeerDescriptor }
16
+
17
+ export interface Events {
18
+ contactRemoved: (removedDescriptor: PeerDescriptor, closestDescriptors: PeerDescriptor[]) => void
19
+ newContact: (newDescriptor: PeerDescriptor, closestDescriptors: PeerDescriptor[]) => void
20
+ }
21
+
22
+ export class Contact implements IContact {
23
+ private peerDescriptor: PeerDescriptor
24
+
25
+ constructor(peerDescriptor: PeerDescriptor) {
26
+ this.peerDescriptor = peerDescriptor
27
+ }
28
+
29
+ public getPeerDescriptor(): PeerDescriptor {
30
+ return this.peerDescriptor
31
+ }
32
+
33
+ public getPeerId(): PeerID {
34
+ return peerIdFromPeerDescriptor(this.peerDescriptor)
35
+ }
36
+ }
@@ -0,0 +1,92 @@
1
+ import { Events, IContact, ContactState } from './Contact'
2
+
3
+ import EventEmitter from 'eventemitter3'
4
+ import { PeerID, PeerIDKey } from '../../helpers/PeerID'
5
+ export class RandomContactList<Contact extends IContact> extends EventEmitter<Events> {
6
+ private contactsById: Map<PeerIDKey, ContactState<Contact>> = new Map()
7
+ private contactIds: PeerID[] = []
8
+ private ownId: PeerID
9
+ private maxSize: number
10
+ private randomness = 0.20
11
+ private getContactsLimit = 20
12
+
13
+ constructor(
14
+ ownId: PeerID,
15
+ maxSize: number,
16
+ randomness = 0.20,
17
+ getContactsLimit = 20
18
+ ) {
19
+ super()
20
+ this.ownId = ownId
21
+ this.maxSize = maxSize
22
+ this.randomness = randomness
23
+ this.getContactsLimit = getContactsLimit
24
+ }
25
+
26
+ addContact(contact: Contact): void {
27
+ if (this.ownId.equals(contact.getPeerId())) {
28
+ return
29
+ }
30
+ if (!this.contactsById.has(contact.getPeerId().toKey())) {
31
+ const roll = Math.random()
32
+ if (roll < this.randomness) {
33
+ if (this.getSize() === this.maxSize && this.getSize() > 0) {
34
+ const toRemove = this.contactIds[0]
35
+ this.removeContact(toRemove)
36
+ }
37
+ this.contactIds.push(contact.getPeerId())
38
+ this.contactsById.set(contact.getPeerId().toKey(), new ContactState(contact))
39
+ this.emit(
40
+ 'newContact',
41
+ contact.getPeerDescriptor(),
42
+ this.getContacts().map((contact: Contact) => contact.getPeerDescriptor())
43
+ )
44
+ }
45
+ }
46
+ }
47
+
48
+ addContacts(contacts: Contact[]): void {
49
+ contacts.forEach((contact) => this.addContact(contact))
50
+ }
51
+
52
+ removeContact(id: PeerID): boolean {
53
+ if (this.contactsById.has(id.toKey())) {
54
+ const removedDescriptor = this.contactsById.get(id.toKey())!.contact.getPeerDescriptor()
55
+ const index = this.contactIds.indexOf(id)
56
+ this.contactIds.splice(index, 1)
57
+ this.contactsById.delete(id.toKey())
58
+ this.emit('contactRemoved', removedDescriptor, this.getContacts().map((contact: Contact) => contact.getPeerDescriptor()))
59
+ return true
60
+ }
61
+ return false
62
+ }
63
+
64
+ public getSize(): number {
65
+ return this.contactIds.length
66
+ }
67
+
68
+ public getContact(id: PeerID): ContactState<Contact> {
69
+ return this.contactsById.get(id.toKey())!
70
+ }
71
+
72
+ public getContacts(limit = this.getContactsLimit): Contact[] {
73
+ const ret: Contact[] = []
74
+ this.contactIds.forEach((contactId) => {
75
+ const contact = this.contactsById.get(contactId.toKey())
76
+ if (contact) {
77
+ ret.push(contact.contact)
78
+ }
79
+ })
80
+ return ret.splice(0, limit)
81
+ }
82
+
83
+ public clear(): void {
84
+ this.contactsById.clear()
85
+ this.contactIds = []
86
+ }
87
+
88
+ public stop(): void {
89
+ this.removeAllListeners()
90
+ this.clear()
91
+ }
92
+ }
@@ -0,0 +1,40 @@
1
+ import { PeerDescriptor } from '../../proto/packages/dht/protos/DhtRpc'
2
+ import { ProtoRpcClient } from '@streamr/proto-rpc'
3
+ import { peerIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
4
+ import { PeerID } from '../../helpers/PeerID'
5
+ import { IContact } from './Contact'
6
+
7
+ export abstract class Remote<T> implements IContact {
8
+
9
+ protected readonly peerId: PeerID
10
+ protected readonly peerDescriptor: PeerDescriptor
11
+ protected readonly client: ProtoRpcClient<T>
12
+ protected readonly serviceId: string
13
+ protected readonly ownPeerDescriptor: PeerDescriptor
14
+
15
+ constructor(
16
+ ownPeerDescriptor: PeerDescriptor,
17
+ peerDescriptor: PeerDescriptor,
18
+ client: ProtoRpcClient<T>,
19
+ serviceId: string
20
+ ) {
21
+ this.ownPeerDescriptor = ownPeerDescriptor
22
+ this.peerId = peerIdFromPeerDescriptor(peerDescriptor)
23
+ this.peerDescriptor = peerDescriptor
24
+ this.client = client
25
+ this.serviceId = serviceId
26
+ }
27
+
28
+ getPeerId(): PeerID {
29
+ return this.peerId
30
+ }
31
+
32
+ getPeerDescriptor(): PeerDescriptor {
33
+ return this.peerDescriptor
34
+ }
35
+
36
+ getServiceId(): string {
37
+ return this.serviceId
38
+ }
39
+
40
+ }
@@ -0,0 +1,196 @@
1
+ import KBucket from 'k-bucket'
2
+ import { PeerID, PeerIDKey } from '../../helpers/PeerID'
3
+ import EventEmitter from 'eventemitter3'
4
+ import { Events, IContact, ContactState } from './Contact'
5
+
6
+ export class SortedContactList<Contact extends IContact> extends EventEmitter<Events> {
7
+ private contactsById: Map<PeerIDKey, ContactState<Contact>> = new Map()
8
+ private contactIds: PeerID[] = []
9
+ private ownId: PeerID
10
+ private maxSize: number
11
+ private getContactsLimit: number
12
+ private allowOwnPeerId: boolean
13
+ private peerIdDistanceLimit?: PeerID
14
+ private excludedPeerIDs?: PeerID[]
15
+
16
+ constructor(
17
+ ownId: PeerID,
18
+ maxSize: number,
19
+ getContactsLimit = 20,
20
+ allowOwnPeerId = false,
21
+ peerIdDistanceLimit?: PeerID,
22
+ excludedPeerIDs?: PeerID[]
23
+ ) {
24
+ super()
25
+ this.compareIds = this.compareIds.bind(this)
26
+ this.ownId = ownId
27
+ this.maxSize = maxSize
28
+ this.getContactsLimit = getContactsLimit
29
+ this.allowOwnPeerId = allowOwnPeerId
30
+ this.peerIdDistanceLimit = peerIdDistanceLimit
31
+ this.excludedPeerIDs = excludedPeerIDs
32
+ }
33
+
34
+ public getClosestContactId(): PeerID {
35
+ return this.contactIds[0]
36
+ }
37
+
38
+ public getContactIds(): PeerID[] {
39
+ return this.contactIds
40
+ }
41
+
42
+ public addContact(contact: Contact): void {
43
+ if (this.excludedPeerIDs
44
+ && this.excludedPeerIDs.some((peerId) => contact.getPeerId().equals(peerId))) {
45
+ return
46
+ }
47
+
48
+ if ((!this.allowOwnPeerId && this.ownId.equals(contact.getPeerId())) ||
49
+ (this.peerIdDistanceLimit !== undefined && this.compareIds(this.peerIdDistanceLimit, contact.getPeerId()) < 0)) {
50
+ return
51
+ }
52
+ if (!this.contactsById.has(contact.getPeerId().toKey())) {
53
+ if (this.contactIds.length < this.maxSize) {
54
+ this.contactsById.set(contact.getPeerId().toKey(), new ContactState(contact))
55
+ this.contactIds.push(contact.getPeerId())
56
+ this.contactIds.sort(this.compareIds)
57
+ } else if (this.compareIds(this.contactIds[this.maxSize - 1], contact.getPeerId()) > 0) {
58
+ const removed = this.contactIds.pop()
59
+ this.contactsById.delete(removed!.toKey())
60
+ this.contactsById.set(contact.getPeerId().toKey(), new ContactState(contact))
61
+ this.contactIds.push(contact.getPeerId())
62
+ this.contactIds.sort(this.compareIds)
63
+ this.emit(
64
+ 'contactRemoved',
65
+ contact.getPeerDescriptor(),
66
+ this.getClosestContacts().map((contact: Contact) => contact.getPeerDescriptor())
67
+ )
68
+ }
69
+ this.emit(
70
+ 'newContact',
71
+ contact.getPeerDescriptor(),
72
+ this.getClosestContacts().map((contact: Contact) => contact.getPeerDescriptor())
73
+ )
74
+ }
75
+ }
76
+
77
+ public addContacts(contacts: Contact[]): void {
78
+ contacts.forEach((contact) => this.addContact(contact))
79
+ }
80
+
81
+ public setContacted(contactId: PeerID): void {
82
+ if (this.contactsById.has(contactId.toKey())) {
83
+ this.contactsById.get(contactId.toKey())!.contacted = true
84
+ }
85
+ }
86
+
87
+ public setActive(contactId: PeerID): void {
88
+ if (this.contactsById.has(contactId.toKey())) {
89
+ this.contactsById.get(contactId.toKey())!.active = true
90
+ }
91
+ }
92
+
93
+ public getClosestContacts(limit = this.getContactsLimit): Contact[] {
94
+ const ret: Contact[] = []
95
+ this.contactIds.forEach((contactId) => {
96
+ const contact = this.contactsById.get(contactId.toKey())
97
+ if (contact) {
98
+ ret.push(contact.contact)
99
+ }
100
+ })
101
+ return ret.splice(0, limit)
102
+ }
103
+
104
+ public getUncontactedContacts(num: number): Contact[] {
105
+ const ret: Contact[] = []
106
+ for (const contactId of this.contactIds) {
107
+ const contact = this.contactsById.get(contactId.toKey())
108
+ if (contact && !contact.contacted) {
109
+ ret.push(contact.contact)
110
+ if (ret.length >= num) {
111
+ return ret
112
+ }
113
+ }
114
+ }
115
+ return ret
116
+ }
117
+
118
+ public getActiveContacts(limit?: number): Contact[] {
119
+ const ret: Contact[] = []
120
+ this.contactIds.forEach((contactId) => {
121
+ const contact = this.contactsById.get(contactId.toKey())
122
+ if (contact && contact.active) {
123
+ ret.push(contact.contact)
124
+ }
125
+ })
126
+ if (limit !== undefined) {
127
+ return ret.splice(0, limit)
128
+ } else {
129
+ return ret
130
+ }
131
+ }
132
+
133
+ public compareIds(id1: PeerID, id2: PeerID): number {
134
+ const distance1 = KBucket.distance(this.ownId.value, id1.value)
135
+ const distance2 = KBucket.distance(this.ownId.value, id2.value)
136
+ return distance1 - distance2
137
+ }
138
+
139
+ public getStringIds(): string[] {
140
+ return this.contactIds.map((peerId) => peerId.toKey())
141
+ }
142
+
143
+ public getSize(): number {
144
+ return this.contactIds.length
145
+ }
146
+
147
+ public getContact(id: PeerID): ContactState<Contact> {
148
+ return this.contactsById.get(id.toKey())!
149
+ }
150
+
151
+ public removeContact(id: PeerID): boolean {
152
+ if (this.contactsById.has(id.toKey())) {
153
+ const removedDescriptor = this.contactsById.get(id.toKey())!.contact.getPeerDescriptor()
154
+ const index = this.contactIds.indexOf(id)
155
+ this.contactIds.splice(index, 1)
156
+ this.contactsById.delete(id.toKey())
157
+ this.emit(
158
+ 'contactRemoved',
159
+ removedDescriptor,
160
+ this.getClosestContacts().map((contact: Contact) => contact.getPeerDescriptor())
161
+ )
162
+ return true
163
+ }
164
+ return false
165
+ }
166
+
167
+ public hasContact(id: PeerID): boolean {
168
+ return this.contactsById.has(id.toKey())
169
+ }
170
+
171
+ public isActive(id: PeerID): boolean {
172
+ return this.contactsById.has(id.toKey()) ? this.contactsById.get(id.toKey())!.active : false
173
+ }
174
+
175
+ public getAllContacts(): Contact[] {
176
+ return this.contactIds.map((peerId) => this.contactsById.get(peerId.toKey())!.contact)
177
+ }
178
+
179
+ public getMaxSize(): number {
180
+ return this.maxSize
181
+ }
182
+
183
+ public setAllAsUncontacted(): void {
184
+ this.contactsById.forEach((contact) => contact.contacted = false)
185
+ }
186
+
187
+ public clear(): void {
188
+ this.contactsById.clear()
189
+ this.contactIds = []
190
+ }
191
+
192
+ public stop(): void {
193
+ this.removeAllListeners()
194
+ this.clear()
195
+ }
196
+ }
@@ -0,0 +1,150 @@
1
+ import { RpcCommunicator, toProtoRpcClient } from '@streamr/proto-rpc'
2
+ import { Logger, runAndWaitForEvents3 } from '@streamr/utils'
3
+ import EventEmitter from 'eventemitter3'
4
+ import KBucket from 'k-bucket'
5
+ import { v4 } from 'uuid'
6
+ import { PeerID } from '../../helpers/PeerID'
7
+ import { PeerDescriptor } from '../../proto/packages/dht/protos/DhtRpc'
8
+ import { DhtRpcServiceClient } from '../../proto/packages/dht/protos/DhtRpc.client'
9
+ import { SortedContactList } from '../contact/SortedContactList'
10
+ import { DhtPeer } from '../DhtPeer'
11
+ import { peerIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
12
+
13
+ const logger = new Logger(module)
14
+
15
+ interface DiscoverySessionEvents {
16
+ discoveryCompleted: () => void
17
+ }
18
+
19
+ interface DiscoverySessionConfig {
20
+ bucket: KBucket<DhtPeer>
21
+ neighborList: SortedContactList<DhtPeer>
22
+ targetId: Uint8Array
23
+ ownPeerDescriptor: PeerDescriptor
24
+ serviceId: string
25
+ rpcCommunicator: RpcCommunicator
26
+ parallelism: number
27
+ noProgressLimit: number
28
+ newContactListener?: (dhtPeer: DhtPeer) => void
29
+ nodeName?: string
30
+ }
31
+
32
+ export class DiscoverySession {
33
+ public readonly sessionId = v4()
34
+
35
+ private stopped = false
36
+ private emitter = new EventEmitter<DiscoverySessionEvents>()
37
+ private outgoingClosestPeersRequestsCounter = 0
38
+ private noProgressCounter = 0
39
+ private ongoingClosestPeersRequests: Set<string> = new Set()
40
+ private readonly config: DiscoverySessionConfig
41
+ private readonly ownPeerId: PeerID
42
+
43
+ constructor(config: DiscoverySessionConfig) {
44
+ this.config = config
45
+ this.ownPeerId = peerIdFromPeerDescriptor(config.ownPeerDescriptor)
46
+ }
47
+
48
+ private addNewContacts(contacts: PeerDescriptor[]): void {
49
+ if (this.stopped) {
50
+ return
51
+ }
52
+ contacts.forEach((contact) => {
53
+ const dhtPeer = new DhtPeer(
54
+ this.config.ownPeerDescriptor,
55
+ contact,
56
+ toProtoRpcClient(new DhtRpcServiceClient(this.config.rpcCommunicator!.getRpcClientTransport())),
57
+ this.config.serviceId
58
+ )
59
+ if (!dhtPeer.getPeerId().equals(this.ownPeerId!)) {
60
+ if (this.config.newContactListener) {
61
+ this.config.newContactListener(dhtPeer)
62
+ }
63
+ if (!this.config.neighborList.getContact(dhtPeer.getPeerId())) {
64
+ this.config.neighborList!.addContact(dhtPeer)
65
+ }
66
+ }
67
+ })
68
+ }
69
+
70
+ private async getClosestPeersFromContact(contact: DhtPeer): Promise<PeerDescriptor[]> {
71
+ if (this.stopped) {
72
+ return []
73
+ }
74
+ logger.trace(`Getting closest peers from contact: ${contact.getPeerId().toKey()}`)
75
+ this.outgoingClosestPeersRequestsCounter++
76
+ this.config.neighborList!.setContacted(contact.getPeerId())
77
+ const returnedContacts = await contact.getClosestPeers(this.config.targetId)
78
+ this.config.neighborList!.setActive(contact.getPeerId())
79
+ return returnedContacts
80
+ }
81
+
82
+ private onClosestPeersRequestSucceeded(peerId: PeerID, contacts: PeerDescriptor[]) {
83
+ if (!this.ongoingClosestPeersRequests.has(peerId.toKey())) {
84
+ return
85
+ }
86
+ this.ongoingClosestPeersRequests.delete(peerId.toKey())
87
+ const oldClosestContact = this.config.neighborList!.getClosestContactId()
88
+ this.addNewContacts(contacts)
89
+ if (this.config.neighborList!.getClosestContactId().equals(oldClosestContact)) {
90
+ this.noProgressCounter++
91
+ } else {
92
+ this.noProgressCounter = 0
93
+ }
94
+ }
95
+
96
+ private onClosestPeersRequestFailed(peer: DhtPeer, _exception: Error) {
97
+ if (!this.ongoingClosestPeersRequests.has(peer.getPeerId().toKey())) {
98
+ return
99
+ }
100
+ this.ongoingClosestPeersRequests.delete(peer.getPeerId().toKey())
101
+ this.config.bucket.remove(peer.getPeerId().value)
102
+ this.config.neighborList!.removeContact(peer.getPeerId())
103
+ }
104
+
105
+ private findMoreContacts(): void {
106
+ if (this.stopped) {
107
+ return
108
+ }
109
+ const uncontacted = this.config.neighborList!.getUncontactedContacts(this.config.parallelism)
110
+ if (uncontacted.length < 1 || this.noProgressCounter >= this.config.noProgressLimit) {
111
+ this.emitter.emit('discoveryCompleted')
112
+ this.stopped = true
113
+ return
114
+ }
115
+ for (const nextPeer of uncontacted) {
116
+ if (this.ongoingClosestPeersRequests.size >= this.config.parallelism) {
117
+ break
118
+ }
119
+ this.ongoingClosestPeersRequests.add(nextPeer!.getPeerId().toKey())
120
+ // eslint-disable-next-line promise/catch-or-return
121
+ this.getClosestPeersFromContact(nextPeer!)
122
+ .then((contacts) => this.onClosestPeersRequestSucceeded(nextPeer!.getPeerId(), contacts))
123
+ .catch((err) => this.onClosestPeersRequestFailed(nextPeer!, err))
124
+ .finally(() => {
125
+ this.outgoingClosestPeersRequestsCounter--
126
+ this.findMoreContacts()
127
+ })
128
+ }
129
+ }
130
+
131
+ public async findClosestNodes(timeout: number): Promise<SortedContactList<DhtPeer>> {
132
+ if (this.config.neighborList!.getUncontactedContacts(this.config.parallelism).length < 1) {
133
+ logger.trace('getUncontactedContacts length was 0 in beginning of discovery, this.neighborList.size: '
134
+ + this.config.neighborList.getSize())
135
+ return this.config.neighborList
136
+ }
137
+ await runAndWaitForEvents3<DiscoverySessionEvents>(
138
+ [this.findMoreContacts.bind(this)],
139
+ [[this.emitter, 'discoveryCompleted']],
140
+ timeout
141
+ )
142
+ return this.config.neighborList
143
+ }
144
+
145
+ public stop(): void {
146
+ this.stopped = true
147
+ this.emitter.emit('discoveryCompleted')
148
+ this.emitter.removeAllListeners()
149
+ }
150
+ }