@streamr/dht 100.0.0-pretestnet.6 → 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 (444) hide show
  1. package/README.md +90 -8
  2. package/dist/package.json +70 -0
  3. package/dist/src/connection/Connection.d.ts +1 -0
  4. package/dist/src/connection/Connection.js +10 -3
  5. package/dist/src/connection/Connection.js.map +1 -1
  6. package/dist/src/connection/ConnectionLockHandler.d.ts +14 -14
  7. package/dist/src/connection/ConnectionLockHandler.js +22 -16
  8. package/dist/src/connection/ConnectionLockHandler.js.map +1 -1
  9. package/dist/src/connection/ConnectionLockRpcLocal.d.ts +3 -3
  10. package/dist/src/connection/ConnectionLockRpcLocal.js +7 -6
  11. package/dist/src/connection/ConnectionLockRpcLocal.js.map +1 -1
  12. package/dist/src/connection/ConnectionLockRpcRemote.d.ts +4 -6
  13. package/dist/src/connection/ConnectionLockRpcRemote.js +10 -37
  14. package/dist/src/connection/ConnectionLockRpcRemote.js.map +1 -1
  15. package/dist/src/connection/ConnectionManager.d.ts +19 -20
  16. package/dist/src/connection/ConnectionManager.js +132 -117
  17. package/dist/src/connection/ConnectionManager.js.map +1 -1
  18. package/dist/src/connection/ConnectorFacade.d.ts +3 -2
  19. package/dist/src/connection/ConnectorFacade.js +10 -3
  20. package/dist/src/connection/ConnectorFacade.js.map +1 -1
  21. package/dist/src/connection/Handshaker.d.ts +3 -1
  22. package/dist/src/connection/Handshaker.js +18 -9
  23. package/dist/src/connection/Handshaker.js.map +1 -1
  24. package/dist/src/connection/IConnection.d.ts +2 -7
  25. package/dist/src/connection/IConnection.js +1 -8
  26. package/dist/src/connection/IConnection.js.map +1 -1
  27. package/dist/src/connection/ManagedConnection.d.ts +5 -7
  28. package/dist/src/connection/ManagedConnection.js +42 -26
  29. package/dist/src/connection/ManagedConnection.js.map +1 -1
  30. package/dist/src/connection/ManagedWebrtcConnection.js.map +1 -1
  31. package/dist/src/connection/connectivityChecker.d.ts +9 -0
  32. package/dist/src/connection/connectivityChecker.js +130 -0
  33. package/dist/src/connection/connectivityChecker.js.map +1 -0
  34. package/dist/src/connection/connectivityRequestHandler.d.ts +3 -0
  35. package/dist/src/connection/connectivityRequestHandler.js +101 -0
  36. package/dist/src/connection/connectivityRequestHandler.js.map +1 -0
  37. package/dist/src/connection/simulator/Simulator.d.ts +0 -3
  38. package/dist/src/connection/simulator/Simulator.js +34 -69
  39. package/dist/src/connection/simulator/Simulator.js.map +1 -1
  40. package/dist/src/connection/simulator/SimulatorConnection.js +27 -25
  41. package/dist/src/connection/simulator/SimulatorConnection.js.map +1 -1
  42. package/dist/src/connection/simulator/SimulatorConnector.js +16 -12
  43. package/dist/src/connection/simulator/SimulatorConnector.js.map +1 -1
  44. package/dist/src/connection/simulator/pings.js.map +1 -1
  45. package/dist/src/connection/webrtc/NodeWebrtcConnection.d.ts +2 -3
  46. package/dist/src/connection/webrtc/NodeWebrtcConnection.js +40 -27
  47. package/dist/src/connection/webrtc/NodeWebrtcConnection.js.map +1 -1
  48. package/dist/src/connection/webrtc/WebrtcConnector.d.ts +0 -2
  49. package/dist/src/connection/webrtc/WebrtcConnector.js +24 -25
  50. package/dist/src/connection/webrtc/WebrtcConnector.js.map +1 -1
  51. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.d.ts +2 -2
  52. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js +27 -20
  53. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js.map +1 -1
  54. package/dist/src/connection/webrtc/WebrtcConnectorRpcRemote.d.ts +3 -6
  55. package/dist/src/connection/webrtc/WebrtcConnectorRpcRemote.js +2 -5
  56. package/dist/src/connection/webrtc/WebrtcConnectorRpcRemote.js.map +1 -1
  57. package/dist/src/connection/webrtc/iceServerAsString.js +1 -1
  58. package/dist/src/connection/webrtc/iceServerAsString.js.map +1 -1
  59. package/dist/src/connection/websocket/AutoCertifierClientFacade.d.ts +1 -2
  60. package/dist/src/connection/websocket/AutoCertifierClientFacade.js +6 -4
  61. package/dist/src/connection/websocket/AutoCertifierClientFacade.js.map +1 -1
  62. package/dist/src/connection/websocket/ClientWebsocket.d.ts +1 -0
  63. package/dist/src/connection/websocket/ClientWebsocket.js +14 -7
  64. package/dist/src/connection/websocket/ClientWebsocket.js.map +1 -1
  65. package/dist/src/connection/websocket/WebsocketConnector.d.ts +3 -9
  66. package/dist/src/connection/websocket/WebsocketConnector.js +142 -74
  67. package/dist/src/connection/websocket/WebsocketConnector.js.map +1 -1
  68. package/dist/src/connection/websocket/WebsocketConnectorRpcLocal.d.ts +5 -3
  69. package/dist/src/connection/websocket/WebsocketConnectorRpcLocal.js +9 -12
  70. package/dist/src/connection/websocket/WebsocketConnectorRpcLocal.js.map +1 -1
  71. package/dist/src/connection/websocket/WebsocketConnectorRpcRemote.d.ts +4 -7
  72. package/dist/src/connection/websocket/WebsocketConnectorRpcRemote.js +7 -44
  73. package/dist/src/connection/websocket/WebsocketConnectorRpcRemote.js.map +1 -1
  74. package/dist/src/connection/websocket/WebsocketServer.d.ts +1 -4
  75. package/dist/src/connection/websocket/WebsocketServer.js +49 -40
  76. package/dist/src/connection/websocket/WebsocketServer.js.map +1 -1
  77. package/dist/src/connection/websocket/{ServerWebsocket.d.ts → WebsocketServerConnection.d.ts} +8 -4
  78. package/dist/src/connection/websocket/WebsocketServerConnection.js +97 -0
  79. package/dist/src/connection/websocket/WebsocketServerConnection.js.map +1 -0
  80. package/dist/src/dht/DhtNode.d.ts +45 -49
  81. package/dist/src/dht/DhtNode.js +229 -317
  82. package/dist/src/dht/DhtNode.js.map +1 -1
  83. package/dist/src/dht/DhtNodeRpcLocal.d.ts +10 -9
  84. package/dist/src/dht/DhtNodeRpcLocal.js +19 -11
  85. package/dist/src/dht/DhtNodeRpcLocal.js.map +1 -1
  86. package/dist/src/dht/DhtNodeRpcRemote.d.ts +15 -10
  87. package/dist/src/dht/DhtNodeRpcRemote.js +38 -21
  88. package/dist/src/dht/DhtNodeRpcRemote.js.map +1 -1
  89. package/dist/src/dht/ExternalApiRpcLocal.d.ts +7 -6
  90. package/dist/src/dht/ExternalApiRpcLocal.js +9 -13
  91. package/dist/src/dht/ExternalApiRpcLocal.js.map +1 -1
  92. package/dist/src/dht/ExternalApiRpcRemote.d.ts +6 -5
  93. package/dist/src/dht/ExternalApiRpcRemote.js +10 -7
  94. package/dist/src/dht/ExternalApiRpcRemote.js.map +1 -1
  95. package/dist/src/dht/PeerManager.d.ts +61 -0
  96. package/dist/src/dht/PeerManager.js +288 -0
  97. package/dist/src/dht/PeerManager.js.map +1 -0
  98. package/dist/src/dht/contact/Contact.d.ts +2 -2
  99. package/dist/src/dht/contact/Contact.js +4 -3
  100. package/dist/src/dht/contact/Contact.js.map +1 -1
  101. package/dist/src/dht/contact/ContactList.d.ts +8 -8
  102. package/dist/src/dht/contact/ContactList.js +12 -7
  103. package/dist/src/dht/contact/ContactList.js.map +1 -1
  104. package/dist/src/dht/contact/RandomContactList.d.ts +4 -4
  105. package/dist/src/dht/contact/RandomContactList.js +13 -12
  106. package/dist/src/dht/contact/RandomContactList.js.map +1 -1
  107. package/dist/src/dht/contact/RingContactList.d.ts +31 -0
  108. package/dist/src/dht/contact/RingContactList.js +133 -0
  109. package/dist/src/dht/contact/RingContactList.js.map +1 -0
  110. package/dist/src/dht/contact/{Remote.d.ts → RpcRemote.d.ts} +8 -7
  111. package/dist/src/dht/contact/{Remote.js → RpcRemote.js} +16 -13
  112. package/dist/src/dht/contact/RpcRemote.js.map +1 -0
  113. package/dist/src/dht/contact/SortedContactList.d.ts +29 -15
  114. package/dist/src/dht/contact/SortedContactList.js +79 -42
  115. package/dist/src/dht/contact/SortedContactList.js.map +1 -1
  116. package/dist/src/dht/contact/ringIdentifiers.d.ts +16 -0
  117. package/dist/src/dht/contact/ringIdentifiers.js +54 -0
  118. package/dist/src/dht/contact/ringIdentifiers.js.map +1 -0
  119. package/dist/src/dht/discovery/DiscoverySession.d.ts +8 -18
  120. package/dist/src/dht/discovery/DiscoverySession.js +32 -48
  121. package/dist/src/dht/discovery/DiscoverySession.js.map +1 -1
  122. package/dist/src/dht/discovery/PeerDiscovery.d.ts +16 -12
  123. package/dist/src/dht/discovery/PeerDiscovery.js +82 -39
  124. package/dist/src/dht/discovery/PeerDiscovery.js.map +1 -1
  125. package/dist/src/dht/discovery/RingDiscoverySession.d.ts +29 -0
  126. package/dist/src/dht/discovery/RingDiscoverySession.js +123 -0
  127. package/dist/src/dht/discovery/RingDiscoverySession.js.map +1 -0
  128. package/dist/src/dht/recursive-operation/RecursiveOperationManager.d.ts +36 -0
  129. package/dist/src/dht/recursive-operation/RecursiveOperationManager.js +166 -0
  130. package/dist/src/dht/recursive-operation/RecursiveOperationManager.js.map +1 -0
  131. package/dist/src/dht/recursive-operation/RecursiveOperationRpcLocal.d.ts +14 -0
  132. package/dist/src/dht/recursive-operation/RecursiveOperationRpcLocal.js +26 -0
  133. package/dist/src/dht/recursive-operation/RecursiveOperationRpcLocal.js.map +1 -0
  134. package/dist/src/dht/recursive-operation/RecursiveOperationRpcRemote.d.ts +6 -0
  135. package/dist/src/dht/recursive-operation/RecursiveOperationRpcRemote.js +44 -0
  136. package/dist/src/dht/recursive-operation/RecursiveOperationRpcRemote.js.map +1 -0
  137. package/dist/src/dht/recursive-operation/RecursiveOperationSession.d.ts +44 -0
  138. package/dist/src/dht/recursive-operation/RecursiveOperationSession.js +187 -0
  139. package/dist/src/dht/recursive-operation/RecursiveOperationSession.js.map +1 -0
  140. package/dist/src/dht/recursive-operation/RecursiveOperationSessionRpcLocal.d.ts +14 -0
  141. package/dist/src/dht/recursive-operation/RecursiveOperationSessionRpcLocal.js +20 -0
  142. package/dist/src/dht/recursive-operation/RecursiveOperationSessionRpcLocal.js.map +1 -0
  143. package/dist/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.d.ts +6 -0
  144. package/dist/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.js +21 -0
  145. package/dist/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.js.map +1 -0
  146. package/dist/src/dht/routing/DuplicateDetector.d.ts +2 -4
  147. package/dist/src/dht/routing/DuplicateDetector.js +10 -15
  148. package/dist/src/dht/routing/DuplicateDetector.js.map +1 -1
  149. package/dist/src/dht/routing/Router.d.ts +11 -27
  150. package/dist/src/dht/routing/Router.js +92 -58
  151. package/dist/src/dht/routing/Router.js.map +1 -1
  152. package/dist/src/dht/routing/RouterRpcLocal.d.ts +3 -4
  153. package/dist/src/dht/routing/RouterRpcLocal.js +17 -16
  154. package/dist/src/dht/routing/RouterRpcLocal.js.map +1 -1
  155. package/dist/src/dht/routing/RouterRpcRemote.d.ts +3 -3
  156. package/dist/src/dht/routing/RouterRpcRemote.js +29 -20
  157. package/dist/src/dht/routing/RouterRpcRemote.js.map +1 -1
  158. package/dist/src/dht/routing/RoutingSession.d.ts +29 -21
  159. package/dist/src/dht/routing/RoutingSession.js +93 -68
  160. package/dist/src/dht/routing/RoutingSession.js.map +1 -1
  161. package/dist/src/dht/routing/RoutingTablesCache.d.ts +24 -0
  162. package/dist/src/dht/routing/RoutingTablesCache.js +46 -0
  163. package/dist/src/dht/routing/RoutingTablesCache.js.map +1 -0
  164. package/dist/src/dht/routing/getPreviousPeer.js.map +1 -1
  165. package/dist/src/dht/store/LocalDataStore.d.ts +9 -14
  166. package/dist/src/dht/store/LocalDataStore.js +46 -72
  167. package/dist/src/dht/store/LocalDataStore.js.map +1 -1
  168. package/dist/src/dht/store/StoreManager.d.ts +33 -0
  169. package/dist/src/dht/store/StoreManager.js +182 -0
  170. package/dist/src/dht/store/StoreManager.js.map +1 -0
  171. package/dist/src/dht/store/StoreRpcLocal.d.ts +11 -41
  172. package/dist/src/dht/store/StoreRpcLocal.js +27 -234
  173. package/dist/src/dht/store/StoreRpcLocal.js.map +1 -1
  174. package/dist/src/dht/store/StoreRpcRemote.d.ts +6 -7
  175. package/dist/src/dht/store/StoreRpcRemote.js +10 -20
  176. package/dist/src/dht/store/StoreRpcRemote.js.map +1 -1
  177. package/dist/src/exports.d.ts +5 -3
  178. package/dist/src/exports.js +10 -8
  179. package/dist/src/exports.js.map +1 -1
  180. package/dist/src/helpers/AddressTools.js +2 -0
  181. package/dist/src/helpers/AddressTools.js.map +1 -1
  182. package/dist/src/helpers/Connectivity.js.map +1 -1
  183. package/dist/src/helpers/MapWithTtl.d.ts +14 -0
  184. package/dist/src/helpers/MapWithTtl.js +60 -0
  185. package/dist/src/helpers/MapWithTtl.js.map +1 -0
  186. package/dist/src/helpers/createPeerDescriptor.d.ts +3 -0
  187. package/dist/src/helpers/createPeerDescriptor.js +57 -0
  188. package/dist/src/helpers/createPeerDescriptor.js.map +1 -0
  189. package/dist/src/helpers/createPeerDescriptorSignaturePayload.d.ts +2 -0
  190. package/dist/src/helpers/createPeerDescriptorSignaturePayload.js +30 -0
  191. package/dist/src/helpers/createPeerDescriptorSignaturePayload.js.map +1 -0
  192. package/dist/src/helpers/debugHelpers.js.map +1 -1
  193. package/dist/src/helpers/errors.js +2 -0
  194. package/dist/src/helpers/errors.js.map +1 -1
  195. package/dist/src/helpers/offering.d.ts +4 -0
  196. package/dist/src/helpers/offering.js +18 -0
  197. package/dist/src/helpers/offering.js.map +1 -0
  198. package/dist/src/helpers/protoClasses.js +2 -3
  199. package/dist/src/helpers/protoClasses.js.map +1 -1
  200. package/dist/src/helpers/protoToString.js.map +1 -1
  201. package/dist/src/helpers/version.d.ts +6 -0
  202. package/dist/src/helpers/version.js +38 -0
  203. package/dist/src/helpers/version.js.map +1 -0
  204. package/dist/src/identifiers.d.ts +10 -0
  205. package/dist/src/identifiers.js +31 -0
  206. package/dist/src/identifiers.js.map +1 -0
  207. package/dist/src/proto/google/protobuf/any.js +8 -8
  208. package/dist/src/proto/google/protobuf/any.js.map +1 -1
  209. package/dist/src/proto/google/protobuf/empty.js +2 -4
  210. package/dist/src/proto/google/protobuf/empty.js.map +1 -1
  211. package/dist/src/proto/google/protobuf/timestamp.js +10 -10
  212. package/dist/src/proto/google/protobuf/timestamp.js.map +1 -1
  213. package/dist/src/proto/packages/dht/protos/DhtRpc.client.d.ts +46 -49
  214. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js +63 -54
  215. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +1 -1
  216. package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +226 -232
  217. package/dist/src/proto/packages/dht/protos/DhtRpc.js +146 -168
  218. package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
  219. package/dist/src/proto/packages/dht/protos/DhtRpc.server.d.ts +26 -29
  220. package/dist/src/proto/packages/proto-rpc/protos/ProtoRpc.js +1 -1
  221. package/dist/src/rpc-protocol/DhtCallContext.d.ts +2 -2
  222. package/dist/src/rpc-protocol/DhtCallContext.js +8 -0
  223. package/dist/src/rpc-protocol/DhtCallContext.js.map +1 -1
  224. package/dist/src/rpc-protocol/DhtRpcOptions.d.ts +2 -1
  225. package/dist/src/transport/ITransport.d.ts +10 -2
  226. package/dist/src/transport/ITransport.js +5 -0
  227. package/dist/src/transport/ITransport.js.map +1 -1
  228. package/dist/src/transport/ListeningRpcCommunicator.js +3 -1
  229. package/dist/src/transport/ListeningRpcCommunicator.js.map +1 -1
  230. package/dist/src/transport/RoutingRpcCommunicator.d.ts +4 -2
  231. package/dist/src/transport/RoutingRpcCommunicator.js +19 -12
  232. package/dist/src/transport/RoutingRpcCommunicator.js.map +1 -1
  233. package/jest.config.js +4 -1
  234. package/karma-setup.js +2 -0
  235. package/karma.config.js +13 -9
  236. package/package.json +16 -13
  237. package/protos/DhtRpc.proto +76 -76
  238. package/src/connection/Connection.ts +6 -1
  239. package/src/connection/ConnectionLockHandler.ts +30 -22
  240. package/src/connection/ConnectionLockRpcLocal.ts +7 -12
  241. package/src/connection/ConnectionLockRpcRemote.ts +9 -19
  242. package/src/connection/ConnectionManager.ts +132 -138
  243. package/src/connection/ConnectorFacade.ts +10 -9
  244. package/src/connection/Handshaker.ts +23 -11
  245. package/src/connection/IConnection.ts +2 -8
  246. package/src/connection/ManagedConnection.ts +34 -35
  247. package/src/connection/connectivityChecker.ts +109 -0
  248. package/src/connection/connectivityRequestHandler.ts +103 -0
  249. package/src/connection/simulator/Simulator.ts +6 -37
  250. package/src/connection/simulator/SimulatorConnection.ts +23 -25
  251. package/src/connection/simulator/SimulatorConnector.ts +11 -11
  252. package/src/connection/webrtc/BrowserWebrtcConnection.ts +17 -25
  253. package/src/connection/webrtc/NodeWebrtcConnection.ts +24 -26
  254. package/src/connection/webrtc/WebrtcConnector.ts +18 -29
  255. package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +29 -24
  256. package/src/connection/webrtc/WebrtcConnectorRpcRemote.ts +4 -14
  257. package/src/connection/webrtc/iceServerAsString.ts +1 -1
  258. package/src/connection/websocket/AutoCertifierClientFacade.ts +4 -6
  259. package/src/connection/websocket/ClientWebsocket.ts +10 -4
  260. package/src/connection/websocket/WebsocketConnector.ts +120 -97
  261. package/src/connection/websocket/WebsocketConnectorRpcLocal.ts +13 -15
  262. package/src/connection/websocket/WebsocketConnectorRpcRemote.ts +7 -27
  263. package/src/connection/websocket/WebsocketServer.ts +50 -53
  264. package/src/connection/websocket/WebsocketServerConnection.ts +104 -0
  265. package/src/dht/DhtNode.ts +289 -410
  266. package/src/dht/DhtNodeRpcLocal.ts +25 -17
  267. package/src/dht/DhtNodeRpcRemote.ts +43 -27
  268. package/src/dht/ExternalApiRpcLocal.ts +30 -17
  269. package/src/dht/ExternalApiRpcRemote.ts +14 -11
  270. package/src/dht/PeerManager.ts +339 -0
  271. package/src/dht/contact/Contact.ts +4 -4
  272. package/src/dht/contact/ContactList.ts +11 -10
  273. package/src/dht/contact/RandomContactList.ts +15 -15
  274. package/src/dht/contact/RingContactList.ts +151 -0
  275. package/src/dht/contact/{Remote.ts → RpcRemote.ts} +16 -19
  276. package/src/dht/contact/SortedContactList.ts +120 -72
  277. package/src/dht/contact/ringIdentifiers.ts +62 -0
  278. package/src/dht/discovery/DiscoverySession.ts +36 -61
  279. package/src/dht/discovery/PeerDiscovery.ts +98 -43
  280. package/src/dht/discovery/RingDiscoverySession.ts +160 -0
  281. package/src/dht/recursive-operation/RecursiveOperationManager.ts +246 -0
  282. package/src/dht/recursive-operation/RecursiveOperationRpcLocal.ts +34 -0
  283. package/src/dht/recursive-operation/RecursiveOperationRpcRemote.ts +43 -0
  284. package/src/dht/recursive-operation/RecursiveOperationSession.ts +232 -0
  285. package/src/dht/recursive-operation/RecursiveOperationSessionRpcLocal.ts +35 -0
  286. package/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.ts +30 -0
  287. package/src/dht/routing/DuplicateDetector.ts +9 -21
  288. package/src/dht/routing/Router.ts +95 -92
  289. package/src/dht/routing/RouterRpcLocal.ts +16 -18
  290. package/src/dht/routing/RouterRpcRemote.ts +26 -24
  291. package/src/dht/routing/RoutingSession.ts +119 -98
  292. package/src/dht/routing/RoutingTablesCache.ts +58 -0
  293. package/src/dht/routing/getPreviousPeer.ts +1 -1
  294. package/src/dht/store/LocalDataStore.ts +47 -77
  295. package/src/dht/store/StoreManager.ts +209 -0
  296. package/src/dht/store/StoreRpcLocal.ts +39 -308
  297. package/src/dht/store/StoreRpcRemote.ts +13 -31
  298. package/src/exports.ts +13 -3
  299. package/src/helpers/AddressTools.ts +2 -0
  300. package/src/helpers/MapWithTtl.ts +71 -0
  301. package/src/helpers/createPeerDescriptor.ts +57 -0
  302. package/src/helpers/createPeerDescriptorSignaturePayload.ts +28 -0
  303. package/src/helpers/offering.ts +15 -0
  304. package/src/helpers/protoClasses.ts +4 -6
  305. package/src/helpers/version.ts +32 -0
  306. package/src/identifiers.ts +29 -0
  307. package/src/proto/google/protobuf/any.ts +4 -4
  308. package/src/proto/google/protobuf/empty.ts +2 -4
  309. package/src/proto/google/protobuf/timestamp.ts +4 -4
  310. package/src/proto/packages/dht/protos/DhtRpc.client.ts +65 -68
  311. package/src/proto/packages/dht/protos/DhtRpc.server.ts +27 -30
  312. package/src/proto/packages/dht/protos/DhtRpc.ts +297 -313
  313. package/src/proto/packages/proto-rpc/protos/ProtoRpc.ts +1 -1
  314. package/src/rpc-protocol/DhtCallContext.ts +2 -2
  315. package/src/rpc-protocol/DhtRpcOptions.ts +2 -1
  316. package/src/transport/ITransport.ts +11 -2
  317. package/src/transport/ListeningRpcCommunicator.ts +1 -1
  318. package/src/transport/RoutingRpcCommunicator.ts +21 -14
  319. package/test/RandomGraphSimulation.ts +3 -2
  320. package/test/benchmark/Find.test.ts +13 -28
  321. package/test/benchmark/KademliaCorrectness.test.ts +24 -28
  322. package/test/benchmark/RingCorrectness.test.ts +157 -0
  323. package/test/benchmark/SortedContactListBenchmark.test.ts +151 -0
  324. package/test/benchmark/WebsocketServerMemoryLeak.test.ts +41 -0
  325. package/test/benchmark/hybrid-network-simulation/RingContactList.test.ts +72 -0
  326. package/test/benchmark/kademlia-simulation/Contact.ts +9 -9
  327. package/test/benchmark/kademlia-simulation/KademliaSimulation.ts +11 -11
  328. package/test/benchmark/kademlia-simulation/SimulationNode.ts +29 -25
  329. package/test/data/generateGroundTruthData.ts +7 -6
  330. package/test/end-to-end/Layer0-Layer1.test.ts +11 -15
  331. package/test/end-to-end/Layer0.test.ts +19 -22
  332. package/test/end-to-end/Layer0MixedConnectionTypes.test.ts +19 -21
  333. package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +26 -28
  334. package/test/end-to-end/Layer0Webrtc.test.ts +19 -19
  335. package/test/end-to-end/Layer1-Scale-WebSocket.test.ts +10 -18
  336. package/test/end-to-end/Layer1-Scale-Webrtc.test.ts +8 -15
  337. package/test/end-to-end/RecoveryFromFailedAutoCertification.test.ts +2 -2
  338. package/test/end-to-end/WebsocketConnectionRequest.test.ts +8 -9
  339. package/test/end-to-end/memory-leak.test.ts +19 -24
  340. package/test/integration/ConnectionLocking.test.ts +66 -60
  341. package/test/integration/ConnectionManager.test.ts +43 -63
  342. package/test/integration/ConnectivityChecking.test.ts +52 -0
  343. package/test/integration/DhtJoinPeerDiscovery.test.ts +8 -12
  344. package/test/integration/DhtNodeExternalAPI.test.ts +17 -21
  345. package/test/integration/DhtNodeRpcRemote.test.ts +19 -26
  346. package/test/integration/DhtRpc.test.ts +20 -24
  347. package/test/integration/Find.test.ts +10 -12
  348. package/test/integration/Layer1-scale.test.ts +25 -37
  349. package/test/integration/Mock-Layer1-Layer0.test.ts +39 -59
  350. package/test/integration/MultipleEntryPointJoining.test.ts +14 -14
  351. package/test/integration/ReplicateData.test.ts +106 -0
  352. package/test/integration/RouteMessage.test.ts +42 -68
  353. package/test/integration/RouterRpcRemote.test.ts +19 -24
  354. package/test/integration/ScaleDownDht.test.ts +14 -12
  355. package/test/integration/SimultaneousConnections.test.ts +112 -111
  356. package/test/integration/Store.test.ts +43 -27
  357. package/test/integration/StoreAndDelete.test.ts +36 -48
  358. package/test/integration/StoreOnDhtWithThreeNodes.test.ts +59 -0
  359. package/test/integration/StoreOnDhtWithTwoNodes.test.ts +17 -37
  360. package/test/integration/StoreRpcRemote.test.ts +20 -32
  361. package/test/integration/WebrtcConnectionManagement.test.ts +39 -25
  362. package/test/integration/WebrtcConnectorRpc.test.ts +6 -11
  363. package/test/integration/WebsocketConnectionManagement.test.ts +87 -22
  364. package/test/integration/WebsocketConnectorRpc.test.ts +14 -24
  365. package/test/integration/{RpcErrors.test.ts → rpc-connections-over-webrpc.test.ts} +15 -26
  366. package/test/unit/AddressTools.test.ts +4 -0
  367. package/test/unit/ConnectivityHelpers.test.ts +9 -17
  368. package/test/unit/DuplicateDetector.test.ts +8 -5
  369. package/test/unit/LocalDataStore.test.ts +78 -75
  370. package/test/unit/PeerManager.test.ts +33 -0
  371. package/test/unit/RandomContactList.test.ts +12 -9
  372. package/test/unit/RecursiveOperationManager.test.ts +157 -0
  373. package/test/unit/RecursiveOperationSession.test.ts +68 -0
  374. package/test/unit/Router.test.ts +52 -35
  375. package/test/unit/RoutingSession.test.ts +79 -0
  376. package/test/unit/SortedContactList.test.ts +61 -30
  377. package/test/unit/StoreManager.test.ts +138 -0
  378. package/test/unit/WebsocketConnector.test.ts +27 -35
  379. package/test/unit/connectivityRequestHandler.test.ts +104 -0
  380. package/test/unit/createPeerDescriptor.test.ts +69 -0
  381. package/test/unit/customMatchers.test.ts +16 -0
  382. package/test/unit/version.test.ts +18 -0
  383. package/test/utils/FakeTransport.ts +47 -0
  384. package/test/utils/customMatchers.ts +71 -0
  385. package/test/utils/mock/MockRpcCommunicator.ts +7 -0
  386. package/test/utils/mock/Router.ts +13 -3
  387. package/test/utils/mock/Transport.ts +1 -1
  388. package/test/utils/mock/mockDataEntry.ts +38 -0
  389. package/test/utils/utils.ts +104 -107
  390. package/tsconfig.browser.json +2 -1
  391. package/tsconfig.jest.json +4 -2
  392. package/tsconfig.node.json +4 -2
  393. package/dist/src/connection/ConnectivityChecker.d.ts +0 -17
  394. package/dist/src/connection/ConnectivityChecker.js +0 -208
  395. package/dist/src/connection/ConnectivityChecker.js.map +0 -1
  396. package/dist/src/connection/websocket/ServerWebsocket.js +0 -100
  397. package/dist/src/connection/websocket/ServerWebsocket.js.map +0 -1
  398. package/dist/src/dht/contact/Remote.js.map +0 -1
  399. package/dist/src/dht/find/FindRpcLocal.d.ts +0 -14
  400. package/dist/src/dht/find/FindRpcLocal.js +0 -25
  401. package/dist/src/dht/find/FindRpcLocal.js.map +0 -1
  402. package/dist/src/dht/find/FindSession.d.ts +0 -44
  403. package/dist/src/dht/find/FindSession.js +0 -145
  404. package/dist/src/dht/find/FindSession.js.map +0 -1
  405. package/dist/src/dht/find/FindSessionRpcLocal.d.ts +0 -12
  406. package/dist/src/dht/find/FindSessionRpcLocal.js +0 -17
  407. package/dist/src/dht/find/FindSessionRpcLocal.js.map +0 -1
  408. package/dist/src/dht/find/FindSessionRpcRemote.d.ts +0 -6
  409. package/dist/src/dht/find/FindSessionRpcRemote.js +0 -21
  410. package/dist/src/dht/find/FindSessionRpcRemote.js.map +0 -1
  411. package/dist/src/dht/find/Finder.d.ts +0 -49
  412. package/dist/src/dht/find/Finder.js +0 -184
  413. package/dist/src/dht/find/Finder.js.map +0 -1
  414. package/dist/src/dht/routing/FindRpcRemote.d.ts +0 -6
  415. package/dist/src/dht/routing/FindRpcRemote.js +0 -41
  416. package/dist/src/dht/routing/FindRpcRemote.js.map +0 -1
  417. package/dist/src/helpers/PeerID.d.ts +0 -24
  418. package/dist/src/helpers/PeerID.js +0 -78
  419. package/dist/src/helpers/PeerID.js.map +0 -1
  420. package/dist/src/helpers/UUID.d.ts +0 -8
  421. package/dist/src/helpers/UUID.js +0 -36
  422. package/dist/src/helpers/UUID.js.map +0 -1
  423. package/dist/src/helpers/kademliaId.d.ts +0 -1
  424. package/dist/src/helpers/kademliaId.js +0 -14
  425. package/dist/src/helpers/kademliaId.js.map +0 -1
  426. package/dist/src/helpers/peerIdFromPeerDescriptor.d.ts +0 -6
  427. package/dist/src/helpers/peerIdFromPeerDescriptor.js +0 -23
  428. package/dist/src/helpers/peerIdFromPeerDescriptor.js.map +0 -1
  429. package/src/connection/ConnectivityChecker.ts +0 -199
  430. package/src/connection/websocket/ServerWebsocket.ts +0 -114
  431. package/src/dht/find/FindRpcLocal.ts +0 -35
  432. package/src/dht/find/FindSession.ts +0 -178
  433. package/src/dht/find/FindSessionRpcLocal.ts +0 -25
  434. package/src/dht/find/FindSessionRpcRemote.ts +0 -30
  435. package/src/dht/find/Finder.ts +0 -275
  436. package/src/dht/routing/FindRpcRemote.ts +0 -40
  437. package/src/helpers/PeerID.ts +0 -88
  438. package/src/helpers/UUID.ts +0 -35
  439. package/src/helpers/kademliaId.ts +0 -8
  440. package/src/helpers/peerIdFromPeerDescriptor.ts +0 -20
  441. package/test/integration/MigrateData.test.ts +0 -204
  442. package/test/unit/Finder.test.ts +0 -110
  443. package/test/unit/PeerID.test.ts +0 -22
  444. package/test/unit/UUID.test.ts +0 -55
