@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,306 @@
1
+ import {
2
+ IceCandidate,
3
+ PeerDescriptor,
4
+ RtcAnswer,
5
+ RtcOffer, WebRtcConnectionRequest
6
+ } from '../../proto/packages/dht/protos/DhtRpc'
7
+ import { Empty } from '../../proto/google/protobuf/empty'
8
+ import { ITransport } from '../../transport/ITransport'
9
+ import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicator'
10
+ import { NodeWebRtcConnection } from './NodeWebRtcConnection'
11
+ import { RemoteWebrtcConnector } from './RemoteWebrtcConnector'
12
+ import { WebRtcConnectorServiceClient } from '../../proto/packages/dht/protos/DhtRpc.client'
13
+ import { PeerIDKey } from '../../helpers/PeerID'
14
+ import { ManagedWebRtcConnection } from '../ManagedWebRtcConnection'
15
+ import { Logger } from '@streamr/utils'
16
+ import * as Err from '../../helpers/errors'
17
+ import { IWebRtcConnectorService } from '../../proto/packages/dht/protos/DhtRpc.server'
18
+ import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
19
+ import { ManagedConnection } from '../ManagedConnection'
20
+ import { toProtoRpcClient } from '@streamr/proto-rpc'
21
+ import {
22
+ isSamePeerDescriptor,
23
+ keyFromPeerDescriptor,
24
+ peerIdFromPeerDescriptor
25
+ } from '../../helpers/peerIdFromPeerDescriptor'
26
+ import { getAddressFromIceCandidate, isPrivateIPv4 } from '../../helpers/AddressTools'
27
+
28
+ const logger = new Logger(module)
29
+
30
+ export interface WebRtcConnectorConfig {
31
+ rpcTransport: ITransport
32
+ protocolVersion: string
33
+ iceServers?: IceServer[]
34
+ allowPrivateAddresses?: boolean
35
+ bufferThresholdLow?: number
36
+ bufferThresholdHigh?: number
37
+ connectionTimeout?: number
38
+ }
39
+
40
+ export interface IceServer {
41
+ url: string
42
+ port: number
43
+ username?: string
44
+ password?: string
45
+ tcp?: boolean
46
+ }
47
+
48
+ export class WebRtcConnector implements IWebRtcConnectorService {
49
+ private static readonly WEBRTC_CONNECTOR_SERVICE_ID = 'system/webrtc_connector'
50
+ private readonly rpcCommunicator: ListeningRpcCommunicator
51
+ private readonly ongoingConnectAttempts: Map<PeerIDKey, ManagedWebRtcConnection> = new Map()
52
+ private ownPeerDescriptor?: PeerDescriptor
53
+ private stopped = false
54
+ private iceServers: IceServer[]
55
+ private allowPrivateAddresses: boolean
56
+ private config: WebRtcConnectorConfig
57
+ private incomingConnectionCallback: (connection: ManagedConnection) => boolean
58
+
59
+ constructor(
60
+ config: WebRtcConnectorConfig,
61
+ incomingConnectionCallback: (connection: ManagedConnection) => boolean
62
+ ) {
63
+ this.config = config
64
+ this.iceServers = config.iceServers || []
65
+ this.allowPrivateAddresses = config.allowPrivateAddresses || true
66
+ this.incomingConnectionCallback = incomingConnectionCallback
67
+
68
+ this.rpcCommunicator = new ListeningRpcCommunicator(WebRtcConnector.WEBRTC_CONNECTOR_SERVICE_ID, config.rpcTransport, {
69
+ rpcRequestTimeout: 15000
70
+ })
71
+ this.rpcCommunicator.registerRpcNotification(RtcOffer, 'rtcOffer',
72
+ (req: RtcOffer, context) => this.rtcOffer(req, context))
73
+ this.rpcCommunicator.registerRpcNotification(RtcAnswer, 'rtcAnswer',
74
+ (req: RtcAnswer, context) => this.rtcAnswer(req, context))
75
+ this.rpcCommunicator.registerRpcNotification(IceCandidate, 'iceCandidate',
76
+ (req: IceCandidate, context) => this.iceCandidate(req, context))
77
+ this.rpcCommunicator.registerRpcNotification(WebRtcConnectionRequest, 'requestConnection',
78
+ (req: WebRtcConnectionRequest, context) => this.requestConnection(req, context))
79
+ }
80
+
81
+ connect(targetPeerDescriptor: PeerDescriptor): ManagedConnection {
82
+ if (isSamePeerDescriptor(targetPeerDescriptor, this.ownPeerDescriptor!)) {
83
+ throw new Err.CannotConnectToSelf('Cannot open WebRTC Connection to self')
84
+ }
85
+
86
+ logger.trace(`Opening WebRTC connection to ${targetPeerDescriptor.kademliaId.toString()}`)
87
+
88
+ const peerKey = keyFromPeerDescriptor(targetPeerDescriptor)
89
+ const existingConnection = this.ongoingConnectAttempts.get(peerKey)
90
+ if (existingConnection) {
91
+ return existingConnection
92
+ }
93
+
94
+ const connection = new NodeWebRtcConnection({
95
+ remotePeerDescriptor: targetPeerDescriptor,
96
+ iceServers: this.iceServers,
97
+ bufferThresholdLow: this.config.bufferThresholdLow,
98
+ bufferThresholdHigh: this.config.bufferThresholdHigh,
99
+ connectingTimeout: this.config.connectionTimeout
100
+ })
101
+
102
+ const offering = this.isOffering(targetPeerDescriptor)
103
+ let managedConnection: ManagedWebRtcConnection
104
+
105
+ if (offering) {
106
+ managedConnection = new ManagedWebRtcConnection(this.ownPeerDescriptor!, this.config.protocolVersion, connection)
107
+ } else {
108
+ managedConnection = new ManagedWebRtcConnection(this.ownPeerDescriptor!, this.config.protocolVersion, undefined, connection)
109
+ }
110
+
111
+ managedConnection.setPeerDescriptor(targetPeerDescriptor)
112
+
113
+ this.ongoingConnectAttempts.set(keyFromPeerDescriptor(targetPeerDescriptor), managedConnection)
114
+
115
+ const delFunc = () => {
116
+ if (this.ongoingConnectAttempts.has(peerKey)) {
117
+ this.ongoingConnectAttempts.delete(peerKey)
118
+ }
119
+ connection.off('disconnected', delFunc)
120
+ managedConnection.off('handshakeCompleted', delFunc)
121
+ }
122
+ connection.on('disconnected', delFunc)
123
+ managedConnection.on('handshakeCompleted', delFunc)
124
+
125
+ const remoteConnector = new RemoteWebrtcConnector(
126
+ targetPeerDescriptor,
127
+ toProtoRpcClient(new WebRtcConnectorServiceClient(this.rpcCommunicator.getRpcClientTransport()))
128
+ )
129
+
130
+ connection.on('localCandidate', (candidate: string, mid: string) => {
131
+ remoteConnector.sendIceCandidate(this.ownPeerDescriptor!, candidate, mid, connection.connectionId.toString())
132
+ })
133
+
134
+ if (offering) {
135
+ connection.once('localDescription', (description: string, _type: string) => {
136
+ remoteConnector.sendRtcOffer(this.ownPeerDescriptor!, description, connection.connectionId.toString())
137
+ })
138
+ } else {
139
+ connection.once('localDescription', (description: string, _type: string) => {
140
+ remoteConnector.sendRtcAnswer(this.ownPeerDescriptor!, description, connection.connectionId.toString())
141
+ })
142
+ }
143
+
144
+ connection.start(offering)
145
+
146
+ if (!offering) {
147
+ remoteConnector.requestConnection(this.ownPeerDescriptor!, connection.connectionId.toString())
148
+ }
149
+
150
+ return managedConnection
151
+ }
152
+
153
+ setOwnPeerDescriptor(peerDescriptor: PeerDescriptor): void {
154
+ this.ownPeerDescriptor = peerDescriptor
155
+ }
156
+
157
+ isIceCandidateAllowed(candidate: string): boolean {
158
+ if (!this.allowPrivateAddresses) {
159
+ const address = getAddressFromIceCandidate(candidate)
160
+ if (address && isPrivateIPv4(address)) {
161
+ return false
162
+ }
163
+ }
164
+ return true
165
+ }
166
+
167
+ private onRtcOffer(
168
+ remotePeer: PeerDescriptor,
169
+ targetPeer: PeerDescriptor,
170
+ description: string,
171
+ connectionId: string
172
+ ): void {
173
+ if (this.stopped || !isSamePeerDescriptor(targetPeer, this.ownPeerDescriptor!)) {
174
+ return
175
+ }
176
+ const peerKey = keyFromPeerDescriptor(remotePeer)
177
+ let managedConnection = this.ongoingConnectAttempts.get(peerKey)
178
+ let connection = managedConnection?.getWebRtcConnection()
179
+
180
+ if (!managedConnection) {
181
+ connection = new NodeWebRtcConnection({ remotePeerDescriptor: remotePeer })
182
+ managedConnection = new ManagedWebRtcConnection(this.ownPeerDescriptor!, this.config.protocolVersion, undefined, connection)
183
+
184
+ managedConnection.setPeerDescriptor(remotePeer)
185
+
186
+ this.ongoingConnectAttempts.set(peerKey, managedConnection)
187
+ this.incomingConnectionCallback(managedConnection)
188
+
189
+ const remoteConnector = new RemoteWebrtcConnector(
190
+ remotePeer,
191
+ toProtoRpcClient(new WebRtcConnectorServiceClient(this.rpcCommunicator.getRpcClientTransport()))
192
+ )
193
+
194
+ connection.on('localCandidate', (candidate: string, mid: string) => {
195
+ remoteConnector.sendIceCandidate(this.ownPeerDescriptor!, candidate, mid, connection!.connectionId.toString())
196
+ })
197
+
198
+ connection.once('localDescription', (description: string, _type: string) => {
199
+ remoteConnector.sendRtcAnswer(this.ownPeerDescriptor!, description, connection!.connectionId.toString())
200
+ })
201
+
202
+ connection.start(false)
203
+
204
+ }
205
+
206
+ // Always use offerers connectionId
207
+ connection!.setConnectionId(connectionId)
208
+ connection!.setRemoteDescription(description, 'offer')
209
+
210
+ managedConnection!.on('handshakeRequest', () => {
211
+ if (this.ongoingConnectAttempts.has(peerKey)) {
212
+ this.ongoingConnectAttempts.delete(peerKey)
213
+ }
214
+ managedConnection!.acceptHandshake()
215
+ })
216
+ }
217
+
218
+ private onRtcAnswer(
219
+ remotePeerDescriptor: PeerDescriptor,
220
+ targetPeerDescriptor: PeerDescriptor,
221
+ description: string,
222
+ connectionId: string
223
+ ): void {
224
+ if (this.stopped || !isSamePeerDescriptor(targetPeerDescriptor, this.ownPeerDescriptor!)) {
225
+ return
226
+ }
227
+ const peerKey = keyFromPeerDescriptor(remotePeerDescriptor)
228
+ const connection = this.ongoingConnectAttempts.get(peerKey)?.getWebRtcConnection()
229
+ if (!connection) {
230
+ return
231
+ } else if (connection.connectionId.toString() !== connectionId) {
232
+ logger.trace(`Ignoring RTC answer due to connectionId mismatch`)
233
+ return
234
+ }
235
+ connection.setRemoteDescription(description, 'answer')
236
+ }
237
+
238
+ private onConnectionRequest(targetPeerDescriptor: PeerDescriptor): void {
239
+ if (this.stopped || this.ongoingConnectAttempts.has(keyFromPeerDescriptor(targetPeerDescriptor))) {
240
+ return
241
+ }
242
+ const managedConnection = this.connect(targetPeerDescriptor)
243
+ managedConnection.setPeerDescriptor(targetPeerDescriptor)
244
+
245
+ this.incomingConnectionCallback(managedConnection)
246
+ }
247
+ private onRemoteCandidate(
248
+ remotePeerDescriptor: PeerDescriptor,
249
+ targetPeerDescriptor: PeerDescriptor,
250
+ candidate: string,
251
+ mid: string,
252
+ connectionId: string
253
+ ): void {
254
+ if (this.stopped || !isSamePeerDescriptor(targetPeerDescriptor, this.ownPeerDescriptor!)) {
255
+ return
256
+ }
257
+ const peerKey = keyFromPeerDescriptor(remotePeerDescriptor)
258
+ const connection = this.ongoingConnectAttempts.get(peerKey)?.getWebRtcConnection()
259
+
260
+ if (!connection) {
261
+ return
262
+ } else if (connection.connectionId.toString() !== connectionId) {
263
+ logger.trace(`Ignoring remote candidate due to connectionId mismatch`)
264
+ return
265
+ } else if (this.isIceCandidateAllowed(candidate)) {
266
+ connection.addRemoteCandidate(candidate, mid)
267
+ }
268
+ }
269
+
270
+ public async stop(): Promise<void> {
271
+ logger.trace('stop()')
272
+ this.stopped = true
273
+
274
+ const attempts = Array.from(this.ongoingConnectAttempts.values())
275
+ await Promise.allSettled(attempts.map((conn) => conn.close('OTHER')))
276
+
277
+ this.rpcCommunicator.stop()
278
+ }
279
+
280
+ public isOffering(targetPeerDescriptor: PeerDescriptor): boolean {
281
+ const myId = peerIdFromPeerDescriptor(this.ownPeerDescriptor!)
282
+ const theirId = peerIdFromPeerDescriptor(targetPeerDescriptor)
283
+ return myId.hasSmallerHashThan(theirId)
284
+ }
285
+
286
+ // IWebRTCConnector implementation
287
+ async requestConnection(request: WebRtcConnectionRequest, _context: ServerCallContext): Promise<Empty> {
288
+ this.onConnectionRequest(request.requester!)
289
+ return {}
290
+ }
291
+
292
+ async rtcOffer(request: RtcOffer, _context: ServerCallContext): Promise<Empty> {
293
+ this.onRtcOffer(request.requester!, request.target!, request.description, request.connectionId)
294
+ return {}
295
+ }
296
+
297
+ async rtcAnswer(request: RtcAnswer, _context: ServerCallContext): Promise<Empty> {
298
+ this.onRtcAnswer(request.requester!, request.target!, request.description, request.connectionId)
299
+ return {}
300
+ }
301
+
302
+ async iceCandidate(request: IceCandidate, _context: ServerCallContext): Promise<Empty> {
303
+ this.onRemoteCandidate(request.requester!, request.target!, request.candidate, request.mid, request.connectionId)
304
+ return {}
305
+ }
306
+ }
@@ -0,0 +1,15 @@
1
+ import { IceServer } from './WebRtcConnector'
2
+
3
+ export function iceServerAsString({ url, port, username, password, tcp }: IceServer): string {
4
+ const [protocol, hostname] = url.split(':')
5
+ if (hostname === undefined) {
6
+ throw new Error(`invalid stun/turn format: ${url}`)
7
+ }
8
+ if (username === undefined && password === undefined) {
9
+ return `${protocol}:${hostname}:${port}`
10
+ }
11
+ if (username !== undefined && password !== undefined) {
12
+ return `${protocol}:${username}:${password}@${hostname}:${port}${tcp ? '?transport=tcp' : ''}`
13
+ }
14
+ throw new Error(`username (${username}) and password (${password}) must be supplied together`)
15
+ }
@@ -0,0 +1,118 @@
1
+ import { IConnection, ConnectionID, ConnectionType, ConnectionEvents } from '../IConnection'
2
+ import { w3cwebsocket as WebSocket, ICloseEvent, IMessageEvent } from 'websocket'
3
+ import EventEmitter from 'eventemitter3'
4
+ import { Logger } from '@streamr/utils'
5
+ import { DisconnectionType } from '../../transport/ITransport'
6
+
7
+ const logger = new Logger(module)
8
+
9
+ const BINARY_TYPE = 'arraybuffer'
10
+
11
+ export class ClientWebSocket extends EventEmitter<ConnectionEvents> implements IConnection {
12
+ public readonly connectionId: ConnectionID
13
+ private socket?: WebSocket
14
+ public connectionType = ConnectionType.WEBSOCKET_CLIENT
15
+
16
+ private stopped = false
17
+
18
+ constructor() {
19
+ super()
20
+ this.connectionId = new ConnectionID()
21
+ }
22
+
23
+ public connect(address: string): void {
24
+ if (!this.stopped) {
25
+ this.socket = new WebSocket(address)
26
+ this.socket.binaryType = BINARY_TYPE
27
+
28
+ this.socket.onerror = (error: Error) => {
29
+ if (!this.stopped) {
30
+ logger.trace('WebSocket Client error: ' + error)
31
+ this.emit('error', error.name)
32
+ }
33
+ }
34
+
35
+ this.socket.onopen = () => {
36
+ if (!this.stopped) {
37
+ logger.trace('WebSocket Client Connected')
38
+ if (this.socket && this.socket.readyState === this.socket.OPEN) {
39
+ this.emit('connected')
40
+ }
41
+ }
42
+ }
43
+
44
+ this.socket.onclose = (event: ICloseEvent) => {
45
+ if (!this.stopped) {
46
+ logger.trace('Websocket Closed')
47
+ this.doDisconnect('OTHER', event.code, event.reason)
48
+ }
49
+ }
50
+
51
+ this.socket.onmessage = (message: IMessageEvent) => {
52
+ if (!this.stopped) {
53
+ if (typeof message.data === 'string') {
54
+ logger.debug('Received string: \'' + message.data + '\'')
55
+ } else {
56
+ this.emit('data', new Uint8Array(message.data))
57
+ }
58
+ }
59
+ }
60
+ } else {
61
+ logger.debug('Tried to connect() a stopped connection')
62
+ }
63
+ }
64
+
65
+ private doDisconnect(disconnectionType: DisconnectionType, code?: number, reason?: string) {
66
+ this.stopped = true
67
+ this.stopListening()
68
+ this.socket = undefined
69
+
70
+ this.emit('disconnected', disconnectionType, code, reason)
71
+ this.removeAllListeners()
72
+ }
73
+
74
+ public send(data: Uint8Array): void {
75
+ if (!this.stopped) {
76
+ if (this.socket && this.socket.readyState === this.socket.OPEN) {
77
+ logger.trace(`Sending data with size ${data.byteLength}`)
78
+ this.socket?.send(data.buffer)
79
+ } else {
80
+ logger.warn('Tried to send data on a non-open connection')
81
+ }
82
+ } else {
83
+ logger.debug('Tried to send() on stopped connection')
84
+ }
85
+ }
86
+
87
+ public async close(): Promise<void> {
88
+ if (!this.stopped) {
89
+ logger.trace(`Closing socket for connection ${this.connectionId.toString()}`)
90
+ this.socket?.close()
91
+ } else {
92
+ logger.debug('Tried to close() a stopped connection')
93
+ }
94
+ }
95
+
96
+ private stopListening(): void {
97
+ if (this.socket) {
98
+ this.socket.onopen = undefined as unknown as (() => void)
99
+ this.socket.onclose = undefined as unknown as (() => void)
100
+ this.socket.onerror = undefined as unknown as (() => void)
101
+ this.socket.onmessage = undefined as unknown as (() => void)
102
+ }
103
+ }
104
+
105
+ public destroy(): void {
106
+ if (!this.stopped) {
107
+ this.removeAllListeners()
108
+ if (this.socket) {
109
+ this.stopListening()
110
+ this.socket.close()
111
+ this.socket = undefined
112
+ }
113
+ this.stopped = true
114
+ } else {
115
+ logger.debug('Tried to destroy() a stopped connection')
116
+ }
117
+ }
118
+ }
@@ -0,0 +1,49 @@
1
+ import {
2
+ PeerDescriptor,
3
+ WebSocketConnectionRequest
4
+ } from '../../proto/packages/dht/protos/DhtRpc'
5
+ import { IWebSocketConnectorServiceClient } from '../../proto/packages/dht/protos/DhtRpc.client'
6
+ import { DhtRpcOptions } from '../../rpc-protocol/DhtRpcOptions'
7
+ import { Logger } from '@streamr/utils'
8
+ import * as Err from '../../helpers/errors'
9
+ import { ProtoRpcClient } from '@streamr/proto-rpc'
10
+
11
+ const logger = new Logger(module)
12
+
13
+ export class RemoteWebSocketConnector {
14
+
15
+ private peerDescriptor: PeerDescriptor
16
+ private client: ProtoRpcClient<IWebSocketConnectorServiceClient>
17
+
18
+ constructor(peerDescriptor: PeerDescriptor, client: ProtoRpcClient<IWebSocketConnectorServiceClient>) {
19
+ this.peerDescriptor = peerDescriptor
20
+ this.client = client
21
+ }
22
+
23
+ async requestConnection(sourceDescriptor: PeerDescriptor, ip: string, port: number): Promise<boolean> {
24
+ logger.trace(`Requesting WebSocket connection from ${this.peerDescriptor.kademliaId.toString()}`)
25
+ const request: WebSocketConnectionRequest = {
26
+ target: this.peerDescriptor,
27
+ requester: sourceDescriptor,
28
+ ip,
29
+ port
30
+ }
31
+ const options: DhtRpcOptions = {
32
+ sourceDescriptor: sourceDescriptor as PeerDescriptor,
33
+ targetDescriptor: this.peerDescriptor as PeerDescriptor
34
+ }
35
+ try {
36
+ const res = await this.client.requestConnection(request, options)
37
+
38
+ if (res.reason) {
39
+ logger.debug('WebSocketConnectionRequest Rejected', {
40
+ stack: new Err.WebSocketConnectionRequestRejected(res.reason).stack
41
+ })
42
+ }
43
+ return res.accepted
44
+ } catch (err) {
45
+ logger.debug(new Err.WebSocketConnectionRequestRejected('WebSocketConnectionRequest rejected', err).stack!)
46
+ return false
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,119 @@
1
+ import EventEmitter from 'eventemitter3'
2
+ import { IConnection, ConnectionID, ConnectionEvents, ConnectionType } from '../IConnection'
3
+ import { connection as WsConnection } from 'websocket'
4
+ import { Logger } from '@streamr/utils'
5
+ import { DisconnectionType } from '../../transport/ITransport'
6
+ import { Url } from 'url'
7
+
8
+ const logger = new Logger(module)
9
+
10
+ // NodeJsBuffer is global defined in preload.js of Karma
11
+ // It is used to make Karma/Electron tests to use the NodeJS
12
+ // implementation of Buffer instead of the browser polyfill
13
+
14
+ declare let NodeJsBuffer: BufferConstructor
15
+
16
+ enum MessageType {
17
+ UTF8 = 'utf8',
18
+ BINARY = 'binary'
19
+ }
20
+
21
+ export class ServerWebSocket extends EventEmitter<ConnectionEvents> implements IConnection {
22
+
23
+ public readonly connectionId: ConnectionID
24
+ public readonly connectionType = ConnectionType.WEBSOCKET_SERVER
25
+ public readonly resourceURL: Url
26
+ private socket?: WsConnection
27
+ private stopped = false
28
+
29
+ constructor(socket: WsConnection, resourceURL: Url) {
30
+ super()
31
+
32
+ this.resourceURL = resourceURL
33
+ this.connectionId = new ConnectionID()
34
+
35
+ socket.on('message', (message) => {
36
+ if (!this.stopped) {
37
+ logger.trace('ServerWebSocket::onMessage')
38
+ if (message.type === MessageType.UTF8) {
39
+ logger.debug('Received string Message: ' + message.utf8Data)
40
+ } else if (message.type === MessageType.BINARY) {
41
+ logger.trace('Received Binary Message of ' + message.binaryData.length + ' bytes')
42
+ this.emit('data',
43
+ new Uint8Array(message.binaryData.buffer, message.binaryData.byteOffset,
44
+ message.binaryData.byteLength / Uint8Array.BYTES_PER_ELEMENT))
45
+ }
46
+ }
47
+ })
48
+ socket.on('close', (reasonCode, description) => {
49
+ if (!this.stopped) {
50
+ logger.trace(' Peer ' + socket.remoteAddress + ' disconnected.')
51
+ this.doDisconnect('OTHER', reasonCode, description)
52
+ }
53
+ })
54
+
55
+ socket.on('error', (error) => {
56
+ if (!this.stopped) {
57
+ this.emit('error', error.name)
58
+ }
59
+ })
60
+
61
+ this.socket = socket
62
+ }
63
+
64
+ private doDisconnect(disconnectionType: DisconnectionType, reasonCode: number, description: string): void {
65
+ this.stopped = true
66
+ this.socket?.removeAllListeners()
67
+ this.socket = undefined
68
+
69
+ this.emit('disconnected', disconnectionType, reasonCode, description)
70
+ this.removeAllListeners()
71
+ }
72
+
73
+ public send(data: Uint8Array): void {
74
+ // If in an Karma / Electron test, use the NodeJS implementation
75
+ // of Buffer instead of the browser polyfill
76
+
77
+ if (!this.stopped && this.socket) {
78
+ if (typeof NodeJsBuffer !== 'undefined') {
79
+ this.socket.sendBytes(NodeJsBuffer.from(data))
80
+ } else {
81
+ this.socket.sendBytes(Buffer.from(data))
82
+ }
83
+ } else {
84
+ logger.error('Tried to call send() on a stopped socket')
85
+ }
86
+
87
+ }
88
+
89
+ public async close(): Promise<void> {
90
+ if (!this.stopped) {
91
+ this.socket?.close()
92
+ } else {
93
+ logger.error('Tried to close a stopped connection')
94
+ }
95
+ }
96
+
97
+ public destroy(): void {
98
+ if (!this.stopped) {
99
+ this.removeAllListeners()
100
+ if (this.socket) {
101
+ this.socket.removeAllListeners()
102
+ this.socket.close()
103
+ this.socket = undefined
104
+ }
105
+ this.stopped = true
106
+ } else {
107
+ logger.error('Tried to destroy() a stopped connection')
108
+ }
109
+ }
110
+
111
+ public getRemoteAddress(): string {
112
+ if (!this.stopped && this.socket) {
113
+ return this.socket.remoteAddress
114
+ } else {
115
+ logger.error('Tried to get the remoteAddress of a stopped connection')
116
+ return ''
117
+ }
118
+ }
119
+ }