@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,321 @@
1
+ import {
2
+ DataEntry, DeleteDataRequest, DeleteDataResponse, MigrateDataRequest, MigrateDataResponse, PeerDescriptor,
3
+ StoreDataRequest, StoreDataResponse
4
+ } from '../../proto/packages/dht/protos/DhtRpc'
5
+ import { PeerID } from '../../helpers/PeerID'
6
+ import { Any } from '../../proto/google/protobuf/any'
7
+ import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
8
+ import { DhtCallContext } from '../../rpc-protocol/DhtCallContext'
9
+ import { toProtoRpcClient } from '@streamr/proto-rpc'
10
+ import { StoreServiceClient } from '../../proto/packages/dht/protos/DhtRpc.client'
11
+ import { RoutingRpcCommunicator } from '../../transport/RoutingRpcCommunicator'
12
+ import { IRecursiveFinder } from '../find/RecursiveFinder'
13
+ import { isSamePeerDescriptor, peerIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
14
+ import { Logger } from '@streamr/utils'
15
+ import { LocalDataStore } from './LocalDataStore'
16
+ import { IStoreService } from '../../proto/packages/dht/protos/DhtRpc.server'
17
+ import { RemoteStore } from './RemoteStore'
18
+ import { Timestamp } from '../../proto/google/protobuf/timestamp'
19
+ import EventEmitter from 'eventemitter3'
20
+ import { Events } from '../DhtNode'
21
+ import { SortedContactList } from '../contact/SortedContactList'
22
+ import { Contact } from '../contact/Contact'
23
+ import { DhtPeer } from '../DhtPeer'
24
+
25
+ interface DataStoreConfig {
26
+ rpcCommunicator: RoutingRpcCommunicator
27
+ recursiveFinder: IRecursiveFinder
28
+ ownPeerDescriptor: PeerDescriptor
29
+ localDataStore: LocalDataStore
30
+ serviceId: string
31
+ storeMaxTtl: number
32
+ storeHighestTtl: number
33
+ storeNumberOfCopies: number
34
+ dhtNodeEmitter: EventEmitter<Events>
35
+ getNodesClosestToIdFromBucket: (id: Uint8Array, n?: number) => DhtPeer[]
36
+ }
37
+
38
+ const logger = new Logger(module)
39
+
40
+ export class DataStore implements IStoreService {
41
+
42
+ private readonly rpcCommunicator: RoutingRpcCommunicator
43
+ private readonly recursiveFinder: IRecursiveFinder
44
+ private readonly ownPeerDescriptor: PeerDescriptor
45
+ private readonly localDataStore: LocalDataStore
46
+ private readonly serviceId: string
47
+ private readonly storeMaxTtl: number
48
+ private readonly storeHighestTtl: number
49
+ private readonly storeNumberOfCopies: number
50
+ private readonly dhtNodeEmitter: EventEmitter<Events>
51
+ private readonly getNodesClosestToIdFromBucket: (id: Uint8Array, n?: number) => DhtPeer[]
52
+
53
+ constructor(config: DataStoreConfig) {
54
+ this.rpcCommunicator = config.rpcCommunicator
55
+ this.recursiveFinder = config.recursiveFinder
56
+ this.ownPeerDescriptor = config.ownPeerDescriptor
57
+ this.localDataStore = config.localDataStore
58
+ this.serviceId = config.serviceId
59
+ this.storeMaxTtl = config.storeMaxTtl
60
+ this.storeHighestTtl = config.storeHighestTtl
61
+ this.storeNumberOfCopies = config.storeNumberOfCopies
62
+ this.dhtNodeEmitter = config.dhtNodeEmitter
63
+ this.getNodesClosestToIdFromBucket = config.getNodesClosestToIdFromBucket
64
+ this.rpcCommunicator!.registerRpcMethod(StoreDataRequest, StoreDataResponse, 'storeData',
65
+ (request: StoreDataRequest, context: ServerCallContext) => this.storeData(request, context))
66
+ this.rpcCommunicator!.registerRpcMethod(MigrateDataRequest, MigrateDataResponse, 'migrateData',
67
+ (request: MigrateDataRequest, context: ServerCallContext) => this.migrateData(request, context))
68
+ this.rpcCommunicator!.registerRpcMethod(DeleteDataRequest, DeleteDataResponse, 'deleteData',
69
+ (request: DeleteDataRequest, context: ServerCallContext) => this.deleteData(request, context))
70
+
71
+ this.dhtNodeEmitter.on('newContact', (peerDescriptor: PeerDescriptor, _closestPeers: PeerDescriptor[]) => {
72
+ this.localDataStore.getStore().forEach((dataMap, _dataKey) => {
73
+ dataMap.forEach((dataEntry) => {
74
+ if (this.shouldMigrateDataToNewNode(dataEntry.dataEntry, peerDescriptor)) {
75
+ this.migrateDataToContact(dataEntry.dataEntry, peerDescriptor)
76
+ }
77
+ })
78
+ })
79
+ })
80
+ }
81
+
82
+ private shouldMigrateDataToNewNode(dataEntry: DataEntry, newNode: PeerDescriptor): boolean {
83
+
84
+ const dataId = PeerID.fromValue(dataEntry.kademliaId)
85
+ const newNodeId = PeerID.fromValue(newNode.kademliaId)
86
+ const ownPeerId = PeerID.fromValue(this.ownPeerDescriptor.kademliaId)
87
+
88
+ const closestToData = this.getNodesClosestToIdFromBucket(dataEntry.kademliaId, 10)
89
+
90
+ const sortedList = new SortedContactList<Contact>(dataId, 20, undefined, true)
91
+ sortedList.addContact(new Contact(this.ownPeerDescriptor!))
92
+
93
+ closestToData.forEach((con) => {
94
+ if (!newNodeId.equals(PeerID.fromValue(con.getPeerDescriptor().kademliaId))) {
95
+ sortedList.addContact(new Contact(con.getPeerDescriptor()))
96
+ }
97
+ })
98
+
99
+ if (!sortedList.getAllContacts()[0].getPeerId().equals(ownPeerId!)) {
100
+ // If we are not the closes node to the data, do not migrate
101
+ return false
102
+ }
103
+
104
+ const newPeerId = PeerID.fromValue(newNode.kademliaId)
105
+ sortedList.addContact(new Contact(newNode))
106
+
107
+ const sorted = sortedList.getAllContacts()
108
+
109
+ let index = 0
110
+
111
+ for (index = 0; index < sorted.length; index++) {
112
+ if (sorted[index].getPeerId().equals(newPeerId)) {
113
+ break
114
+ }
115
+ }
116
+
117
+ // if new node is within the 5 closest nodes to the data
118
+ // do migrate data to it
119
+
120
+ if (index < 5) {
121
+ this.localDataStore.setStale(dataId, dataEntry.storer!, false)
122
+ return true
123
+ } else {
124
+ this.localDataStore.setStale(dataId, dataEntry.storer!, true)
125
+ return false
126
+ }
127
+ }
128
+
129
+ private async migrateDataToContact(dataEntry: DataEntry, contact: PeerDescriptor, doNotConnect: boolean = false): Promise<void> {
130
+ const remoteStore = new RemoteStore(
131
+ this.ownPeerDescriptor,
132
+ contact,
133
+ toProtoRpcClient(new StoreServiceClient(this.rpcCommunicator.getRpcClientTransport())),
134
+ this.serviceId
135
+ )
136
+ try {
137
+ const response = await remoteStore.migrateData({ dataEntry }, doNotConnect)
138
+ if (response.error) {
139
+ logger.debug('RemoteStore::migrateData() returned error: ' + response.error)
140
+ }
141
+ } catch (e) {
142
+ logger.debug('RemoteStore::migrateData() threw an exception ' + e)
143
+ }
144
+ }
145
+
146
+ public async storeDataToDht(key: Uint8Array, data: Any): Promise<PeerDescriptor[]> {
147
+ logger.debug(`Storing data to DHT ${this.serviceId}`)
148
+ const result = await this.recursiveFinder!.startRecursiveFind(key)
149
+ const closestNodes = result.closestNodes
150
+ const successfulNodes: PeerDescriptor[] = []
151
+ const ttl = this.storeHighestTtl // ToDo: make TTL decrease according to some nice curve
152
+ const storerTime = Timestamp.now()
153
+ for (let i = 0; i < closestNodes.length && successfulNodes.length < 5; i++) {
154
+ if (isSamePeerDescriptor(this.ownPeerDescriptor, closestNodes[i])) {
155
+ this.localDataStore.storeEntry({
156
+ kademliaId: key,
157
+ storer: this.ownPeerDescriptor,
158
+ ttl,
159
+ storedAt: Timestamp.now(),
160
+ data,
161
+ stale: false,
162
+ deleted: false,
163
+ storerTime
164
+ })
165
+ successfulNodes.push(closestNodes[i])
166
+ continue
167
+ }
168
+ const remoteStore = new RemoteStore(
169
+ this.ownPeerDescriptor,
170
+ closestNodes[i],
171
+ toProtoRpcClient(new StoreServiceClient(this.rpcCommunicator.getRpcClientTransport())),
172
+ this.serviceId
173
+ )
174
+ try {
175
+ const response = await remoteStore.storeData({ kademliaId: key, data, ttl, storerTime })
176
+ if (!response.error) {
177
+ successfulNodes.push(closestNodes[i])
178
+ logger.trace('remoteStore.storeData() returned success')
179
+ } else {
180
+ logger.debug('remoteStore.storeData() returned error: ' + response.error)
181
+ }
182
+ } catch (e) {
183
+ logger.debug('remoteStore.storeData() threw an exception ' + e)
184
+ }
185
+ }
186
+ return successfulNodes
187
+ }
188
+
189
+ private selfIsOneOfClosestPeers(dataId: Uint8Array): boolean {
190
+ const ownPeerId = PeerID.fromValue(this.ownPeerDescriptor.kademliaId)
191
+ const closestPeers = this.getNodesClosestToIdFromBucket(dataId, 5)
192
+ const sortedList = new SortedContactList<Contact>(ownPeerId, 5, undefined, true)
193
+ sortedList.addContact(new Contact(this.ownPeerDescriptor))
194
+ closestPeers.forEach((con) => sortedList.addContact(new Contact(con.getPeerDescriptor())))
195
+ return sortedList.getClosestContacts().some((node) => node.getPeerId().equals(ownPeerId))
196
+ }
197
+
198
+ public async deleteDataFromDht(key: Uint8Array): Promise<void> {
199
+ logger.debug(`Deleting data from DHT ${this.serviceId}`)
200
+ const result = await this.recursiveFinder!.startRecursiveFind(key)
201
+ const closestNodes = result.closestNodes
202
+ const successfulNodes: PeerDescriptor[] = []
203
+ for (let i = 0; i < closestNodes.length && successfulNodes.length < 5; i++) {
204
+ if (isSamePeerDescriptor(this.ownPeerDescriptor, closestNodes[i])) {
205
+ this.localDataStore.markAsDeleted(key, peerIdFromPeerDescriptor(this.ownPeerDescriptor))
206
+ successfulNodes.push(closestNodes[i])
207
+ continue
208
+ }
209
+ const remoteStore = new RemoteStore(
210
+ this.ownPeerDescriptor,
211
+ closestNodes[i],
212
+ toProtoRpcClient(new StoreServiceClient(this.rpcCommunicator.getRpcClientTransport())),
213
+ this.serviceId
214
+ )
215
+ try {
216
+ const response = await remoteStore.deleteData({ kademliaId: key })
217
+ if (response.deleted) {
218
+ logger.trace('remoteStore.deleteData() returned success')
219
+ } else {
220
+ logger.debug('could not delete data from ' + PeerID.fromValue(closestNodes[i].kademliaId))
221
+ }
222
+ successfulNodes.push(closestNodes[i])
223
+ } catch (e) {
224
+ logger.debug('remoteStore.deleteData() threw an exception ' + e)
225
+ }
226
+ }
227
+ }
228
+
229
+ // RPC service implementation
230
+ async storeData(request: StoreDataRequest, context: ServerCallContext): Promise<StoreDataResponse> {
231
+ const ttl = Math.min(request.ttl, this.storeMaxTtl)
232
+ const { incomingSourceDescriptor } = context as DhtCallContext
233
+ const { kademliaId, data, storerTime } = request
234
+ this.localDataStore.storeEntry({
235
+ kademliaId: kademliaId,
236
+ storer: incomingSourceDescriptor!,
237
+ ttl,
238
+ storedAt: Timestamp.now(),
239
+ storerTime,
240
+ data,
241
+ stale: !this.selfIsOneOfClosestPeers(kademliaId),
242
+ deleted: false
243
+ })
244
+
245
+ if (!this.selfIsOneOfClosestPeers(kademliaId)) {
246
+ this.localDataStore.setAllEntriesAsStale(PeerID.fromValue(kademliaId))
247
+ }
248
+
249
+ logger.trace(this.ownPeerDescriptor.nodeName + ' storeData()')
250
+ return StoreDataResponse.create()
251
+ }
252
+
253
+ // RPC service implementation
254
+ async deleteData(request: DeleteDataRequest, context: ServerCallContext): Promise<DeleteDataResponse> {
255
+ const { incomingSourceDescriptor } = context as DhtCallContext
256
+ const { kademliaId } = request
257
+ const deleted = this.localDataStore.markAsDeleted(kademliaId, peerIdFromPeerDescriptor(incomingSourceDescriptor!))
258
+ return DeleteDataResponse.create({ deleted })
259
+ }
260
+
261
+ // RPC service implementation
262
+ public async migrateData(request: MigrateDataRequest, context: ServerCallContext): Promise<MigrateDataResponse> {
263
+ logger.trace(this.ownPeerDescriptor.nodeName + ' server-side migrateData()')
264
+ const dataEntry = request.dataEntry!
265
+
266
+ const wasStored = this.localDataStore.storeEntry(dataEntry)
267
+
268
+ if (wasStored) {
269
+ this.migrateDataToNeighborsIfNeeded((context as DhtCallContext).incomingSourceDescriptor!, request.dataEntry!)
270
+ }
271
+ if (!this.selfIsOneOfClosestPeers(dataEntry.kademliaId)) {
272
+ this.localDataStore.setAllEntriesAsStale(PeerID.fromValue(dataEntry.kademliaId))
273
+ }
274
+ logger.trace(this.ownPeerDescriptor.nodeName + ' server-side migrateData() at end')
275
+ return MigrateDataResponse.create()
276
+ }
277
+
278
+ private migrateDataToNeighborsIfNeeded(incomingPeer: PeerDescriptor, dataEntry: DataEntry): void {
279
+
280
+ // sort own contact list according to data id
281
+ const ownPeerId = PeerID.fromValue(this.ownPeerDescriptor!.kademliaId)
282
+ const dataId = PeerID.fromValue(dataEntry.kademliaId)
283
+ const incomingPeerId = PeerID.fromValue(incomingPeer.kademliaId)
284
+ const closestToData = this.getNodesClosestToIdFromBucket(dataEntry.kademliaId, 10)
285
+
286
+ const sortedList = new SortedContactList<Contact>(dataId, 5, undefined, true)
287
+ sortedList.addContact(new Contact(this.ownPeerDescriptor!))
288
+
289
+ closestToData.forEach((con) => {
290
+ sortedList.addContact(new Contact(con.getPeerDescriptor()))
291
+ })
292
+
293
+ if (!sortedList.getAllContacts()[0].getPeerId().equals(ownPeerId)) {
294
+ // If we are not the closest node to the data, migrate only to the
295
+ // closest one to the data
296
+
297
+ const contact = sortedList.getAllContacts()[0]
298
+ const contactPeerId = PeerID.fromValue(contact.getPeerDescriptor().kademliaId)
299
+ if (!incomingPeerId.equals(contactPeerId) && !ownPeerId.equals(contactPeerId)) {
300
+ this.migrateDataToContact(dataEntry, contact.getPeerDescriptor()).then(() => {
301
+ logger.trace('migrateDataToContact() returned when migrating to only the closest contact')
302
+ }).catch((e) => {
303
+ logger.error('migrating data to only the closest contact failed ' + e)
304
+ })
305
+ }
306
+ } else {
307
+ // if we are the closest to the data, migrate to all 5 nearest
308
+
309
+ sortedList.getAllContacts().forEach((contact) => {
310
+ const contactPeerId = PeerID.fromValue(contact.getPeerDescriptor().kademliaId)
311
+ if (!incomingPeerId.equals(contactPeerId) && !ownPeerId.equals(contactPeerId)) {
312
+ this.migrateDataToContact(dataEntry, contact.getPeerDescriptor()).then(() => {
313
+ logger.trace('migrateDataToContact() returned')
314
+ }).catch((e) => {
315
+ logger.error('migrating data to one of the closest contacts failed ' + e)
316
+ })
317
+ }
318
+ })
319
+ }
320
+ }
321
+ }
@@ -0,0 +1,114 @@
1
+ import { PeerID, PeerIDKey } from '../../helpers/PeerID'
2
+ import { DataEntry, PeerDescriptor } from '../../proto/packages/dht/protos/DhtRpc'
3
+ import { keyFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
4
+
5
+ const MIN_TTL = 1 * 1000
6
+ const MAX_TTL = 300 * 1000
7
+
8
+ const createTtlValue = (ttl: number): number => {
9
+ if (ttl < MIN_TTL) {
10
+ return MIN_TTL
11
+ } else if (ttl > MAX_TTL) {
12
+ return MAX_TTL
13
+ } else {
14
+ return ttl
15
+ }
16
+ }
17
+
18
+ interface LocalDataEntry {
19
+ dataEntry: DataEntry
20
+ ttlTimeout: NodeJS.Timeout
21
+ }
22
+
23
+ export class LocalDataStore {
24
+ // A map into which each node can store one value per data key
25
+ // The first key is the key of the data, the second key is the
26
+ // PeerID of the storer of the data
27
+ private store: Map<PeerIDKey, Map<PeerIDKey, LocalDataEntry>> = new Map()
28
+
29
+ public storeEntry(dataEntry: DataEntry): boolean {
30
+ const publisherKey = PeerID.fromValue(dataEntry.storer!.kademliaId!).toKey()
31
+ const dataKey = PeerID.fromValue(dataEntry.kademliaId).toKey()
32
+
33
+ if (!this.store.has(dataKey)) {
34
+ this.store.set(dataKey, new Map())
35
+ }
36
+
37
+ if (this.store.get(dataKey)!.has(publisherKey)) {
38
+ const storedMillis = (dataEntry.storerTime!.seconds * 1000) + (dataEntry.storerTime!.nanos / 1000000)
39
+ const oldLocalEntry = this.store.get(dataKey)!.get(publisherKey)!
40
+ const oldStoredMillis = (oldLocalEntry.dataEntry.storerTime!.seconds * 1000) + (oldLocalEntry.dataEntry.storerTime!.nanos / 1000000)
41
+
42
+ // do nothing if old entry is newer than the one being migrated
43
+ if (oldStoredMillis >= storedMillis) {
44
+ return false
45
+ } else {
46
+ clearTimeout(oldLocalEntry.ttlTimeout)
47
+ }
48
+ }
49
+ this.store.get(dataKey)!.set(publisherKey, {
50
+ dataEntry,
51
+ ttlTimeout: setTimeout(() => {
52
+ this.deleteEntry(PeerID.fromValue(dataEntry.kademliaId), dataEntry.storer!)
53
+ }, createTtlValue(dataEntry.ttl))
54
+ })
55
+ return true
56
+ }
57
+
58
+ public markAsDeleted(id: Uint8Array, storer: PeerID): boolean {
59
+ const dataKey = PeerID.fromValue(id).toKey()
60
+ if (!this.store.get(dataKey)?.has(storer.toKey())) {
61
+ return false
62
+ }
63
+ const storedEntry = this.store.get(dataKey)!.get(storer.toKey())
64
+ storedEntry!.dataEntry.deleted = true
65
+ return true
66
+ }
67
+
68
+ public getStore(): Map<PeerIDKey, Map<PeerIDKey, LocalDataEntry>> {
69
+ return this.store
70
+ }
71
+
72
+ public getEntry(key: PeerID): Map<PeerIDKey, DataEntry> {
73
+ const dataEntries = new Map<PeerIDKey, DataEntry>
74
+ this.store.get(key.toKey())?.forEach((value, key) => {
75
+ dataEntries.set(key, value.dataEntry)
76
+ })
77
+ return dataEntries
78
+ }
79
+
80
+ public setStale(key: PeerID, storer: PeerDescriptor, stale: boolean): void {
81
+ const storerKey = keyFromPeerDescriptor(storer)
82
+ const storedEntry = this.store.get(key.toKey())?.get(storerKey)
83
+ if (storedEntry) {
84
+ storedEntry.dataEntry.stale = stale
85
+ }
86
+ }
87
+
88
+ public setAllEntriesAsStale(key: PeerID): void {
89
+ this.store.get(key.toKey())?.forEach((value) => {
90
+ value.dataEntry.stale = true
91
+ })
92
+ }
93
+
94
+ public deleteEntry(key: PeerID, storer: PeerDescriptor): void {
95
+ const storerKey = keyFromPeerDescriptor(storer)
96
+ const storedEntry = this.store.get(key.toKey())?.get(storerKey)
97
+ if (storedEntry) {
98
+ clearTimeout(storedEntry.ttlTimeout)
99
+ this.store.get(key.toKey())?.delete(storerKey)
100
+ if (this.store.get(key.toKey())?.size === 0) {
101
+ this.store.delete(key.toKey())
102
+ }
103
+ }
104
+ }
105
+
106
+ public clear(): void {
107
+ this.store.forEach((value) => {
108
+ value.forEach((value) => {
109
+ clearTimeout(value.ttlTimeout)
110
+ })
111
+ })
112
+ this.store.clear()
113
+ }
114
+ }
@@ -0,0 +1,58 @@
1
+ import { Remote } from '../contact/Remote'
2
+ import { IStoreServiceClient } from '../../proto/packages/dht/protos/DhtRpc.client'
3
+ import {
4
+ DeleteDataRequest,
5
+ DeleteDataResponse,
6
+ MigrateDataRequest,
7
+ MigrateDataResponse,
8
+ StoreDataRequest,
9
+ StoreDataResponse
10
+ } from '../../proto/packages/dht/protos/DhtRpc'
11
+ import { DhtRpcOptions } from '../../rpc-protocol/DhtRpcOptions'
12
+ import { keyFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
13
+
14
+ export class RemoteStore extends Remote<IStoreServiceClient> {
15
+
16
+ async storeData(request: StoreDataRequest): Promise<StoreDataResponse> {
17
+ const options: DhtRpcOptions = {
18
+ sourceDescriptor: this.ownPeerDescriptor,
19
+ targetDescriptor: this.peerDescriptor,
20
+ timeout: 10000
21
+ }
22
+ try {
23
+ return await this.client.storeData(request, options)
24
+ } catch (err) {
25
+ throw Error(
26
+ `Could not store data to ${keyFromPeerDescriptor(this.peerDescriptor)} from ${keyFromPeerDescriptor(this.ownPeerDescriptor)} ${err}`
27
+ )
28
+ }
29
+ }
30
+
31
+ async deleteData(request: DeleteDataRequest): Promise<DeleteDataResponse> {
32
+ const options: DhtRpcOptions = {
33
+ sourceDescriptor: this.ownPeerDescriptor,
34
+ targetDescriptor: this.peerDescriptor,
35
+ timeout: 10000
36
+ }
37
+ try {
38
+ return await this.client.deleteData(request, options)
39
+ } catch (err) {
40
+ throw Error(
41
+ `Could not call delete data to ${keyFromPeerDescriptor(this.peerDescriptor)} ${err}`
42
+ )
43
+ }
44
+ }
45
+
46
+ async migrateData(request: MigrateDataRequest, doNotConnect: boolean = false): Promise<MigrateDataResponse> {
47
+
48
+ const options: DhtRpcOptions = {
49
+ sourceDescriptor: this.ownPeerDescriptor,
50
+ targetDescriptor: this.peerDescriptor,
51
+ timeout: 10000,
52
+ doNotConnect: doNotConnect
53
+ }
54
+
55
+ return this.client.migrateData(request, options)
56
+ }
57
+
58
+ }
package/src/exports.ts ADDED
@@ -0,0 +1,19 @@
1
+ export { DhtNode, DhtNodeEvents, DhtNodeOptions } from './dht/DhtNode'
2
+ export { ListeningRpcCommunicator } from './transport/ListeningRpcCommunicator'
3
+ export { Simulator, LatencyType } from './connection/Simulator/Simulator'
4
+ export { SimulatorTransport } from './connection/Simulator/SimulatorTransport'
5
+ export { getRandomRegion, getRegionDelayMatrix } from './connection/Simulator/pings'
6
+ export { PeerDescriptor, Message, NodeType, DataEntry } from './proto/packages/dht/protos/DhtRpc'
7
+ export { ITransport } from './transport/ITransport'
8
+ export { ConnectionManager, ConnectionLocker } from './connection/ConnectionManager'
9
+ export { PeerID, PeerIDKey } from './helpers/PeerID'
10
+ export { DhtPeer } from './dht/DhtPeer'
11
+ export { UUID } from './helpers/UUID'
12
+ export { DhtRpcOptions } from './rpc-protocol/DhtRpcOptions'
13
+ export { protoClasses } from './helpers/protoClasses'
14
+ export { SortedContactList } from './dht/contact/SortedContactList'
15
+ export { Contact } from './dht/contact/Contact'
16
+ export { RecursiveFindResult } from './dht/find/RecursiveFinder'
17
+ export { peerIdFromPeerDescriptor, keyFromPeerDescriptor, isSamePeerDescriptor } from './helpers/peerIdFromPeerDescriptor'
18
+ export { IceServer } from './connection/WebRTC/WebRtcConnector'
19
+ export { DhtCallContext } from './rpc-protocol/DhtCallContext'
@@ -0,0 +1,26 @@
1
+ import ipaddr from 'ipaddr.js'
2
+
3
+ // IPv4 private address ranges as specified by RFC 1918
4
+ const IPv4PrivateRanges = [
5
+ '10.0.0.0/8',
6
+ '172.16.0.0/12',
7
+ '192.168.0.0/16',
8
+ ].map((a) => ipaddr.parseCIDR(a))
9
+
10
+ export function isPrivateIPv4(address: string): boolean {
11
+ if (ipaddr.IPv4.isValid(address)) {
12
+ const ip = ipaddr.IPv4.parse(address)
13
+ for (const range of IPv4PrivateRanges) {
14
+ if (ip.match(range)) {
15
+ return true
16
+ }
17
+ }
18
+ }
19
+
20
+ return false
21
+ }
22
+
23
+ export function getAddressFromIceCandidate(candidate: string): string | undefined {
24
+ const fields = candidate.split(' ').filter((field) => field.length > 0)
25
+ return fields.length >= 5 && ipaddr.isValid(fields[4]) ? fields[4] : undefined
26
+ }
@@ -0,0 +1,95 @@
1
+ import { BrandedString } from '@streamr/utils'
2
+ import { UUID } from './UUID'
3
+ import { IllegalArguments } from './errors'
4
+ import crypto from 'crypto'
5
+
6
+ export type PeerIDKey = BrandedString<'PeerIDKey'>
7
+
8
+ export class PeerID {
9
+ // avoid creating a new instance for every operation
10
+ private static readonly textEncoder = new TextEncoder()
11
+ private static readonly textDecoder = new TextDecoder()
12
+
13
+ private readonly data!: Uint8Array
14
+ private readonly key: PeerIDKey // precompute often-used form of data
15
+
16
+ protected constructor({ ip, value, stringValue }: { ip?: string, value?: Uint8Array, stringValue?: string } = {}) {
17
+ if (ip) {
18
+ this.data = new Uint8Array(20)
19
+ const ipNum = this.ip2Int(ip)
20
+ const view = new DataView(this.data.buffer)
21
+ view.setInt32(0, ipNum)
22
+
23
+ this.data.set((new UUID()).value, 4)
24
+ } else if (value) {
25
+ this.data = new Uint8Array(value.slice(0))
26
+ } else if (stringValue) {
27
+ const ab = PeerID.textEncoder.encode(stringValue) //toUTF8Array(stringValue)
28
+ this.data = ab
29
+ } else {
30
+ throw new IllegalArguments('Constructor of PeerID must be given either ip, value or stringValue')
31
+ }
32
+
33
+ this.key = Buffer.from(this.data).toString('hex') as PeerIDKey
34
+ }
35
+
36
+ static fromIp(ip: string): PeerID {
37
+ return new PeerID({ ip })
38
+ }
39
+
40
+ static fromValue(value: Uint8Array): PeerID {
41
+ return new PeerID({ value })
42
+ }
43
+
44
+ static fromKey(value: PeerIDKey): PeerID {
45
+ return new PeerID({ value: Buffer.from(value, 'hex') })
46
+ }
47
+
48
+ static fromString(stringValue: string): PeerID {
49
+ return new PeerID({ stringValue })
50
+ }
51
+
52
+ static generateRandom(): PeerID {
53
+ // generate 160 bit random Uint8array
54
+ const value = new Uint8Array(20)
55
+ crypto.randomFillSync(value)
56
+ return new PeerID({ value })
57
+ }
58
+
59
+ // TODO convert to static method?
60
+ // eslint-disable-next-line class-methods-use-this
61
+ private ip2Int(ip: string): number {
62
+ return ip.split('.').map((octet, index, array) => {
63
+ return parseInt(octet) * Math.pow(256, (array.length - index - 1))
64
+ }).reduce((prev, curr) => {
65
+ return prev + curr
66
+ })
67
+ }
68
+
69
+ equals(other: PeerID): boolean {
70
+ return (Buffer.compare(this.data, other.value) === 0)
71
+ }
72
+
73
+ toString(): string {
74
+ return PeerID.textDecoder.decode(this.data) //utf8ArrayToString(this.data)
75
+ }
76
+
77
+ toKey(): PeerIDKey {
78
+ return this.key
79
+ }
80
+
81
+ get value(): Uint8Array {
82
+ return this.data
83
+ }
84
+
85
+ hasSmallerHashThan(other: PeerID): boolean {
86
+ const myId = this.toKey()
87
+ const theirId = other.toKey()
88
+ return PeerID.offeringHash(myId + ',' + theirId) < PeerID.offeringHash(theirId + ',' + myId)
89
+ }
90
+
91
+ private static offeringHash(idPair: string): number {
92
+ const buffer = crypto.createHash('md5').update(idPair).digest()
93
+ return buffer.readInt32LE(0)
94
+ }
95
+ }
@@ -0,0 +1,30 @@
1
+ import { v4, parse, stringify } from 'uuid'
2
+
3
+ export class UUID {
4
+ private buf: Uint8Array
5
+
6
+ constructor(other?: (UUID | Uint8Array | string)) {
7
+ if (!other) {
8
+ this.buf = new Uint8Array(16)
9
+ v4(null, this.buf)
10
+ } else if (other.constructor === UUID) {
11
+ this.buf = other.buf
12
+ } else if (typeof other === 'string') {
13
+ this.buf = new Uint8Array(parse(other))
14
+ } else {
15
+ this.buf = other as Uint8Array
16
+ }
17
+ }
18
+
19
+ toString(): string {
20
+ return stringify(this.buf)
21
+ }
22
+
23
+ equals(other: UUID): boolean {
24
+ return (Buffer.compare(this.buf, other.value) === 0)
25
+ }
26
+
27
+ get value(): Uint8Array {
28
+ return this.buf
29
+ }
30
+ }
@@ -0,0 +1,9 @@
1
+ import { Logger } from '@streamr/utils'
2
+
3
+ export const debugVars: Record<string, any> = []
4
+
5
+ export function logInfoIf(logger: Logger, condition: boolean, msg: string): void {
6
+ if (condition) {
7
+ logger.info(msg)
8
+ }
9
+ }