@@ -1,70 +1,68 @@
1
- import { DhtNodeRpcRemote } from './DhtNodeRpcRemote'
2
- import KBucket from 'k-bucket'
1
+ import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
2
+ import {
3
+ Logger,
4
+ MetricsContext,
5
+ merge,
6
+ waitForCondition
7
+ } from '@streamr/utils'
3
8
  import { EventEmitter } from 'eventemitter3'
4
- import { SortedContactList } from './contact/SortedContactList'
5
- import { RoutingRpcCommunicator } from '../transport/RoutingRpcCommunicator'
6
- import { PeerID, PeerIDKey } from '../helpers/PeerID'
9
+ import { sample } from 'lodash'
10
+ import { MarkRequired } from 'ts-essentials'
11
+ import { ConnectionManager, PortRange, TlsCertificate } from '../connection/ConnectionManager'
12
+ import { DefaultConnectorFacade, DefaultConnectorFacadeConfig } from '../connection/ConnectorFacade'
13
+ import { IceServer } from '../connection/webrtc/WebrtcConnector'
14
+ import { isBrowserEnvironment } from '../helpers/browser/isBrowserEnvironment'
15
+ import { DhtAddress, KADEMLIA_ID_LENGTH_IN_BYTES, getNodeIdFromPeerDescriptor } from '../identifiers'
16
+ import { Any } from '../proto/google/protobuf/any'
7
17
  import {
8
18
  ClosestPeersRequest,
9
19
  ClosestPeersResponse,
10
- LeaveNotice,
20
+ ClosestRingPeersRequest,
21
+ ClosestRingPeersResponse,
11
22
  ConnectivityResponse,
23
+ DataEntry,
24
+ ExternalFetchDataRequest,
25
+ ExternalFetchDataResponse,
26
+ ExternalStoreDataRequest,
27
+ ExternalStoreDataResponse,
28
+ LeaveNotice,
12
29
  Message,
13
- NodeType,
14
30
  PeerDescriptor,
15
31
  PingRequest,
16
32
  PingResponse,
17
- DataEntry,
18
- ExternalFindDataRequest,
19
- ExternalFindDataResponse,
20
- ExternalStoreDataRequest,
21
- ExternalStoreDataResponse,
33
+ RecursiveOperation
22
34
  } from '../proto/packages/dht/protos/DhtRpc'
