@streamr/dht 100.0.0-pretestnet.6 → 100.0.0-rc.1

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 +19 -10
  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 +1 -2
  49. package/dist/src/connection/webrtc/WebrtcConnector.js +36 -32
  50. package/dist/src/connection/webrtc/WebrtcConnector.js.map +1 -1
  51. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.d.ts +4 -2
  52. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js +28 -22
  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 +17 -14
  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 +24 -12
  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 +25 -27
  254. package/src/connection/webrtc/WebrtcConnector.ts +31 -36
  255. package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +31 -25
  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,11 +1,9 @@
1
1
  import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
2
- import { toProtoRpcClient } from '@streamr/proto-rpc'
3
2
  import { Logger } from '@streamr/utils'
4
3
  import { getAddressFromIceCandidate, isPrivateIPv4 } from '../../helpers/AddressTools'
5
- import { PeerIDKey } from '../../helpers/PeerID'
6
- import { keyFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
7
4
  import { Empty } from '../../proto/google/protobuf/empty'
8
5
  import {
6
+ HandshakeError,
9
7
  IceCandidate,
10
8
  PeerDescriptor,
11
9
  RtcAnswer,
@@ -19,14 +17,18 @@ import { ManagedConnection } from '../ManagedConnection'
19
17
  import { ManagedWebrtcConnection } from '../ManagedWebrtcConnection'
20
18
  import { NodeWebrtcConnection } from './NodeWebrtcConnection'
21
19
  import { WebrtcConnectorRpcRemote } from './WebrtcConnectorRpcRemote'
20
+ import { DhtAddress, getNodeIdFromPeerDescriptor } from '../../identifiers'
21
+ import { isMaybeSupportedVersion } from '../../helpers/version'
22
+ import { ConnectionID } from '../IConnection'
22
23
 
23
24
  const logger = new Logger(module)
24
25
 
25
26
  interface WebrtcConnectorRpcLocalConfig {
27
+ createConnection: (targetPeerDescriptor: PeerDescriptor) => NodeWebrtcConnection
26
28
  connect: (targetPeerDescriptor: PeerDescriptor) => ManagedConnection
27
29
  onNewConnection: (connection: ManagedConnection) => boolean
28
30
  // TODO pass accessor methods instead of passing a mutable entity
29
- ongoingConnectAttempts: Map<PeerIDKey, ManagedWebrtcConnection>
31
+ ongoingConnectAttempts: Map<DhtAddress, ManagedWebrtcConnection>
30
32
  rpcCommunicator: ListeningRpcCommunicator
31
33
  getLocalPeerDescriptor: () => PeerDescriptor
32
34
  allowPrivateAddresses: boolean
@@ -42,7 +44,7 @@ export class WebrtcConnectorRpcLocal implements IWebrtcConnectorRpc {
42
44
 
43
45
  async requestConnection(context: ServerCallContext): Promise<Empty> {
44
46
  const targetPeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
45
- if (this.config.ongoingConnectAttempts.has(keyFromPeerDescriptor(targetPeerDescriptor))) {
47
+ if (this.config.ongoingConnectAttempts.has(getNodeIdFromPeerDescriptor(targetPeerDescriptor))) {
46
48
  return {}
47
49
  }
48
50
  const managedConnection = this.config.connect(targetPeerDescriptor)
@@ -53,50 +55,55 @@ export class WebrtcConnectorRpcLocal implements IWebrtcConnectorRpc {
53
55
 
54
56
  async rtcOffer(request: RtcOffer, context: ServerCallContext): Promise<Empty> {
55
57
  const remotePeer = (context as DhtCallContext).incomingSourceDescriptor!
56
- const peerKey = keyFromPeerDescriptor(remotePeer)
57
- let managedConnection = this.config.ongoingConnectAttempts.get(peerKey)
58
+ const nodeId = getNodeIdFromPeerDescriptor(remotePeer)
59
+ let managedConnection = this.config.ongoingConnectAttempts.get(nodeId)
58
60
  let connection = managedConnection?.getWebrtcConnection()
59
61
 
60
62
  if (!managedConnection) {
61
- connection = new NodeWebrtcConnection({ remotePeerDescriptor: remotePeer })
63
+ connection = this.config.createConnection(remotePeer)
62
64
  managedConnection = new ManagedWebrtcConnection(this.config.getLocalPeerDescriptor(), undefined, connection)
63
65
  managedConnection.setRemotePeerDescriptor(remotePeer)
64
- this.config.ongoingConnectAttempts.set(peerKey, managedConnection)
66
+ this.config.ongoingConnectAttempts.set(nodeId, managedConnection)
65
67
  this.config.onNewConnection(managedConnection)
66
68
  const remoteConnector = new WebrtcConnectorRpcRemote(
67
69
  this.config.getLocalPeerDescriptor(),
68
70
  remotePeer,
69
- toProtoRpcClient(new WebrtcConnectorRpcClient(this.config.rpcCommunicator.getRpcClientTransport()))
71
+ this.config.rpcCommunicator,
72
+ WebrtcConnectorRpcClient
70
73
  )
71
74
  connection.on('localCandidate', (candidate: string, mid: string) => {
72
- remoteConnector.sendIceCandidate(candidate, mid, connection!.connectionId.toString())
75
+ remoteConnector.sendIceCandidate(candidate, mid, connection!.connectionId)
73
76
  })
74
77
  connection.once('localDescription', (description: string) => {
75
- remoteConnector.sendRtcAnswer(description, connection!.connectionId.toString())
78
+ remoteConnector.sendRtcAnswer(description, connection!.connectionId)
76
79
  })
77
80
  connection.start(false)
78
81
  }
79
82
 
80
83
  // Always use offerers connectionId
81
- connection!.setConnectionId(request.connectionId)
84
+ connection!.setConnectionId(request.connectionId as ConnectionID)
82
85
  connection!.setRemoteDescription(request.description, 'offer')
83
86
 
84
- managedConnection.on('handshakeRequest', () => {
85
- if (this.config.ongoingConnectAttempts.has(peerKey)) {
86
- this.config.ongoingConnectAttempts.delete(peerKey)
87
+ managedConnection.on('handshakeRequest', (_sourceDescriptor: PeerDescriptor, remoteVersion: string) => {
88
+ if (this.config.ongoingConnectAttempts.has(nodeId)) {
89
+ this.config.ongoingConnectAttempts.delete(nodeId)
90
+ }
91
+ if (!isMaybeSupportedVersion(remoteVersion)) {
92
+ managedConnection!.rejectHandshake(HandshakeError.UNSUPPORTED_VERSION)
93
+ } else {
94
+ managedConnection!.acceptHandshake()
87
95
  }
88
- managedConnection!.acceptHandshake()
89
96
  })
90
97
  return {}
91
98
  }
92
99
 
93
100
  async rtcAnswer(request: RtcAnswer, context: ServerCallContext): Promise<Empty> {
94
101
  const remotePeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
95
- const peerKey = keyFromPeerDescriptor(remotePeerDescriptor)
96
- const connection = this.config.ongoingConnectAttempts.get(peerKey)?.getWebrtcConnection()
102
+ const nodeId = getNodeIdFromPeerDescriptor(remotePeerDescriptor)
103
+ const connection = this.config.ongoingConnectAttempts.get(nodeId)?.getWebrtcConnection()
97
104
  if (!connection) {
98
105
  return {}
99
- } else if (connection.connectionId.toString() !== request.connectionId) {
106
+ } else if (connection.connectionId !== request.connectionId) {
100
107
  logger.trace(`Ignoring RTC answer due to connectionId mismatch`)
101
108
  return {}
102
109
  }
@@ -106,12 +113,11 @@ export class WebrtcConnectorRpcLocal implements IWebrtcConnectorRpc {
106
113
 
107
114
  async iceCandidate(request: IceCandidate, context: ServerCallContext): Promise<Empty> {
108
115
  const remotePeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
109
- const peerKey = keyFromPeerDescriptor(remotePeerDescriptor)
110
- const connection = this.config.ongoingConnectAttempts.get(peerKey)?.getWebrtcConnection()
111
-
116
+ const nodeId = getNodeIdFromPeerDescriptor(remotePeerDescriptor)
117
+ const connection = this.config.ongoingConnectAttempts.get(nodeId)?.getWebrtcConnection()
112
118
  if (!connection) {
113
119
  return {}
114
- } else if (connection.connectionId.toString() !== request.connectionId) {
120
+ } else if (connection.connectionId !== request.connectionId) {
115
121
  logger.trace(`Ignoring remote candidate due to connectionId mismatch`)
116
122
  return {}
117
123
  } else if (this.isIceCandidateAllowed(request.candidate)) {
@@ -123,7 +129,7 @@ export class WebrtcConnectorRpcLocal implements IWebrtcConnectorRpc {
123
129
  private isIceCandidateAllowed(candidate: string): boolean {
124
130
  if (!this.config.allowPrivateAddresses) {
125
131
  const address = getAddressFromIceCandidate(candidate)
126
- if (address && isPrivateIPv4(address)) {
132
+ if ((address !== undefined) && isPrivateIPv4(address)) {
127
133
  return false
128
134
  }
129
135
  }
@@ -1,26 +1,16 @@
1
- import { Remote } from '../../dht/contact/Remote'
1
+ import { Logger } from '@streamr/utils'
2
+ import { RpcRemote } from '../../dht/contact/RpcRemote'
2
3
  import {
3
4
  IceCandidate,
4
- PeerDescriptor,
5
5
  RtcAnswer,
6
6
  RtcOffer,
7
7
  WebrtcConnectionRequest
8
8
  } from '../../proto/packages/dht/protos/DhtRpc'
9
- import { IWebrtcConnectorRpcClient } from '../../proto/packages/dht/protos/DhtRpc.client'
10
- import { ProtoRpcClient } from '@streamr/proto-rpc'
11
- import { Logger } from '@streamr/utils'
9
+ import { WebrtcConnectorRpcClient } from '../../proto/packages/dht/protos/DhtRpc.client'
12
10
 
13
11
  const logger = new Logger(module)
14
12
 
15
- export class WebrtcConnectorRpcRemote extends Remote<IWebrtcConnectorRpcClient> {
16
-
17
- constructor(
18
- localPeerDescriptor: PeerDescriptor,
19
- remotePeerDescriptor: PeerDescriptor,
20
- client: ProtoRpcClient<IWebrtcConnectorRpcClient>
21
- ) {
22
- super(localPeerDescriptor, remotePeerDescriptor, 'DUMMY', client)
23
- }
13
+ export class WebrtcConnectorRpcRemote extends RpcRemote<WebrtcConnectorRpcClient> {
24
14
 
25
15
  requestConnection(): void {
26
16
  const request: WebrtcConnectionRequest = {
@@ -9,7 +9,7 @@ export function iceServerAsString({ url, port, username, password, tcp }: IceSer
9
9
  return `${protocol}:${hostname}:${port}`
10
10
  }
11
11
  if (username !== undefined && password !== undefined) {
12
- return `${protocol}:${username}:${password}@${hostname}:${port}${tcp ? '?transport=tcp' : ''}`
12
+ return `${protocol}:${username}:${password}@${hostname}:${port}${(tcp !== undefined) ? '?transport=tcp' : ''}`
13
13
  }
14
14
  throw new Error(`username (${username}) and password (${password}) must be supplied together`)
15
15
  }
@@ -55,12 +55,10 @@ export class AutoCertifierClientFacade {
55
55
 
56
56
  private autoCertifierClient: IAutoCertifierClient
57
57
  private readonly rpcCommunicator: ListeningRpcCommunicator
58
- private readonly setHost: (host: string) => void
59
- private readonly updateCertificate: (certificate: string, privateKey: string) => void
58
+ private readonly config: AutoCertifierClientFacadeConfig
60
59
 
61
60
  constructor(config: AutoCertifierClientFacadeConfig) {
62
- this.setHost = config.setHost
63
- this.updateCertificate = config.updateCertificate
61
+ this.config = config
64
62
  this.rpcCommunicator = new ListeningRpcCommunicator(AUTO_CERTIFIER_SERVICE_ID, config.transport)
65
63
  this.autoCertifierClient = config.createClientFactory ? config.createClientFactory()
66
64
  : defaultAutoCertifierClientFactory(
@@ -73,8 +71,8 @@ export class AutoCertifierClientFacade {
73
71
 
74
72
  async start(): Promise<void> {
75
73
  this.autoCertifierClient.on('updatedCertificate', (subdomain: CertifiedSubdomain) => {
76
- this.setHost(subdomain.fqdn)
77
- this.updateCertificate(subdomain.certificate, subdomain.privateKey)
74
+ this.config.setHost(subdomain.fqdn)
75
+ this.config.updateCertificate(subdomain.certificate, subdomain.privateKey)
78
76
  logger.trace(`Updated certificate`)
79
77
  })
80
78
  await Promise.all([
@@ -2,16 +2,21 @@ import { Logger } from '@streamr/utils'
2
2
  import EventEmitter from 'eventemitter3'
3
3
  import { ICloseEvent, IMessageEvent, w3cwebsocket as Websocket } from 'websocket'
4
4
  import { ConnectionEvents, ConnectionID, ConnectionType, IConnection } from '../IConnection'
5
+ import { createRandomConnectionId } from '../Connection'
5
6
 
6
7
  const logger = new Logger(module)
7
8
 
8
9
  // https://kapeli.com/cheat_sheets/WebSocket_Status_Codes.docset/Contents/Resources/Documents/index
9
10
  // Browsers send this automatically when closing a tab
10
11
  export const GOING_AWAY = 1001
12
+ // The GOING_AWAY is a reserved code and we shouldn't send that from the application. Therefore
13
+ // we have a custom counterpart
14
+ export const CUSTOM_GOING_AWAY = 3001
11
15
 
12
16
  const BINARY_TYPE = 'arraybuffer'
13
17
 
14
18
  export class ClientWebsocket extends EventEmitter<ConnectionEvents> implements IConnection {
19
+
15
20
  public readonly connectionId: ConnectionID
16
21
  private socket?: Websocket
17
22
  public connectionType = ConnectionType.WEBSOCKET_CLIENT
@@ -20,9 +25,10 @@ export class ClientWebsocket extends EventEmitter<ConnectionEvents> implements I
20
25
 
21
26
  constructor() {
22
27
  super()
23
- this.connectionId = new ConnectionID()
28
+ this.connectionId = createRandomConnectionId()
24
29
  }
25
30
 
31
+ // TODO explicit default value for "selfSigned" or make it required
26
32
  public connect(address: string, selfSigned?: boolean): void {
27
33
  if (!this.destroyed) {
28
34
  this.socket = new Websocket(address, undefined, undefined, undefined, { rejectUnauthorized: !selfSigned })
@@ -68,7 +74,7 @@ export class ClientWebsocket extends EventEmitter<ConnectionEvents> implements I
68
74
  this.destroyed = true
69
75
  this.stopListening()
70
76
  this.socket = undefined
71
- const gracefulLeave = code === GOING_AWAY
77
+ const gracefulLeave = (code === GOING_AWAY) || (code === CUSTOM_GOING_AWAY)
72
78
  this.emit('disconnected', gracefulLeave, code, reason)
73
79
  this.removeAllListeners()
74
80
  }
@@ -90,8 +96,8 @@ export class ClientWebsocket extends EventEmitter<ConnectionEvents> implements I
90
96
  this.emit('disconnected', gracefulLeave, undefined, 'close() called')
91
97
  this.removeAllListeners()
92
98
  if (!this.destroyed) {
93
- logger.trace(`Closing socket for connection ${this.connectionId.toString()}`)
94
- this.socket?.close(gracefulLeave === true ? GOING_AWAY : undefined)
99
+ logger.trace(`Closing socket for connection ${this.connectionId}`)
100
+ this.socket?.close(gracefulLeave ? CUSTOM_GOING_AWAY : undefined)
95
101
  } else {
96
102
  logger.debug('Tried to close() a stopped connection')
97
103
  }
@@ -9,26 +9,28 @@ import {
9
9
  ConnectivityResponse,
10
10
  HandshakeError,
11
11
  PeerDescriptor,
12
- WebsocketConnectionRequest,
13
- WebsocketConnectionResponse
12
+ WebsocketConnectionRequest
14
13
  } from '../../proto/packages/dht/protos/DhtRpc'
15
14
  import { WebsocketConnectorRpcClient } from '../../proto/packages/dht/protos/DhtRpc.client'
16
- import { Logger, binaryToHex, wait } from '@streamr/utils'
15
+ import { ipv4ToNumber, Logger, wait } from '@streamr/utils'
17
16
  import { ManagedConnection } from '../ManagedConnection'
18
17
  import { WebsocketServer } from './WebsocketServer'
19
- import { ConnectivityChecker } from '../ConnectivityChecker'
18
+ import { sendConnectivityRequest } from '../connectivityChecker'
20
19
  import { NatType, PortRange, TlsCertificate } from '../ConnectionManager'
21
- import { PeerIDKey } from '../../helpers/PeerID'
22
- import { ServerWebsocket } from './ServerWebsocket'
23
- import { toProtoRpcClient } from '@streamr/proto-rpc'
20
+ import { WebsocketServerConnection } from './WebsocketServerConnection'
24
21
  import { Handshaker } from '../Handshaker'
25
- import { areEqualPeerDescriptors, keyFromPeerDescriptor, peerIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
26
- import { ParsedUrlQuery } from 'querystring'
22
+ import queryString from 'querystring'
27
23
  import { range, sample } from 'lodash'
28
24
  import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
29
25
  import { expectedConnectionType } from '../../helpers/Connectivity'
30
26
  import { WebsocketServerStartError } from '../../helpers/errors'
31
27
  import { AutoCertifierClientFacade } from './AutoCertifierClientFacade'
28
+ import { DISABLE_CONNECTIVITY_PROBE, attachConnectivityRequestHandler } from '../connectivityRequestHandler'
29
+ import * as Err from '../../helpers/errors'
30
+ import { Empty } from '../../proto/google/protobuf/empty'
31
+ import { DhtAddress, areEqualPeerDescriptors, getNodeIdFromPeerDescriptor } from '../../identifiers'
32
+ import { LOCAL_PROTOCOL_VERSION, isMaybeSupportedVersion } from '../../helpers/version'
33
+
32
34
  const logger = new Logger(module)
33
35
 
34
36
  export type Action = 'connectivityRequest' | 'connectivityProbe'
@@ -38,11 +40,10 @@ export const connectivityMethodToWebsocketUrl = (ws: ConnectivityMethod, action?
38
40
  }
39
41
 
40
42
  const ENTRY_POINT_CONNECTION_ATTEMPTS = 5
41
-
42
43
  export interface WebsocketConnectorConfig {
43
44
  transport: ITransport
44
- canConnect: (peerDescriptor: PeerDescriptor) => boolean
45
45
  onNewConnection: (connection: ManagedConnection) => boolean
46
+ hasConnection: (nodeId: DhtAddress) => boolean
46
47
  portRange?: PortRange
47
48
  maxMessageSize?: number
48
49
  host?: string
@@ -59,59 +60,55 @@ export class WebsocketConnector {
59
60
  private static readonly WEBSOCKET_CONNECTOR_SERVICE_ID = 'system/websocket-connector'
60
61
  private readonly rpcCommunicator: ListeningRpcCommunicator
61
62
  private readonly websocketServer?: WebsocketServer
62
- private connectivityChecker?: ConnectivityChecker
63
- private readonly ongoingConnectRequests: Map<PeerIDKey, ManagedConnection> = new Map()
64
- private onNewConnection: (connection: ManagedConnection) => boolean
63
+ private readonly ongoingConnectRequests: Map<DhtAddress, ManagedConnection> = new Map()
65
64
  private host?: string
66
- private readonly entrypoints?: PeerDescriptor[]
67
- private readonly tlsCertificate?: TlsCertificate
68
- private readonly autoCertifierTransport: ITransport
69
- private readonly autoCertifierUrl: string
70
- private readonly autoCertifierConfigFile: string
71
- private readonly serverEnableTls: boolean
72
65
  private autoCertifierClient?: AutoCertifierClientFacade
73
66
  private selectedPort?: number
74
67
  private localPeerDescriptor?: PeerDescriptor
75
- private connectingConnections: Map<PeerIDKey, ManagedConnection> = new Map()
68
+ private connectingConnections: Map<DhtAddress, ManagedConnection> = new Map()
76
69
  private abortController = new AbortController()
70
+ private readonly config: WebsocketConnectorConfig
77
71
 
78
72
  constructor(config: WebsocketConnectorConfig) {
73
+ this.config = config
79
74
  this.websocketServer = config.portRange ? new WebsocketServer({
80
- portRange: config.portRange!,
75
+ portRange: config.portRange,
81
76
  tlsCertificate: config.tlsCertificate,
82
77
  maxMessageSize: config.maxMessageSize,
83
78
  enableTls: config.serverEnableTls
84
79
  }) : undefined
85
- this.onNewConnection = config.onNewConnection
86
80
  this.host = config.host
87
- this.entrypoints = config.entrypoints
88
- this.tlsCertificate = config.tlsCertificate
89
- this.autoCertifierTransport = config.autoCertifierTransport
90
- this.autoCertifierUrl = config.autoCertifierUrl
91
- this.autoCertifierConfigFile = config.autoCertifierConfigFile
92
- this.serverEnableTls = config.serverEnableTls
93
81
  this.rpcCommunicator = new ListeningRpcCommunicator(WebsocketConnector.WEBSOCKET_CONNECTOR_SERVICE_ID, config.transport, {
94
- rpcRequestTimeout: 15000
82
+ rpcRequestTimeout: 15000 // TODO use config option or named constant?
95
83
  })
96
84
  this.registerLocalRpcMethods(config)
97
85
  }
98
86
 
99
87
  private registerLocalRpcMethods(config: WebsocketConnectorConfig) {
100
88
  const rpcLocal = new WebsocketConnectorRpcLocal({
101
- canConnect: (peerDescriptor: PeerDescriptor) => config.canConnect(peerDescriptor),
102
89
  connect: (targetPeerDescriptor: PeerDescriptor) => this.connect(targetPeerDescriptor),
90
+ hasConnection: (nodeId: DhtAddress): boolean => {
91
+ if (this.connectingConnections.has(nodeId)
92
+ || this.connectingConnections.has(nodeId)
93
+ || this.ongoingConnectRequests.has(nodeId)
94
+ || config.hasConnection(nodeId)
95
+ ) {
96
+ return true
97
+ } else {
98
+ return false
99
+ }
100
+ },
103
101
  onNewConnection: (connection: ManagedConnection) => config.onNewConnection(connection),
104
102
  abortSignal: this.abortController.signal
105
103
  })
106
- this.rpcCommunicator.registerRpcMethod(
104
+ this.rpcCommunicator.registerRpcNotification(
107
105
  WebsocketConnectionRequest,
108
- WebsocketConnectionResponse,
109
106
  'requestConnection',
110
- async (req: WebsocketConnectionRequest, context: ServerCallContext) => {
107
+ async (req: WebsocketConnectionRequest, context: ServerCallContext): Promise<Empty> => {
111
108
  if (!this.abortController.signal.aborted) {
112
109
  return rpcLocal.requestConnection(req, context)
113
110
  } else {
114
- return { accepted: false }
111
+ return {}
115
112
  }
116
113
  }
117
114
  )
@@ -119,82 +116,100 @@ export class WebsocketConnector {
119
116
 
120
117
  private attachHandshaker(connection: IConnection) {
121
118
  const handshaker = new Handshaker(this.localPeerDescriptor!, connection)
122
- handshaker.once('handshakeRequest', (localPeerDescriptor: PeerDescriptor, remotePeerDescriptor?: PeerDescriptor) => {
123
- this.onServerSocketHandshakeRequest(localPeerDescriptor, connection, remotePeerDescriptor)
119
+ handshaker.once('handshakeRequest', (localPeerDescriptor: PeerDescriptor, sourceVersion: string, remotePeerDescriptor?: PeerDescriptor) => {
120
+ this.onServerSocketHandshakeRequest(localPeerDescriptor, connection, sourceVersion, remotePeerDescriptor)
124
121
  })
125
122
  }
126
123
 
127
124
  public async autoCertify(): Promise<void> {
128
125
  this.autoCertifierClient = new AutoCertifierClientFacade({
129
- configFile: this.autoCertifierConfigFile,
130
- transport: this.autoCertifierTransport,
131
- url: this.autoCertifierUrl,
126
+ configFile: this.config.autoCertifierConfigFile,
127
+ transport: this.config.autoCertifierTransport,
128
+ url: this.config.autoCertifierUrl,
132
129
  wsServerPort: this.selectedPort!,
133
130
  setHost: (hostName: string) => this.setHost(hostName),
134
131
  updateCertificate: (certificate: string, privateKey: string) => this.websocketServer!.updateCertificate(certificate, privateKey)
135
132
  })
136
133
  logger.trace(`AutoCertifying subdomain...`)
137
- await this.autoCertifierClient!.start()
134
+ await this.autoCertifierClient.start()
138
135
  }
139
136
 
140
137
  private setHost(hostName: string): void {
141
138
  logger.trace(`Setting host name to ${hostName}`)
142
139
  this.host = hostName
143
- this.connectivityChecker!.setHost(hostName)
144
140
  }
145
141
 
146
142
  public async start(): Promise<void> {
147
143
  if (!this.abortController.signal.aborted && this.websocketServer) {
148
144
  this.websocketServer.on('connected', (connection: IConnection) => {
149
- const serverSocket = connection as unknown as ServerWebsocket
150
- const query = serverSocket.resourceURL.query as unknown as (ParsedUrlQuery | null)
151
- const action = query?.action as (Action | undefined)
152
- logger.trace('WebSocket client connected', { action, remoteAddress: serverSocket.getRemoteAddress() })
145
+ const serverSocket = connection as unknown as WebsocketServerConnection
146
+ const query = queryString.parse(serverSocket.resourceURL.query as string ?? '')
147
+ const action = query.action as (Action | undefined)
148
+ logger.trace('WebSocket client connected', { action, remoteAddress: serverSocket.remoteIpAddress })
153
149
  if (action === 'connectivityRequest') {
154
- this.connectivityChecker!.listenToIncomingConnectivityRequests(serverSocket)
150
+ attachConnectivityRequestHandler(serverSocket)
155
151
  } else if (action === 'connectivityProbe') {
156
152
  // no-op
157
153
  } else {
158
- this.attachHandshaker(connection)
154
+ // The localPeerDescriptor can be undefined here as the WS server is used for connectivity checks
155
+ // before the localPeerDescriptor is set during start.
156
+ // Handshaked connections should be rejected before the localPeerDescriptor is set.
157
+ if (this.localPeerDescriptor !== undefined) {
158
+ this.attachHandshaker(connection)
159
+ } else {
160
+ logger.trace('incoming Websocket connection before localPeerDescriptor was set, closing connection')
161
+ connection.close(false).catch(() => {})
162
+ }
159
163
  }
160
164
  })
161
165
  const port = await this.websocketServer.start()
162
166
  this.selectedPort = port
163
- this.connectivityChecker = new ConnectivityChecker(this.selectedPort, this.serverEnableTls, this.host)
164
167
  }
165
168
  }
166
169
 
167
170
  public async checkConnectivity(selfSigned: boolean): Promise<ConnectivityResponse> {
168
- // TODO: this could throw if the server is not running
169
- const noServerConnectivityResponse: ConnectivityResponse = {
170
- host: '127.0.0.1',
171
- natType: NatType.UNKNOWN
172
- }
171
+ // TODO: this could throw?
173
172
  if (this.abortController.signal.aborted) {
174
- return noServerConnectivityResponse
173
+ return {
174
+ host: '127.0.0.1',
175
+ natType: NatType.UNKNOWN,
176
+ ipAddress: ipv4ToNumber('127.0.0.1'),
177
+ version: LOCAL_PROTOCOL_VERSION
178
+ }
179
+ }
180
+ if (!this.config.entrypoints || this.config.entrypoints.length === 0) {
181
+ // return connectivity info given in config
182
+ return {
183
+ host: this.host!,
184
+ natType: NatType.OPEN_INTERNET,
185
+ websocket: {
186
+ host: this.host!,
187
+ port: this.selectedPort!,
188
+ tls: this.config.tlsCertificate !== undefined
189
+ },
190
+ // TODO: Resolve the given host name or or use as is if IP was given.
191
+ ipAddress: ipv4ToNumber('127.0.0.1'),
192
+ version: LOCAL_PROTOCOL_VERSION
193
+ }
175
194
  }
176
195
  for (const reattempt of range(ENTRY_POINT_CONNECTION_ATTEMPTS)) {
177
- const entryPoint = sample(this.entrypoints)!
196
+ const entryPoint = sample(this.config.entrypoints)!
178
197
  try {
179
- if (!this.websocketServer) {
180
- return noServerConnectivityResponse
198
+ // Do real connectivity checking
199
+ const connectivityRequest = {
200
+ port: this.selectedPort ?? DISABLE_CONNECTIVITY_PROBE,
201
+ host: this.host,
202
+ tls: this.websocketServer ? this.config.serverEnableTls : false,
203
+ selfSigned
204
+ }
205
+ if (!this.abortController.signal.aborted) {
206
+ return await sendConnectivityRequest(connectivityRequest, entryPoint)
181
207
  } else {
182
- if (!this.entrypoints || this.entrypoints.length === 0) {
183
- // return connectivity info given in config
184
- const preconfiguredConnectivityResponse: ConnectivityResponse = {
185
- host: this.host!,
186
- natType: NatType.OPEN_INTERNET,
187
- websocket: { host: this.host!, port: this.selectedPort!, tls: this.tlsCertificate !== undefined }
188
- }
189
- return preconfiguredConnectivityResponse
190
- } else {
191
- // Do real connectivity checking
192
- return await this.connectivityChecker!.sendConnectivityRequest(entryPoint, selfSigned)
193
- }
208
+ throw new Err.ConnectionFailed('ConnectivityChecker is destroyed')
194
209
  }
195
210
  } catch (err) {
196
211
  if (reattempt < ENTRY_POINT_CONNECTION_ATTEMPTS) {
197
- const error = `Failed to connect to entrypoint with id ${binaryToHex(entryPoint.kademliaId)} `
212
+ const error = `Failed to connect to entrypoint with id ${getNodeIdFromPeerDescriptor(entryPoint)} `
198
213
  + `and URL ${connectivityMethodToWebsocketUrl(entryPoint.websocket!)}`
199
214
  logger.error(error, { error: err })
200
215
  await wait(2000)
@@ -210,8 +225,8 @@ export class WebsocketConnector {
210
225
  }
211
226
 
212
227
  public connect(targetPeerDescriptor: PeerDescriptor): ManagedConnection {
213
- const peerKey = keyFromPeerDescriptor(targetPeerDescriptor)
214
- const existingConnection = this.connectingConnections.get(peerKey)
228
+ const nodeId = getNodeIdFromPeerDescriptor(targetPeerDescriptor)
229
+ const existingConnection = this.connectingConnections.get(nodeId)
215
230
  if (existingConnection) {
216
231
  return existingConnection
217
232
  }
@@ -232,11 +247,11 @@ export class WebsocketConnector {
232
247
  )
233
248
  managedConnection.setRemotePeerDescriptor(targetPeerDescriptor)
234
249
 
235
- this.connectingConnections.set(keyFromPeerDescriptor(targetPeerDescriptor), managedConnection)
250
+ this.connectingConnections.set(nodeId, managedConnection)
236
251
 
237
252
  const delFunc = () => {
238
- if (this.connectingConnections.has(peerKey)) {
239
- this.connectingConnections.delete(peerKey)
253
+ if (this.connectingConnections.has(nodeId)) {
254
+ this.connectingConnections.delete(nodeId)
240
255
  }
241
256
  socket.off('disconnected', delFunc)
242
257
  managedConnection.off('handshakeCompleted', delFunc)
@@ -255,9 +270,17 @@ export class WebsocketConnector {
255
270
  const remoteConnector = new WebsocketConnectorRpcRemote(
256
271
  localPeerDescriptor,
257
272
  targetPeerDescriptor,
258
- toProtoRpcClient(new WebsocketConnectorRpcClient(this.rpcCommunicator.getRpcClientTransport()))
273
+ this.rpcCommunicator,
274
+ WebsocketConnectorRpcClient
259
275
  )
260
- remoteConnector.requestConnection(localPeerDescriptor.websocket!.host, localPeerDescriptor.websocket!.port)
276
+ remoteConnector.requestConnection().then(() => {
277
+ logger.trace('Sent WebsocketConnectionRequest notification to peer', { targetPeerDescriptor })
278
+ return
279
+ }, (err) => {
280
+ logger.debug('Failed to send WebsocketConnectionRequest notification to peer ', {
281
+ error: err, targetPeerDescriptor
282
+ })
283
+ })
261
284
  })
262
285
  const managedConnection = new ManagedConnection(
263
286
  this.localPeerDescriptor!,
@@ -265,43 +288,44 @@ export class WebsocketConnector {
265
288
  undefined,
266
289
  undefined,
267
290
  targetPeerDescriptor
268
- )
269
- managedConnection.on('disconnected', () => this.ongoingConnectRequests.delete(keyFromPeerDescriptor(targetPeerDescriptor)))
291
+ )
292
+ const nodeId = getNodeIdFromPeerDescriptor(targetPeerDescriptor)
293
+ managedConnection.on('disconnected', () => this.ongoingConnectRequests.delete(nodeId))
270
294
  managedConnection.setRemotePeerDescriptor(targetPeerDescriptor)
271
- this.ongoingConnectRequests.set(keyFromPeerDescriptor(targetPeerDescriptor), managedConnection)
295
+ this.ongoingConnectRequests.set(nodeId, managedConnection)
272
296
  return managedConnection
273
297
  }
274
298
 
275
299
  private onServerSocketHandshakeRequest(
276
- sourcePeerDescriptor: PeerDescriptor,
277
- serverWebsocket: IConnection,
300
+ sourcePeerDescriptor: PeerDescriptor,
301
+ websocketServerConnection: IConnection,
302
+ remoteVersion: string,
278
303
  targetPeerDescriptor?: PeerDescriptor
279
304
  ) {
280
- const peerId = peerIdFromPeerDescriptor(sourcePeerDescriptor)
281
-
282
- if (this.ongoingConnectRequests.has(peerId.toKey())) {
283
- const ongoingConnectRequest = this.ongoingConnectRequests.get(peerId.toKey())!
284
- ongoingConnectRequest.attachImplementation(serverWebsocket)
285
- if (targetPeerDescriptor && !areEqualPeerDescriptors(this.localPeerDescriptor!, targetPeerDescriptor)) {
286
- ongoingConnectRequest.rejectHandshake(HandshakeError.INVALID_TARGET_PEER_DESCRIPTOR)
305
+ const nodeId = getNodeIdFromPeerDescriptor(sourcePeerDescriptor)
306
+ if (this.ongoingConnectRequests.has(nodeId)) {
307
+ const ongoingConnectRequest = this.ongoingConnectRequests.get(nodeId)!
308
+ if (!isMaybeSupportedVersion(remoteVersion)) {
309
+ ongoingConnectRequest.rejectHandshake(HandshakeError.UNSUPPORTED_VERSION)
287
310
  } else {
311
+ ongoingConnectRequest.attachImplementation(websocketServerConnection)
288
312
  ongoingConnectRequest.acceptHandshake()
289
- this.ongoingConnectRequests.delete(peerId.toKey())
290
313
  }
314
+ this.ongoingConnectRequests.delete(nodeId)
291
315
  } else {
292
316
  const managedConnection = new ManagedConnection(
293
317
  this.localPeerDescriptor!,
294
318
  ConnectionType.WEBSOCKET_SERVER,
295
319
  undefined,
296
- serverWebsocket,
320
+ websocketServerConnection,
297
321
  targetPeerDescriptor
298
322
  )
299
-
300
323
  managedConnection.setRemotePeerDescriptor(sourcePeerDescriptor)
301
-
302
- if (targetPeerDescriptor && !areEqualPeerDescriptors(this.localPeerDescriptor!, targetPeerDescriptor)) {
324
+ if (!isMaybeSupportedVersion(remoteVersion)) {
325
+ managedConnection.rejectHandshake(HandshakeError.UNSUPPORTED_VERSION)
326
+ } else if (targetPeerDescriptor && !areEqualPeerDescriptors(this.localPeerDescriptor!, targetPeerDescriptor)) {
303
327
  managedConnection.rejectHandshake(HandshakeError.INVALID_TARGET_PEER_DESCRIPTOR)
304
- } else if (this.onNewConnection(managedConnection)) {
328
+ } else if (this.config.onNewConnection(managedConnection)) {
305
329
  managedConnection.acceptHandshake()
306
330
  } else {
307
331
  managedConnection.rejectHandshake(HandshakeError.DUPLICATE_CONNECTION)
@@ -322,7 +346,6 @@ export class WebsocketConnector {
322
346
 
323
347
  const attempts = Array.from(this.connectingConnections.values())
324
348
  await Promise.allSettled(attempts.map((conn) => conn.close(false)))
325
- this.connectivityChecker?.destroy()
326
349
  await this.websocketServer?.stop()
327
350
  }
328
351
  }