35
+ import { ExternalApiRpcClient, StoreRpcClient } from '../proto/packages/dht/protos/DhtRpc.client'
23
36
  import { ITransport, TransportEvents } from '../transport/ITransport'
24
- import { ConnectionManager, PortRange, TlsCertificate } from '../connection/ConnectionManager'
25
- import { DhtNodeRpcClient, ExternalApiRpcClient } from '../proto/packages/dht/protos/DhtRpc.client'
26
- import {
27
- Logger,
28
- MetricsContext,
29
- hexToBinary,
30
- merge,
31
- waitForCondition
32
- } from '@streamr/utils'
33
- import { toProtoRpcClient } from '@streamr/proto-rpc'
34
- import { RandomContactList } from './contact/RandomContactList'
35
- import { Any } from '../proto/google/protobuf/any'
36
- import {
37
- areEqualPeerDescriptors,
38
- getNodeIdFromPeerDescriptor,
39
- keyFromPeerDescriptor,
40
- peerIdFromPeerDescriptor
41
- } from '../helpers/peerIdFromPeerDescriptor'
42
- import { Router } from './routing/Router'
43
- import { Finder, FindResult } from './find/Finder'
44
- import { StoreRpcLocal } from './store/StoreRpcLocal'
45
- import { PeerDiscovery } from './discovery/PeerDiscovery'
46
- import { LocalDataStore } from './store/LocalDataStore'
47
- import { IceServer } from '../connection/webrtc/WebrtcConnector'
48
- import { ExternalApiRpcRemote } from './ExternalApiRpcRemote'
49
- import { UUID } from '../helpers/UUID'
50
- import { isBrowserEnvironment } from '../helpers/browser/isBrowserEnvironment'
51
- import { sample } from 'lodash'
52
- import { DefaultConnectorFacade, DefaultConnectorFacadeConfig } from '../connection/ConnectorFacade'
53
- import { MarkRequired } from 'ts-essentials'
37
+ import { RoutingRpcCommunicator } from '../transport/RoutingRpcCommunicator'
38
+ import { ServiceID } from '../types/ServiceID'
54
39
  import { DhtNodeRpcLocal } from './DhtNodeRpcLocal'
55
- import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
40
+ import { DhtNodeRpcRemote } from './DhtNodeRpcRemote'
56
41
  import { ExternalApiRpcLocal } from './ExternalApiRpcLocal'
42
+ import { ExternalApiRpcRemote } from './ExternalApiRpcRemote'
43
+ import { PeerManager } from './PeerManager'
44
+ import { PeerDiscovery } from './discovery/PeerDiscovery'
45
+ import { RecursiveOperationManager } from './recursive-operation/RecursiveOperationManager'
46
+ import { Router } from './routing/Router'
47
+ import { LocalDataStore } from './store/LocalDataStore'
48
+ import { StoreManager } from './store/StoreManager'
49
+ import { StoreRpcRemote } from './store/StoreRpcRemote'
50
+ import { createPeerDescriptor } from '../helpers/createPeerDescriptor'
51
+ import { RingIdRaw } from './contact/ringIdentifiers'
52
+ import { getLocalRegion } from '@streamr/cdn-location'
53
+ import { RingContacts } from './contact/RingContactList'
57
54
 
58
55
  export interface DhtNodeEvents {
59
- newContact: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
56
+ contactAdded: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
60
57
  contactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
61
- joinCompleted: () => void
62
- newRandomContact: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
58
+ randomContactAdded: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
63
59
  randomContactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
60
+ ringContactAdded: (peerDescriptor: PeerDescriptor, closestPeers: RingContacts) => void
61
+ ringContactRemoved: (peerDescriptor: PeerDescriptor, closestPeers: RingContacts) => void
64
62
  }
65
63
 
66
64
  export interface DhtNodeOptions {
67
- serviceId?: string
65
+ serviceId?: ServiceID
68
66
  joinParallelism?: number
69
67
  maxNeighborListSize?: number
70
68
  numberOfNodesPerKBucket?: number
@@ -76,6 +74,7 @@ export interface DhtNodeOptions {
76
74
  storeMaxTtl?: number
77
75
  networkConnectivityTimeout?: number
78
76
  storageRedundancyFactor?: number
77
+ region?: number
79
78
 
80
79
  transport?: ITransport
81
80
  peerDescriptor?: PeerDescriptor
@@ -83,7 +82,7 @@ export interface DhtNodeOptions {
83
82
  websocketHost?: string
84
83
  websocketPortRange?: PortRange
85
84
  websocketServerEnableTls?: boolean
86
- peerId?: string
85
+ nodeId?: DhtAddress
87
86
 
88
87
  rpcRequestTimeout?: number
89
88
  iceServers?: IceServer[]
@@ -100,7 +99,7 @@ export interface DhtNodeOptions {
100
99
  autoCertifierConfigFile?: string
101
100
  }
102
101
 
103
- type StrictDhtNodeOptions = MarkRequired<DhtNodeOptions,
102
+ type StrictDhtNodeOptions = MarkRequired<DhtNodeOptions,
104
103
  'serviceId' |
105
104
  'joinParallelism' |
106
105
  'maxNeighborListSize' |
@@ -113,49 +112,28 @@ type StrictDhtNodeOptions = MarkRequired<DhtNodeOptions,
113
112
  'storeMaxTtl' |
114
113
  'networkConnectivityTimeout' |
115
114
  'storageRedundancyFactor' |
116
- 'metricsContext' |
117
- 'peerId'>
115
+ 'metricsContext'>
118
116
 
119
117
  const logger = new Logger(module)
120
118
 
121
119
  export type Events = TransportEvents & DhtNodeEvents
122
120
 
123
- export const createPeerDescriptor = (msg?: ConnectivityResponse, peerId?: string): PeerDescriptor => {
124
- let kademliaId: Uint8Array
125
- if (msg) {
126
- kademliaId = peerId ? hexToBinary(peerId) : PeerID.fromIp(msg.host).value
127
- } else {
128
- kademliaId = hexToBinary(peerId!)
129
- }
130
- const nodeType = isBrowserEnvironment() ? NodeType.BROWSER : NodeType.NODEJS
131
- const ret: PeerDescriptor = { kademliaId, type: nodeType }
132
- if (msg && msg.websocket) {
133
- ret.websocket = { host: msg.websocket.host, port: msg.websocket.port, tls: msg.websocket.tls }
134
- }
135
- return ret
136
- }
137
-
138
121
  export class DhtNode extends EventEmitter<Events> implements ITransport {
139
122
 
140
123
  private readonly config: StrictDhtNodeOptions
141
- private bucket?: KBucket<DhtNodeRpcRemote>
142
- private connections: Map<PeerIDKey, DhtNodeRpcRemote> = new Map()
143
- private neighborList?: SortedContactList<DhtNodeRpcRemote>
144
- private randomPeers?: RandomContactList<DhtNodeRpcRemote>
145
124
  private rpcCommunicator?: RoutingRpcCommunicator
146
125
  private transport?: ITransport
147
126
  private localPeerDescriptor?: PeerDescriptor
148
127
  public router?: Router
149
- private storeRpcLocal?: StoreRpcLocal
150
- private localDataStore = new LocalDataStore()
151
- private finder?: Finder
128
+ private storeManager?: StoreManager
129
+ private localDataStore: LocalDataStore
130
+ private recursiveOperationManager?: RecursiveOperationManager
152
131
  private peerDiscovery?: PeerDiscovery
153
-
132
+ private peerManager?: PeerManager
154
133
  public connectionManager?: ConnectionManager
134
+ private region?: number
155
135
  private started = false
156
- private stopped = false
157
- private entryPointDisconnectTimeout?: NodeJS.Timeout
158
-
136
+ private abortController = new AbortController()
159
137
  constructor(conf: DhtNodeOptions) {
160
138
  super()
161
139
  this.config = merge({
@@ -163,7 +141,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
163
141
  joinParallelism: 3,
164
142
  maxNeighborListSize: 200,
165
143
  numberOfNodesPerKBucket: 8,
166
- joinNoProgressLimit: 4,
144
+ joinNoProgressLimit: 5,
167
145
  dhtJoinTimeout: 60000,
168
146
  peerDiscoveryQueryBatchSize: 5,
169
147
  maxConnections: 80,
@@ -171,14 +149,31 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
171
149
  storeMaxTtl: 60000,
172
150
  networkConnectivityTimeout: 10000,
173
151
  storageRedundancyFactor: 5,
174
- metricsContext: new MetricsContext(),
175
- peerId: new UUID().toHex()
152
+ metricsContext: new MetricsContext()
176
153
  }, conf)
154
+ this.validateConfig()
155
+ this.localDataStore = new LocalDataStore(this.config.storeMaxTtl)
177
156
  this.send = this.send.bind(this)
178
157
  }
179
158
 
159
+ private validateConfig(): void {
160
+ const expectedNodeIdLength = KADEMLIA_ID_LENGTH_IN_BYTES * 2
161
+ if (this.config.nodeId !== undefined) {
162
+ if (!/^[0-9a-fA-F]+$/.test(this.config.nodeId)) {
163
+ throw new Error('Invalid nodeId, the nodeId should be a hex string')
164
+ } else if (this.config.nodeId.length !== expectedNodeIdLength) {
165
+ throw new Error(`Invalid nodeId, the length of the nodeId should be ${expectedNodeIdLength}`)
166
+ }
167
+ }
168
+ if (this.config.peerDescriptor !== undefined) {
169
+ if (this.config.peerDescriptor.nodeId.length !== KADEMLIA_ID_LENGTH_IN_BYTES) {
170
+ throw new Error(`Invalid peerDescriptor, the length of the nodeId should be ${KADEMLIA_ID_LENGTH_IN_BYTES} bytes`)
171
+ }
172
+ }
173
+ }
174
+
180
175
  public async start(): Promise<void> {
181
- if (this.started || this.stopped) {
176
+ if (this.started || this.abortController.signal.aborted) {
182
177
  return
183
178
  }
184
179
  logger.trace(`Starting new Streamr Network DHT Node with serviceId ${this.config.serviceId}`)
@@ -190,6 +185,14 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
190
185
  this.config.peerDescriptor.websocket = undefined
191
186
  }
192
187
  }
188
+ if (this.region !== undefined) {
189
+ this.region = this.config.region
190
+ } else if (this.config.peerDescriptor?.region !== undefined) {
191
+ this.region = this.config.peerDescriptor.region
192
+ } else {
193
+ this.region = await getLocalRegion()
194
+ }
195
+
193
196
  // If transport is given, do not create a ConnectionManager
194
197
  if (this.config.transport) {
195
198
  this.transport = this.config.transport
@@ -218,12 +221,12 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
218
221
  // If own PeerDescriptor is given in config, create a ConnectionManager with ws server
219
222
  if (this.config.peerDescriptor?.websocket) {
220
223
  connectorFacadeConfig.websocketHost = this.config.peerDescriptor.websocket.host
221
- connectorFacadeConfig.websocketPortRange = {
224
+ connectorFacadeConfig.websocketPortRange = {
222
225
  min: this.config.peerDescriptor.websocket.port,
223
226
  max: this.config.peerDescriptor.websocket.port
224
227
  }
225
- // If websocketPortRange is given, create ws server using it, websocketHost can be undefined
226
- } else if (this.config.websocketPortRange) {
228
+ // If websocketPortRange is given, create ws server using it, websocketHost can be undefined
229
+ } else if (this.config.websocketPortRange) {
227
230
  connectorFacadeConfig.websocketHost = this.config.websocketHost
228
231
  connectorFacadeConfig.websocketPortRange = this.config.websocketPortRange
229
232
  }
@@ -244,426 +247,296 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
244
247
  { rpcRequestTimeout: this.config.rpcRequestTimeout }
245
248
  )
246
249
 
247
- this.transport.on('message', (message: Message) => this.handleMessage(message))
250
+ this.transport.on('message', (message: Message) => this.handleMessageFromTransport(message))
251
+
252
+ this.initPeerManager()
248
253
 
249
- this.initKBuckets(peerIdFromPeerDescriptor(this.localPeerDescriptor!))
250
254
  this.peerDiscovery = new PeerDiscovery({
251
- rpcCommunicator: this.rpcCommunicator,
252
255
  localPeerDescriptor: this.localPeerDescriptor!,
253
- bucket: this.bucket!,
254
- neighborList: this.neighborList!,
255
256
  joinNoProgressLimit: this.config.joinNoProgressLimit,
256
257
  peerDiscoveryQueryBatchSize: this.config.peerDiscoveryQueryBatchSize,
257
258
  joinTimeout: this.config.dhtJoinTimeout,
258
259
  serviceId: this.config.serviceId,
259
260
  parallelism: this.config.joinParallelism,
260
- addContact: this.addNewContact.bind(this),
261
261
  connectionManager: this.connectionManager,
262
- rpcRequestTimeout: this.config.rpcRequestTimeout
262
+ peerManager: this.peerManager!
263
263
  })
264
264
  this.router = new Router({
265
265
  rpcCommunicator: this.rpcCommunicator,
266
- connections: this.connections,
266
+ connections: this.peerManager!.connections,
267
267
  localPeerDescriptor: this.localPeerDescriptor!,
268
- addContact: this.addNewContact.bind(this),
269
- serviceId: this.config.serviceId,
270
- connectionManager: this.connectionManager
268
+ addContact: (contact: PeerDescriptor, setActive?: boolean) => this.peerManager!.addContact([contact], setActive),
269
+ handleMessage: (message: Message) => this.handleMessageFromRouter(message),
271
270
  })
272
- this.finder = new Finder({
271
+ this.recursiveOperationManager = new RecursiveOperationManager({
273
272
  rpcCommunicator: this.rpcCommunicator,
274
273
  router: this.router,
275
274
  sessionTransport: this,
276
- connections: this.connections,
275
+ connections: this.peerManager!.connections,
277
276
  localPeerDescriptor: this.localPeerDescriptor!,
278
277
  serviceId: this.config.serviceId,
279
- addContact: this.addNewContact.bind(this),
280
- isPeerCloserToIdThanSelf: this.isPeerCloserToIdThanSelf.bind(this),
278
+ addContact: (contact: PeerDescriptor) => this.peerManager!.addContact([contact]),
281
279
  localDataStore: this.localDataStore
282
280
  })
283
- this.storeRpcLocal = new StoreRpcLocal({
281
+ this.storeManager = new StoreManager({
284
282
  rpcCommunicator: this.rpcCommunicator,
285
- finder: this.finder,
283
+ recursiveOperationManager: this.recursiveOperationManager,
286
284
  localPeerDescriptor: this.localPeerDescriptor!,
287
285
  serviceId: this.config.serviceId,
288
286
  highestTtl: this.config.storeHighestTtl,
289
- maxTtl: this.config.storeMaxTtl,
290
287
  redundancyFactor: this.config.storageRedundancyFactor,
291
288
  localDataStore: this.localDataStore,
292
- dhtNodeEmitter: this,
293
- getNodesClosestToIdFromBucket: (id: Uint8Array, n?: number) => {
294
- return this.bucket!.closest(id, n)
289
+ getClosestNeighborsTo: (key: DhtAddress, n?: number) => {
290
+ return this.peerManager!.getClosestNeighborsTo(key, n).map((n) => n.getPeerDescriptor())
295
291
  },
296
- rpcRequestTimeout: this.config.rpcRequestTimeout
292
+ createRpcRemote: (contact: PeerDescriptor) => {
293
+ return new StoreRpcRemote(
294
+ this.localPeerDescriptor!,
295
+ contact,
296
+ this.rpcCommunicator!,
297
+ StoreRpcClient,
298
+ this.config.rpcRequestTimeout
299
+ )
300
+ }
301
+ })
302
+ this.on('contactAdded', (peerDescriptor: PeerDescriptor) => {
303
+ this.storeManager!.onContactAdded(peerDescriptor)
297
304
  })
298
305
  this.bindRpcLocalMethods()
299
- if (this.connectionManager! && this.config.entryPoints && this.config.entryPoints.length > 0
300
- && !areEqualPeerDescriptors(this.config.entryPoints[0], this.localPeerDescriptor!)) {
301
- this.connectToEntryPoint(this.config.entryPoints[0])
302
- }
303
306
  }
304
307
 
305
- private initKBuckets(selfId: PeerID) {
306
- this.bucket = new KBucket<DhtNodeRpcRemote>({
307
- localNodeId: selfId.value,
308
+ private initPeerManager() {
309
+ this.peerManager = new PeerManager({
308
310
  numberOfNodesPerKBucket: this.config.numberOfNodesPerKBucket,
309
- numberOfNodesToPing: this.config.numberOfNodesPerKBucket
311
+ maxContactListSize: this.config.maxNeighborListSize,
312
+ localNodeId: this.getNodeId(),
313
+ localPeerDescriptor: this.localPeerDescriptor!,
314
+ connectionManager: this.connectionManager!,
315
+ peerDiscoveryQueryBatchSize: this.config.peerDiscoveryQueryBatchSize,
316
+ isLayer0: (this.connectionManager !== undefined),
317
+ createDhtNodeRpcRemote: (peerDescriptor: PeerDescriptor) => this.createDhtNodeRpcRemote(peerDescriptor),
318
+ lockId: this.config.serviceId
310
319
  })
311
- this.bucket.on('ping', (oldContacts: DhtNodeRpcRemote[], newContact: DhtNodeRpcRemote) => this.onKBucketPing(oldContacts, newContact))
312
- this.bucket.on('removed', (contact: DhtNodeRpcRemote) => this.onKBucketRemoved(contact))
313
- this.bucket.on('added', (contact: DhtNodeRpcRemote) => this.onKBucketAdded(contact))
314
- this.bucket.on('updated', () => {
315
- // TODO: Update contact info to the connection manager and reconnect
320
+ this.peerManager.on('contactRemoved', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) => {
321
+ this.emit('contactRemoved', peerDescriptor, activeContacts)
316
322
  })
317
- this.neighborList = new SortedContactList(selfId, this.config.maxNeighborListSize)
318
- this.neighborList.on('contactRemoved', (removedContact: DhtNodeRpcRemote, activeContacts: DhtNodeRpcRemote[]) => {
319
- if (this.stopped) {
320
- return
323
+ this.peerManager.on('contactAdded', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) =>
324
+ this.emit('contactAdded', peerDescriptor, activeContacts)
325
+ )
326
+ this.peerManager.on('randomContactRemoved', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) =>
327
+ this.emit('randomContactRemoved', peerDescriptor, activeContacts)
328
+ )
329
+ this.peerManager.on('randomContactAdded', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) =>
330
+ this.emit('randomContactAdded', peerDescriptor, activeContacts)
331
+ )
332
+ this.peerManager.on('ringContactRemoved', (peerDescriptor: PeerDescriptor, activeContacts: RingContacts) => {
333
+ this.emit('ringContactRemoved', peerDescriptor, activeContacts)
334
+ })
335
+ this.peerManager.on('ringContactAdded', (peerDescriptor: PeerDescriptor, activeContacts: RingContacts) => {
336
+ this.emit('ringContactAdded', peerDescriptor, activeContacts)
337
+ })
338
+ this.peerManager.on('kBucketEmpty', () => {
339
+ if (!this.peerDiscovery!.isJoinOngoing()
340
+ && this.config.entryPoints
341
+ && this.config.entryPoints.length > 0
342
+ ) {
343
+ setImmediate(async () => {
344
+ // TODO should we catch possible promise rejection?
345
+ await Promise.all(this.config.entryPoints!.map((entryPoint) =>
346
+ this.peerDiscovery!.rejoinDht(entryPoint)
347
+ ))
348
+ })
321
349
  }
322
- this.emit('contactRemoved', removedContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
323
- this.randomPeers!.addContact(
324
- new DhtNodeRpcRemote(
325
- this.localPeerDescriptor!,
326
- removedContact.getPeerDescriptor(),
327
- toProtoRpcClient(new DhtNodeRpcClient(this.rpcCommunicator!.getRpcClientTransport())),
328
- this.config.serviceId,
329
- this.config.rpcRequestTimeout
330
- )
331
- )
332
350
  })
333
- this.neighborList.on('newContact', (newContact: DhtNodeRpcRemote, activeContacts: DhtNodeRpcRemote[]) =>
334
- this.emit('newContact', newContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
335
- )
336
- this.transport!.on('connected', (peerDescriptor: PeerDescriptor) => this.onTransportConnected(peerDescriptor))
337
-
351
+ this.transport!.on('connected', (peerDescriptor: PeerDescriptor) => {
352
+ this.peerManager!.onContactConnected(peerDescriptor)
353
+ this.router!.onNodeConnected(peerDescriptor)
354
+ this.emit('connected', peerDescriptor)
355
+ })
338
356
  this.transport!.on('disconnected', (peerDescriptor: PeerDescriptor, gracefulLeave: boolean) => {
339
- this.onTransportDisconnected(peerDescriptor, gracefulLeave)
357
+ this.peerManager!.onContactDisconnected(getNodeIdFromPeerDescriptor(peerDescriptor), gracefulLeave)
358
+ this.router!.onNodeDisconnected(peerDescriptor)
359
+ this.emit('disconnected', peerDescriptor, gracefulLeave)
340
360
  })
341
-
342
- this.transport!.getAllConnectionPeerDescriptors().forEach((peer) => {
343
- const rpcRemote = new DhtNodeRpcRemote(
344
- this.localPeerDescriptor!,
345
- peer,
346
- toProtoRpcClient(new DhtNodeRpcClient(this.rpcCommunicator!.getRpcClientTransport())),
347
- this.config.serviceId,
348
- this.config.rpcRequestTimeout
349
- )
350
- if (areEqualPeerDescriptors(peer, this.localPeerDescriptor!)) {
351
- logger.error('own peerdescriptor added to connections in initKBucket')
352
- }
353
- this.connections.set(keyFromPeerDescriptor(peer), rpcRemote)
361
+ this.transport!.getConnections().forEach((peer) => {
362
+ this.peerManager!.onContactConnected(peer)
354
363
  })
355
- this.randomPeers = new RandomContactList(selfId, this.config.maxNeighborListSize)
356
- this.randomPeers.on('contactRemoved', (removedContact: DhtNodeRpcRemote, activeContacts: DhtNodeRpcRemote[]) =>
357
- this.emit('randomContactRemoved', removedContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
358
- )
359
- this.randomPeers.on('newContact', (newContact: DhtNodeRpcRemote, activeContacts: DhtNodeRpcRemote[]) =>
360
- this.emit('newRandomContact', newContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
361
- )
362
- }
363
-
364
- private onTransportConnected(peerDescriptor: PeerDescriptor): void {
365
-
366
- if (areEqualPeerDescriptors(this.localPeerDescriptor!, peerDescriptor)) {
367
- logger.error('onTransportConnected() to self')
368
- }
369
-
370
- const rpcRemote = new DhtNodeRpcRemote(
371
- this.localPeerDescriptor!,
372
- peerDescriptor,
373
- toProtoRpcClient(new DhtNodeRpcClient(this.rpcCommunicator!.getRpcClientTransport())),
374
- this.config.serviceId,
375
- this.config.rpcRequestTimeout
376
- )
377
- if (!this.connections.has(PeerID.fromValue(rpcRemote.id).toKey())) {
378
- this.connections.set(PeerID.fromValue(rpcRemote.id).toKey(), rpcRemote)
379
- logger.trace('connectionschange add ' + this.connections.size)
380
- } else {
381
- logger.trace('new connection not set to connections, there is already a connection with the peer ID')
382
- }
383
- logger.trace('connected: ' + getNodeIdFromPeerDescriptor(peerDescriptor) + ' ' + this.connections.size)
384
- this.emit('connected', peerDescriptor)
385
- }
386
-
387
- private onTransportDisconnected(peerDescriptor: PeerDescriptor, gracefulLeave: boolean): void {
388
- logger.trace('disconnected: ' + getNodeIdFromPeerDescriptor(peerDescriptor))
389
- this.connections.delete(keyFromPeerDescriptor(peerDescriptor))
390
- // only remove from bucket if we are on layer 0
391
- if (this.connectionManager) {
392
- this.bucket!.remove(peerDescriptor.kademliaId)
393
-
394
- if (gracefulLeave === true) {
395
- logger.trace(getNodeIdFromPeerDescriptor(peerDescriptor) + ' ' + 'onTransportDisconnected with gracefulLeave ' + gracefulLeave)
396
- this.removeContact(peerDescriptor)
397
- } else {
398
- logger.trace(getNodeIdFromPeerDescriptor(peerDescriptor) + ' ' + 'onTransportDisconnected with gracefulLeave ' + gracefulLeave)
399
- }
400
- }
401
-
402
- this.emit('disconnected', peerDescriptor, gracefulLeave)
403
364
  }
404
365
 
405
366
  private bindRpcLocalMethods(): void {
406
- if (!this.started || this.stopped) {
367
+ if (!this.started || this.abortController.signal.aborted) {
407
368
  return
408
369
  }
409
370
  const dhtNodeRpcLocal = new DhtNodeRpcLocal({
410
- bucket: this.bucket!,
411
- serviceId: this.config.serviceId,
412
371
  peerDiscoveryQueryBatchSize: this.config.peerDiscoveryQueryBatchSize,
413
- addNewContact: (contact: PeerDescriptor) => this.addNewContact(contact),
414
- removeContact: (contact: PeerDescriptor) => this.removeContact(contact)
372
+ getClosestPeersTo: (nodeId: DhtAddress, limit: number) => {
373
+ return this.peerManager!.getClosestNeighborsTo(nodeId, limit)
374
+ .map((dhtPeer: DhtNodeRpcRemote) => dhtPeer.getPeerDescriptor())
375
+ },
376
+ getClosestRingPeersTo: (ringIdRaw: RingIdRaw, limit: number) => {
377
+ return this.getClosestRingContactsTo(ringIdRaw, limit)
378
+ },
379
+ addContact: (contact: PeerDescriptor) => this.peerManager!.addContact([contact]),
380
+ removeContact: (nodeId: DhtAddress) => this.removeContact(nodeId)
415
381
  })
416
382
  this.rpcCommunicator!.registerRpcMethod(ClosestPeersRequest, ClosestPeersResponse, 'getClosestPeers',
417
383
  (req: ClosestPeersRequest, context) => dhtNodeRpcLocal.getClosestPeers(req, context))
384
+ this.rpcCommunicator!.registerRpcMethod(ClosestRingPeersRequest, ClosestRingPeersResponse, 'getClosestRingPeers',
385
+ (req: ClosestRingPeersRequest, context) => dhtNodeRpcLocal.getClosestRingPeers(req, context))
418
386
  this.rpcCommunicator!.registerRpcMethod(PingRequest, PingResponse, 'ping',
419
387
  (req: PingRequest, context) => dhtNodeRpcLocal.ping(req, context))
420
388
  this.rpcCommunicator!.registerRpcNotification(LeaveNotice, 'leaveNotice',
421
- (req: LeaveNotice, context) => dhtNodeRpcLocal.leaveNotice(req, context))
389
+ (_req: LeaveNotice, context) => dhtNodeRpcLocal.leaveNotice(context))
422
390
  const externalApiRpcLocal = new ExternalApiRpcLocal({
423
- startFind: (idToFind: Uint8Array, fetchData: boolean, excludedPeer: PeerDescriptor) => {
424
- return this.startFind(idToFind, fetchData, excludedPeer)
391
+ executeRecursiveOperation: (key: DhtAddress, operation: RecursiveOperation, excludedPeer: DhtAddress) => {
392
+ return this.recursiveOperationManager!.execute(key, operation, excludedPeer)
425
393
  },
426
- storeDataToDht: (key: Uint8Array, data: Any) => this.storeDataToDht(key, data)
394
+ storeDataToDht: (key: DhtAddress, data: Any, creator?: DhtAddress) => this.storeDataToDht(key, data, creator)
427
395
  })
428
396
  this.rpcCommunicator!.registerRpcMethod(
429
- ExternalFindDataRequest,
430
- ExternalFindDataResponse,
431
- 'externalFindData',
432
- (req: ExternalFindDataRequest, context: ServerCallContext) => externalApiRpcLocal.externalFindData(req, context),
433
- { timeout: 10000 }
397
+ ExternalFetchDataRequest,
398
+ ExternalFetchDataResponse,
399
+ 'externalFetchData',
400
+ (req: ExternalFetchDataRequest, context: ServerCallContext) => externalApiRpcLocal.externalFetchData(req, context),
401
+ { timeout: 10000 } // TODO use config option or named constant?
434
402
  )
435
403
  this.rpcCommunicator!.registerRpcMethod(
436
404
  ExternalStoreDataRequest,
437
405
  ExternalStoreDataResponse,
438
406
  'externalStoreData',
439
- (req: ExternalStoreDataRequest) => externalApiRpcLocal.externalStoreData(req),
440
- { timeout: 10000 }
407
+ (req: ExternalStoreDataRequest, context: ServerCallContext) => externalApiRpcLocal.externalStoreData(req, context),
408
+ { timeout: 10000 } // TODO use config option or named constant?
441
409
  )
442
410
  }
443
411
 
444
- private isPeerCloserToIdThanSelf(peer1: PeerDescriptor, compareToId: PeerID): boolean {
445
- const distance1 = this.bucket!.distance(peer1.kademliaId, compareToId.value)
446
- const distance2 = this.bucket!.distance(this.localPeerDescriptor!.kademliaId, compareToId.value)
447
- return distance1 < distance2
412
+ private handleMessageFromTransport(message: Message): void {
413
+ if (message.serviceId === this.config.serviceId) {
414
+ this.rpcCommunicator?.handleMessageFromPeer(message)
415
+ }
448
416
  }
449
-
450
- private handleMessage(message: Message): void {
417
+
418
+ private handleMessageFromRouter(message: Message): void {
451
419
  if (message.serviceId === this.config.serviceId) {
452
- logger.trace('callig this.handleMessageFromPeer ' + getNodeIdFromPeerDescriptor(message.sourceDescriptor!)
453
- + ' ' + message.serviceId + ' ' + message.messageId)
454
420
  this.rpcCommunicator?.handleMessageFromPeer(message)
421
+ } else if (this.connectionManager?.handleIncomingMessage(message)) {
422
+ // message was handled by connectionManager
455
423
  } else {
456
- logger.trace('emit "message" ' + getNodeIdFromPeerDescriptor(message.sourceDescriptor!)
457
- + ' ' + message.serviceId + ' ' + message.messageId)
458
424
  this.emit('message', message)
459
425
  }
460
426
  }
461
427
 
462
428
  private generatePeerDescriptorCallBack(connectivityResponse: ConnectivityResponse) {
463
- if (this.config.peerDescriptor) {
429
+ if (this.config.peerDescriptor !== undefined) {
464
430
  this.localPeerDescriptor = this.config.peerDescriptor
465
431
  } else {
466
- this.localPeerDescriptor = createPeerDescriptor(connectivityResponse, this.config.peerId)
432
+ this.localPeerDescriptor = createPeerDescriptor(connectivityResponse, this.region!, this.config.nodeId)
467
433
  }
468
434
  return this.localPeerDescriptor
469
435
  }
470
436
 
471
- private onKBucketPing(oldContacts: DhtNodeRpcRemote[], newContact: DhtNodeRpcRemote): void {
472
- if (this.stopped) {
473
- return
474
- }
475
- const sortingList: SortedContactList<DhtNodeRpcRemote> = new SortedContactList(this.getNodeId(), 100)
476
- sortingList.addContacts(oldContacts)
477
- const sortedContacts = sortingList.getAllContacts()
478
- this.connectionManager?.weakUnlockConnection(sortedContacts[sortedContacts.length - 1].getPeerDescriptor())
479
- this.bucket?.remove(sortedContacts[sortedContacts.length - 1].getPeerId().value)
480
- this.bucket!.add(newContact)
481
- }
482
-
483
- private onKBucketRemoved(contact: DhtNodeRpcRemote): void {
484
- if (this.stopped) {
485
- return
486
- }
487
- this.connectionManager?.weakUnlockConnection(contact.getPeerDescriptor())
488
- logger.trace(`Removed contact ${getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())}`)
489
- if (this.bucket!.count() === 0
490
- && !this.peerDiscovery!.isJoinOngoing()
491
- && this.config.entryPoints
492
- && this.config.entryPoints.length > 0
493
- ) {
494
- setImmediate(async () => {
495
- await Promise.all(this.config.entryPoints!.map((entryPoint) =>
496
- this.peerDiscovery!.rejoinDht(entryPoint)
497
- ))
498
- })
499
- }
500
- }
501
-
502
- private onKBucketAdded(contact: DhtNodeRpcRemote): void {
503
- if (this.stopped) {
504
- return
505
- }
506
- if (!contact.getPeerId().equals(this.getNodeId())) {
507
- // Important to lock here, before the ping result is known
508
- this.connectionManager?.weakLockConnection(contact.getPeerDescriptor())
509
- if (this.connections.has(contact.getPeerId().toKey())) {
510
- logger.trace(`Added new contact ${getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())}`)
511
- } else { // open connection by pinging
512
- logger.trace('starting ping ' + getNodeIdFromPeerDescriptor(contact.getPeerDescriptor()))
513
- contact.ping().then((result) => {
514
- if (result) {
515
- logger.trace(`Added new contact ${getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())}`)
516
- } else {
517
- logger.trace('ping failed ' + getNodeIdFromPeerDescriptor(contact.getPeerDescriptor()))
518
- this.connectionManager?.weakUnlockConnection(contact.getPeerDescriptor())
519
- this.removeContact(contact.getPeerDescriptor())
520
- this.addClosestContactToBucket()
521
- }
522
- return
523
- }).catch((_e) => {
524
- this.connectionManager?.weakUnlockConnection(contact.getPeerDescriptor())
525
- this.removeContact(contact.getPeerDescriptor())
526
- this.addClosestContactToBucket()
527
- })
528
- }
529
- }
530
- }
531
-
532
- private addClosestContactToBucket(): void {
533
- if (!this.started || this.stopped) {
534
- return
535
- }
536
- const closest = this.getClosestActiveContactNotInBucket()
537
- if (closest) {
538
- this.addNewContact(closest.getPeerDescriptor())
539
- }
437
+ public getClosestContacts(limit?: number): PeerDescriptor[] {
438
+ return this.peerManager!.getClosestContactsTo(
439
+ this.getNodeId(),
440
+ limit).map((peer) => peer.getPeerDescriptor())
540
441
  }
541
442
 
542
- private getClosestActiveContactNotInBucket(): DhtNodeRpcRemote | undefined {
543
- for (const contactId of this.neighborList!.getContactIds()) {
544
- if (!this.bucket!.get(contactId.value) && this.neighborList!.isActive(contactId)) {
545
- return this.neighborList!.getContact(contactId).contact
546
- }
443
+ public getClosestRingContactsTo(ringIdRaw: RingIdRaw, limit?: number): RingContacts {
444
+ const closest = this.peerManager!.getClosestRingContactsTo(ringIdRaw, limit)
445
+ return {
446
+ left: closest.left.map((dhtPeer: DhtNodeRpcRemote) => dhtPeer.getPeerDescriptor()),
447
+ right: closest.right.map((dhtPeer: DhtNodeRpcRemote) => dhtPeer.getPeerDescriptor())
547
448
  }
548
- return undefined
549
- }
550
-
551
- public getClosestContacts(maxCount?: number): PeerDescriptor[] {
552
- return this.neighborList!.getClosestContacts(maxCount).map((c) => c.getPeerDescriptor())
553
449
  }
554
450
 
555
- public getNodeId(): PeerID {
556
- return peerIdFromPeerDescriptor(this.localPeerDescriptor!)
451
+ public getNodeId(): DhtAddress {
452
+ return getNodeIdFromPeerDescriptor(this.localPeerDescriptor!)
557
453
  }
558
454
 
559
- public getBucketSize(): number {
560
- return this.bucket!.count()
455
+ public getNeighborCount(): number {
456
+ return this.peerManager!.getNeighborCount()
561
457
  }
562
458
 
563
- private addNewContact(contact: PeerDescriptor, setActive = false): void {
564
- if (!this.started || this.stopped) {
459
+ public removeContact(nodeId: DhtAddress): void {
460
+ if (!this.started) { // the stopped state is checked in PeerManager
565
461
  return
566
462
  }
567
- if (!areEqualPeerDescriptors(contact, this.localPeerDescriptor!)) {
568
- logger.trace(`Adding new contact ${getNodeIdFromPeerDescriptor(contact)}`)
569
- const rpcRemote = new DhtNodeRpcRemote(
570
- this.localPeerDescriptor!,
571
- contact,
572
- toProtoRpcClient(new DhtNodeRpcClient(this.rpcCommunicator!.getRpcClientTransport())),
573
- this.config.serviceId,
574
- this.config.rpcRequestTimeout
575
- )
576
- if (!this.bucket!.get(contact.kademliaId) && !this.neighborList!.getContact(peerIdFromPeerDescriptor(contact))) {
577
- this.neighborList!.addContact(rpcRemote)
578
- if (setActive) {
579
- const peerId = peerIdFromPeerDescriptor(contact)
580
- this.neighborList!.setActive(peerId)
581
- }
582
- this.bucket!.add(rpcRemote)
583
- } else {
584
- this.randomPeers!.addContact(rpcRemote)
585
- }
586
- }
587
- }
588
-
589
- private connectToEntryPoint(entryPoint: PeerDescriptor): void {
590
- this.connectionManager!.lockConnection(entryPoint, 'temporary-layer0-connection')
591
- this.entryPointDisconnectTimeout = setTimeout(() => {
592
- this.connectionManager!.unlockConnection(entryPoint, 'temporary-layer0-connection')
593
- }, 10 * 1000)
463
+ this.peerManager!.removeContact(nodeId)
594
464
  }
595
465
 
596
- public removeContact(contact: PeerDescriptor): void {
597
- if (!this.started || this.stopped) {
466
+ public async send(msg: Message): Promise<void> {
467
+ if (!this.started || this.abortController.signal.aborted) {
598
468
  return
599
469
  }
600
- logger.trace(`Removing contact ${getNodeIdFromPeerDescriptor(contact)}`)
601
- const peerId = peerIdFromPeerDescriptor(contact)
602
- this.bucket!.remove(peerId.value)
603
- this.neighborList!.removeContact(peerId)
604
- this.randomPeers!.removeContact(peerId)
470
+ const reachableThrough = this.peerDiscovery!.isJoinOngoing() ? this.getConnectedEntryPoints() : []
471
+ this.router!.send(msg, reachableThrough)
605
472
  }
606
473
 
607
- public async send(msg: Message): Promise<void> {
608
- if (!this.started || this.stopped) {
609
- return
610
- }
611
- const reachableThrough = this.peerDiscovery!.isJoinOngoing() ? this.config.entryPoints ?? [] : []
612
- await this.router!.send(msg, reachableThrough)
474
+ private getConnectedEntryPoints(): PeerDescriptor[] {
475
+ return this.config.entryPoints !== undefined ? this.config.entryPoints.filter((entryPoint) =>
476
+ this.peerManager!.connections.has(getNodeIdFromPeerDescriptor(entryPoint))
477
+ ) : []
613
478
  }
614
479
 
615
- public async joinDht(entryPointDescriptors: PeerDescriptor[], doAdditionalRandomPeerDiscovery?: boolean, retry?: boolean): Promise<void> {
480
+ public async joinDht(entryPointDescriptors: PeerDescriptor[], doAdditionalDistantPeerDiscovery?: boolean, retry?: boolean): Promise<void> {
616
481
  if (!this.started) {
617
482
  throw new Error('Cannot join DHT before calling start() on DhtNode')
618
483
  }
619
- await Promise.all(entryPointDescriptors.map((entryPoint) =>
620
- this.peerDiscovery!.joinDht(entryPoint, doAdditionalRandomPeerDiscovery, retry)
621
- ))
484
+ await this.peerDiscovery!.joinDht(entryPointDescriptors, doAdditionalDistantPeerDiscovery, retry)
622
485
  }
623
486
 
624
- public async startFind(idToFind: Uint8Array, fetchData?: boolean, excludedPeer?: PeerDescriptor): Promise<FindResult> {
625
- return this.finder!.startFind(idToFind, fetchData, excludedPeer)
487
+ public async joinRing(): Promise<void> {
488
+ if (!this.started) {
489
+ throw new Error('Cannot join ring before calling start() on DhtNode')
490
+ }
491
+ await this.peerDiscovery!.joinRing()
626
492
  }
627
493
 
628
- public async storeDataToDht(key: Uint8Array, data: Any): Promise<PeerDescriptor[]> {
629
- if (this.peerDiscovery!.isJoinOngoing() && this.config.entryPoints && this.config.entryPoints.length > 0) {
630
- return this.storeDataViaPeer(key, data, sample(this.config.entryPoints)!)
494
+ public async storeDataToDht(key: DhtAddress, data: Any, creator?: DhtAddress): Promise<PeerDescriptor[]> {
495
+ const connectedEntryPoints = this.getConnectedEntryPoints()
496
+ if (this.peerDiscovery!.isJoinOngoing() && connectedEntryPoints.length > 0) {
497
+ return this.storeDataToDhtViaPeer(key, data, sample(connectedEntryPoints)!)
631
498
  }
632
- return this.storeRpcLocal!.storeDataToDht(key, data)
499
+ return this.storeManager!.storeDataToDht(key, data, creator ?? this.getNodeId())
633
500
  }
634
501
 
635
- public async storeDataViaPeer(key: Uint8Array, data: Any, peer: PeerDescriptor): Promise<PeerDescriptor[]> {
502
+ public async storeDataToDhtViaPeer(key: DhtAddress, data: Any, peer: PeerDescriptor): Promise<PeerDescriptor[]> {
636
503
  const rpcRemote = new ExternalApiRpcRemote(
637
504
  this.localPeerDescriptor!,
638
505
  peer,
639
- this.config.serviceId,
640
- toProtoRpcClient(new ExternalApiRpcClient(this.rpcCommunicator!.getRpcClientTransport()))
506
+ this.rpcCommunicator!,
507
+ ExternalApiRpcClient
641
508
  )
642
509
  return await rpcRemote.storeData(key, data)
643
510
  }
644
511
 
645
- public async getDataFromDht(idToFind: Uint8Array): Promise<DataEntry[]> {
646
- if (this.peerDiscovery!.isJoinOngoing() && this.config.entryPoints && this.config.entryPoints.length > 0) {
647
- return this.findDataViaPeer(idToFind, sample(this.config.entryPoints)!)
512
+ public async fetchDataFromDht(key: DhtAddress): Promise<DataEntry[]> {
513
+ const connectedEntryPoints = this.getConnectedEntryPoints()
514
+ if (this.peerDiscovery!.isJoinOngoing() && connectedEntryPoints.length > 0) {
515
+ return this.fetchDataFromDhtViaPeer(key, sample(connectedEntryPoints)!)
648
516
  }
649
- const result = await this.finder!.startFind(idToFind, true)
650
- return result.dataEntries ?? []
517
+ const result = await this.recursiveOperationManager!.execute(key, RecursiveOperation.FETCH_DATA)
518
+ return result.dataEntries ?? [] // TODO is this fallback needed?
651
519
  }
652
520
 
653
- public async deleteDataFromDht(idToDelete: Uint8Array): Promise<void> {
654
- if (!this.stopped) {
655
- return this.storeRpcLocal!.deleteDataFromDht(idToDelete)
656
- }
657
- }
658
-
659
- public async findDataViaPeer(idToFind: Uint8Array, peer: PeerDescriptor): Promise<DataEntry[]> {
521
+ public async fetchDataFromDhtViaPeer(key: DhtAddress, peer: PeerDescriptor): Promise<DataEntry[]> {
660
522
  const rpcRemote = new ExternalApiRpcRemote(
661
523
  this.localPeerDescriptor!,
662
524
  peer,
663
- this.config.serviceId,
664
- toProtoRpcClient(new ExternalApiRpcClient(this.rpcCommunicator!.getRpcClientTransport()))
525
+ this.rpcCommunicator!,
526
+ ExternalApiRpcClient
665
527
  )
666
- return await rpcRemote.externalFindData(idToFind)
528
+ return await rpcRemote.externalFetchData(key)
529
+ }
530
+
531
+ public async deleteDataFromDht(key: DhtAddress, waitForCompletion: boolean): Promise<void> {
532
+ if (!this.abortController.signal.aborted) {
533
+ await this.recursiveOperationManager!.execute(key, RecursiveOperation.DELETE_DATA, undefined, waitForCompletion)
534
+ }
535
+ }
536
+
537
+ async findClosestNodesFromDht(key: DhtAddress): Promise<PeerDescriptor[]> {
538
+ const result = await this.recursiveOperationManager!.execute(key, RecursiveOperation.FIND_CLOSEST_NODES)
539
+ return result.closestNodes
667
540
  }
668
541
 
669
542
  public getTransport(): ITransport {
@@ -674,32 +547,38 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
674
547
  return this.localPeerDescriptor!
675
548
  }
676
549
 
677
- public getAllConnectionPeerDescriptors(): PeerDescriptor[] {
678
- return Array.from(this.connections.values()).map((peer) => peer.getPeerDescriptor())
550
+ public getConnections(): PeerDescriptor[] {
551
+ return Array.from(this.peerManager!.connections.values()).map((peer) => peer.getPeerDescriptor())
679
552
  }
680
553
 
681
- public getKBucketPeers(): PeerDescriptor[] {
682
- return this.bucket!.toArray().map((rpcRemote: DhtNodeRpcRemote) => rpcRemote.getPeerDescriptor())
554
+ public getNeighbors(): PeerDescriptor[] {
555
+ return this.started ? this.peerManager!.getNeighbors() : []
683
556
  }
684
557
 
685
- public getNumberOfConnections(): number {
686
- return this.connections.size
558
+ public getConnectionCount(): number {
559
+ return this.peerManager!.getConnectionCount()
687
560
  }
688
561
 
689
- public getNumberOfLocalLockedConnections(): number {
690
- return this.connectionManager!.getNumberOfLocalLockedConnections()
562
+ public getLocalLockedConnectionCount(): number {
563
+ return this.connectionManager!.getLocalLockedConnectionCount()
691
564
  }
692
565
 
693
- public getNumberOfRemoteLockedConnections(): number {
694
- return this.connectionManager!.getNumberOfRemoteLockedConnections()
566
+ public getRemoteLockedConnectionCount(): number {
567
+ return this.connectionManager!.getRemoteLockedConnectionCount()
695
568
  }
696
569
 
697
- public getNumberOfWeakLockedConnections(): number {
698
- return this.connectionManager!.getNumberOfWeakLockedConnections()
570
+ public getWeakLockedConnectionCount(): number {
571
+ return this.connectionManager!.getWeakLockedConnectionCount()
699
572
  }
700
573
 
701
574
  public async waitForNetworkConnectivity(): Promise<void> {
702
- await waitForCondition(() => this.connections.size > 0, this.config.networkConnectivityTimeout)
575
+ await waitForCondition(() => {
576
+ if (!this.peerManager) {
577
+ return false
578
+ } else {
579
+ return (this.peerManager.getConnectionCount() > 0)
580
+ }
581
+ }, this.config.networkConnectivityTimeout, 100, this.abortController.signal)
703
582
  }
704
583
 
705
584
  public hasJoined(): boolean {
@@ -707,35 +586,35 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
707
586
  }
708
587
 
709
588
  public async stop(): Promise<void> {
710
- if (this.stopped || !this.started) {
589
+ if (this.abortController.signal.aborted || !this.started) {
711
590
  return
712
591
  }
713
592
  logger.trace('stop()')
714
- this.stopped = true
715
-
716
- if (this.entryPointDisconnectTimeout) {
717
- clearTimeout(this.entryPointDisconnectTimeout)
718
- }
719
- this.bucket!.toArray().forEach((rpcRemote: DhtNodeRpcRemote) => {
720
- rpcRemote.leaveNotice()
721
- this.bucket!.remove(rpcRemote.id)
722
- })
723
- this.bucket!.removeAllListeners()
593
+ this.abortController.abort()
594
+ await this.storeManager!.destroy()
724
595
  this.localDataStore.clear()
725
- this.neighborList!.stop()
726
- this.randomPeers!.stop()
596
+ this.peerManager?.stop()
727
597
  this.rpcCommunicator!.stop()
728
598
  this.router!.stop()
729
- this.finder!.stop()
599
+ this.recursiveOperationManager!.stop()
730
600
  this.peerDiscovery!.stop()
731
601
  if (this.config.transport === undefined) {
732
- // if the transport was not given in config, the instance was created in start() and
602
+ // if the transport was not given in config, the instance was created in start() and
733
603
  // this component is responsible for stopping it
734
604
  await this.transport!.stop()
735
605
  }
736
606
  this.transport = undefined
737
607
  this.connectionManager = undefined
738
- this.connections.clear()
739
608
  this.removeAllListeners()
740
609
  }
610
+
611
+ private createDhtNodeRpcRemote(peerDescriptor: PeerDescriptor) {
612
+ return new DhtNodeRpcRemote(
613
+ this.localPeerDescriptor!,
614
+ peerDescriptor,
615
+ this.config.serviceId,
616
+ this.rpcCommunicator!,
617
+ this.config.rpcRequestTimeout
618
+ )
619
+ }
741
620
  }