@streamr/dht 100.0.0-testnet-three.6 → 100.1.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 (215) hide show
  1. package/README.md +1 -1
  2. package/dist/package.json +12 -8
  3. package/dist/src/connection/ConnectionLockRpcLocal.d.ts +1 -1
  4. package/dist/src/connection/ConnectionLockRpcRemote.d.ts +1 -1
  5. package/dist/src/connection/ConnectionLockRpcRemote.js +1 -1
  6. package/dist/src/connection/ConnectionLockRpcRemote.js.map +1 -1
  7. package/dist/src/connection/{ConnectionLockHandler.d.ts → ConnectionLockStates.d.ts} +3 -3
  8. package/dist/src/connection/{ConnectionLockHandler.js → ConnectionLockStates.js} +17 -9
  9. package/dist/src/connection/ConnectionLockStates.js.map +1 -0
  10. package/dist/src/connection/ConnectionManager.d.ts +9 -7
  11. package/dist/src/connection/ConnectionManager.js +16 -18
  12. package/dist/src/connection/ConnectionManager.js.map +1 -1
  13. package/dist/src/connection/ConnectorFacade.js +1 -1
  14. package/dist/src/connection/ConnectorFacade.js.map +1 -1
  15. package/dist/src/connection/Handshaker.js +6 -13
  16. package/dist/src/connection/Handshaker.js.map +1 -1
  17. package/dist/src/connection/ManagedConnection.d.ts +2 -2
  18. package/dist/src/connection/ManagedConnection.js +8 -8
  19. package/dist/src/connection/ManagedConnection.js.map +1 -1
  20. package/dist/src/connection/connectivityChecker.d.ts +1 -1
  21. package/dist/src/connection/connectivityChecker.js +8 -8
  22. package/dist/src/connection/connectivityChecker.js.map +1 -1
  23. package/dist/src/connection/connectivityRequestHandler.d.ts +2 -2
  24. package/dist/src/connection/connectivityRequestHandler.js +10 -11
  25. package/dist/src/connection/connectivityRequestHandler.js.map +1 -1
  26. package/dist/src/connection/webrtc/WebrtcConnector.d.ts +1 -0
  27. package/dist/src/connection/webrtc/WebrtcConnector.js +13 -8
  28. package/dist/src/connection/webrtc/WebrtcConnector.js.map +1 -1
  29. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.d.ts +2 -0
  30. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js +4 -6
  31. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js.map +1 -1
  32. package/dist/src/connection/websocket/AbstractWebsocketClientConnection.d.ts +28 -0
  33. package/dist/src/connection/websocket/{ClientWebsocket.js → AbstractWebsocketClientConnection.js} +42 -68
  34. package/dist/src/connection/websocket/AbstractWebsocketClientConnection.js.map +1 -0
  35. package/dist/src/connection/websocket/NodeWebsocketClientConnection.d.ts +7 -0
  36. package/dist/src/connection/websocket/NodeWebsocketClientConnection.js +39 -0
  37. package/dist/src/connection/websocket/NodeWebsocketClientConnection.js.map +1 -0
  38. package/dist/src/connection/websocket/WebsocketConnector.js +26 -23
  39. package/dist/src/connection/websocket/WebsocketConnector.js.map +1 -1
  40. package/dist/src/connection/websocket/WebsocketServer.js +25 -35
  41. package/dist/src/connection/websocket/WebsocketServer.js.map +1 -1
  42. package/dist/src/connection/websocket/{ServerWebsocket.d.ts → WebsocketServerConnection.d.ts} +4 -5
  43. package/dist/src/connection/websocket/{ServerWebsocket.js → WebsocketServerConnection.js} +18 -51
  44. package/dist/src/connection/websocket/WebsocketServerConnection.js.map +1 -0
  45. package/dist/src/dht/DhtNode.d.ts +15 -8
  46. package/dist/src/dht/DhtNode.js +62 -31
  47. package/dist/src/dht/DhtNode.js.map +1 -1
  48. package/dist/src/dht/DhtNodeRpcLocal.d.ts +5 -1
  49. package/dist/src/dht/DhtNodeRpcLocal.js +10 -0
  50. package/dist/src/dht/DhtNodeRpcLocal.js.map +1 -1
  51. package/dist/src/dht/DhtNodeRpcRemote.d.ts +3 -0
  52. package/dist/src/dht/DhtNodeRpcRemote.js +16 -1
  53. package/dist/src/dht/DhtNodeRpcRemote.js.map +1 -1
  54. package/dist/src/dht/ExternalApiRpcLocal.d.ts +2 -2
  55. package/dist/src/dht/ExternalApiRpcLocal.js +3 -3
  56. package/dist/src/dht/ExternalApiRpcLocal.js.map +1 -1
  57. package/dist/src/dht/ExternalApiRpcRemote.d.ts +1 -1
  58. package/dist/src/dht/ExternalApiRpcRemote.js +2 -2
  59. package/dist/src/dht/ExternalApiRpcRemote.js.map +1 -1
  60. package/dist/src/dht/PeerManager.d.ts +15 -3
  61. package/dist/src/dht/PeerManager.js +54 -40
  62. package/dist/src/dht/PeerManager.js.map +1 -1
  63. package/dist/src/dht/contact/RingContactList.d.ts +31 -0
  64. package/dist/src/dht/contact/RingContactList.js +133 -0
  65. package/dist/src/dht/contact/RingContactList.js.map +1 -0
  66. package/dist/src/dht/contact/SortedContactList.d.ts +2 -1
  67. package/dist/src/dht/contact/SortedContactList.js +19 -17
  68. package/dist/src/dht/contact/SortedContactList.js.map +1 -1
  69. package/dist/src/dht/contact/ringIdentifiers.d.ts +16 -0
  70. package/dist/src/dht/contact/ringIdentifiers.js +54 -0
  71. package/dist/src/dht/contact/ringIdentifiers.js.map +1 -0
  72. package/dist/src/dht/discovery/DiscoverySession.js +3 -1
  73. package/dist/src/dht/discovery/DiscoverySession.js.map +1 -1
  74. package/dist/src/dht/discovery/PeerDiscovery.d.ts +6 -2
  75. package/dist/src/dht/discovery/PeerDiscovery.js +41 -4
  76. package/dist/src/dht/discovery/PeerDiscovery.js.map +1 -1
  77. package/dist/src/dht/discovery/RingDiscoverySession.d.ts +29 -0
  78. package/dist/src/dht/discovery/RingDiscoverySession.js +125 -0
  79. package/dist/src/dht/discovery/RingDiscoverySession.js.map +1 -0
  80. package/dist/src/dht/recursive-operation/RecursiveOperationManager.js +1 -1
  81. package/dist/src/dht/recursive-operation/RecursiveOperationManager.js.map +1 -1
  82. package/dist/src/dht/recursive-operation/RecursiveOperationRpcRemote.js +1 -1
  83. package/dist/src/dht/recursive-operation/RecursiveOperationRpcRemote.js.map +1 -1
  84. package/dist/src/dht/recursive-operation/RecursiveOperationSession.js +0 -1
  85. package/dist/src/dht/recursive-operation/RecursiveOperationSession.js.map +1 -1
  86. package/dist/src/dht/routing/Router.d.ts +0 -1
  87. package/dist/src/dht/routing/Router.js +0 -1
  88. package/dist/src/dht/routing/Router.js.map +1 -1
  89. package/dist/src/dht/routing/RouterRpcLocal.d.ts +0 -1
  90. package/dist/src/dht/routing/RouterRpcLocal.js.map +1 -1
  91. package/dist/src/dht/routing/RouterRpcRemote.js +2 -2
  92. package/dist/src/dht/routing/RouterRpcRemote.js.map +1 -1
  93. package/dist/src/dht/routing/RoutingSession.js +2 -2
  94. package/dist/src/dht/routing/RoutingSession.js.map +1 -1
  95. package/dist/src/dht/store/LocalDataStore.js +2 -2
  96. package/dist/src/dht/store/LocalDataStore.js.map +1 -1
  97. package/dist/src/dht/store/StoreManager.js +2 -2
  98. package/dist/src/dht/store/StoreManager.js.map +1 -1
  99. package/dist/src/exports.d.ts +3 -2
  100. package/dist/src/exports.js +3 -3
  101. package/dist/src/exports.js.map +1 -1
  102. package/dist/src/helpers/createPeerDescriptor.d.ts +1 -1
  103. package/dist/src/helpers/createPeerDescriptor.js +2 -1
  104. package/dist/src/helpers/createPeerDescriptor.js.map +1 -1
  105. package/dist/src/helpers/version.d.ts +6 -0
  106. package/dist/src/helpers/version.js +38 -0
  107. package/dist/src/helpers/version.js.map +1 -0
  108. package/dist/src/proto/packages/dht/protos/DhtRpc.client.d.ts +16 -6
  109. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js +11 -4
  110. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +1 -1
  111. package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +98 -87
  112. package/dist/src/proto/packages/dht/protos/DhtRpc.js +45 -49
  113. package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
  114. package/dist/src/proto/packages/dht/protos/DhtRpc.server.d.ts +10 -4
  115. package/dist/src/transport/RoutingRpcCommunicator.js +0 -2
  116. package/dist/src/transport/RoutingRpcCommunicator.js.map +1 -1
  117. package/karma.config.js +4 -1
  118. package/package.json +12 -8
  119. package/protos/DhtRpc.proto +21 -21
  120. package/src/connection/ConnectionLockRpcLocal.ts +1 -1
  121. package/src/connection/ConnectionLockRpcRemote.ts +2 -2
  122. package/src/connection/{ConnectionLockHandler.ts → ConnectionLockStates.ts} +14 -6
  123. package/src/connection/ConnectionManager.ts +21 -22
  124. package/src/connection/ConnectorFacade.ts +1 -2
  125. package/src/connection/Handshaker.ts +7 -15
  126. package/src/connection/ManagedConnection.ts +8 -8
  127. package/src/connection/connectivityChecker.ts +9 -10
  128. package/src/connection/connectivityRequestHandler.ts +16 -16
  129. package/src/connection/webrtc/BrowserWebrtcConnection.ts +18 -0
  130. package/src/connection/webrtc/NodeWebrtcConnection.ts +1 -1
  131. package/src/connection/webrtc/WebrtcConnector.ts +14 -8
  132. package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +5 -5
  133. package/src/connection/websocket/{ClientWebsocket.ts → AbstractWebsocketClientConnection.ts} +57 -70
  134. package/src/connection/websocket/BrowserWebsocketClientConnection.ts +44 -0
  135. package/src/connection/websocket/NodeWebsocketClientConnection.ts +39 -0
  136. package/src/connection/websocket/WebsocketConnector.ts +27 -28
  137. package/src/connection/websocket/WebsocketServer.ts +27 -42
  138. package/src/connection/websocket/{ServerWebsocket.ts → WebsocketServerConnection.ts} +15 -56
  139. package/src/dht/DhtNode.ts +85 -50
  140. package/src/dht/DhtNodeRpcLocal.ts +16 -0
  141. package/src/dht/DhtNodeRpcRemote.ts +19 -1
  142. package/src/dht/ExternalApiRpcLocal.ts +5 -5
  143. package/src/dht/ExternalApiRpcRemote.ts +4 -4
  144. package/src/dht/PeerManager.ts +70 -44
  145. package/src/dht/contact/RingContactList.ts +151 -0
  146. package/src/dht/contact/SortedContactList.ts +22 -18
  147. package/src/dht/contact/ringIdentifiers.ts +62 -0
  148. package/src/dht/discovery/DiscoverySession.ts +3 -1
  149. package/src/dht/discovery/PeerDiscovery.ts +45 -6
  150. package/src/dht/discovery/RingDiscoverySession.ts +162 -0
  151. package/src/dht/recursive-operation/RecursiveOperationManager.ts +1 -1
  152. package/src/dht/recursive-operation/RecursiveOperationRpcRemote.ts +1 -1
  153. package/src/dht/recursive-operation/RecursiveOperationSession.ts +1 -3
  154. package/src/dht/routing/Router.ts +0 -2
  155. package/src/dht/routing/RouterRpcLocal.ts +0 -1
  156. package/src/dht/routing/RouterRpcRemote.ts +2 -2
  157. package/src/dht/routing/RoutingSession.ts +2 -2
  158. package/src/dht/store/LocalDataStore.ts +1 -1
  159. package/src/dht/store/StoreManager.ts +2 -2
  160. package/src/exports.ts +3 -2
  161. package/src/helpers/createPeerDescriptor.ts +2 -1
  162. package/src/helpers/version.ts +32 -0
  163. package/src/proto/packages/dht/protos/DhtRpc.client.ts +22 -9
  164. package/src/proto/packages/dht/protos/DhtRpc.server.ts +10 -4
  165. package/src/proto/packages/dht/protos/DhtRpc.ts +122 -100
  166. package/src/transport/RoutingRpcCommunicator.ts +1 -2
  167. package/test/benchmark/Find.test.ts +3 -4
  168. package/test/benchmark/KademliaCorrectness.test.ts +14 -8
  169. package/test/benchmark/RingCorrectness.test.ts +157 -0
  170. package/test/benchmark/WebsocketServerMemoryLeak.test.ts +2 -2
  171. package/test/benchmark/hybrid-network-simulation/RingContactList.test.ts +72 -0
  172. package/test/data/generateGroundTruthData.ts +2 -2
  173. package/test/end-to-end/memory-leak.test.ts +1 -2
  174. package/test/integration/ConnectionManager.test.ts +28 -10
  175. package/test/integration/ConnectivityChecking.test.ts +3 -15
  176. package/test/integration/DhtNodeExternalAPI.test.ts +6 -6
  177. package/test/integration/Find.test.ts +6 -6
  178. package/test/integration/Layer1-scale.test.ts +0 -1
  179. package/test/integration/ReplicateData.test.ts +4 -4
  180. package/test/integration/RouteMessage.test.ts +1 -6
  181. package/test/integration/RouterRpcRemote.test.ts +1 -3
  182. package/test/integration/SimultaneousConnections.test.ts +9 -10
  183. package/test/integration/Store.test.ts +4 -4
  184. package/test/integration/StoreAndDelete.test.ts +5 -5
  185. package/test/integration/StoreOnDhtWithThreeNodes.test.ts +5 -5
  186. package/test/integration/StoreOnDhtWithTwoNodes.test.ts +3 -3
  187. package/test/integration/WebrtcConnectionManagement.test.ts +3 -9
  188. package/test/integration/Websocket.test.ts +2 -2
  189. package/test/integration/WebsocketConnectionManagement.test.ts +1 -6
  190. package/test/integration/rpc-connections-over-webrpc.test.ts +1 -2
  191. package/test/unit/PeerManager.test.ts +44 -10
  192. package/test/unit/RecursiveOperationManager.test.ts +14 -8
  193. package/test/unit/RecursiveOperationSession.test.ts +1 -1
  194. package/test/unit/Router.test.ts +0 -3
  195. package/test/unit/RoutingSession.test.ts +1 -2
  196. package/test/unit/connectivityRequestHandler.test.ts +5 -9
  197. package/test/unit/createPeerDescriptor.test.ts +12 -6
  198. package/test/unit/version.test.ts +18 -0
  199. package/test/utils/utils.ts +60 -47
  200. package/tsconfig.browser.json +2 -1
  201. package/tsconfig.jest.json +4 -2
  202. package/tsconfig.node.json +4 -2
  203. package/dist/src/connection/ConnectionLockHandler.js.map +0 -1
  204. package/dist/src/connection/websocket/ClientWebsocket.d.ts +0 -17
  205. package/dist/src/connection/websocket/ClientWebsocket.js.map +0 -1
  206. package/dist/src/connection/websocket/ServerWebsocket.js.map +0 -1
  207. package/dist/src/helpers/MapWithTtl.d.ts +0 -14
  208. package/dist/src/helpers/MapWithTtl.js +0 -60
  209. package/dist/src/helpers/MapWithTtl.js.map +0 -1
  210. package/dist/src/helpers/versionCompatibility.d.ts +0 -2
  211. package/dist/src/helpers/versionCompatibility.js +0 -18
  212. package/dist/src/helpers/versionCompatibility.js.map +0 -1
  213. package/src/helpers/MapWithTtl.ts +0 -71
  214. package/src/helpers/versionCompatibility.ts +0 -13
  215. package/test/unit/versionCompatibility.test.ts +0 -16
@@ -1,4 +1,4 @@
1
- import { ClientWebsocket } from './ClientWebsocket'
1
+ import { WebsocketClientConnection } from './NodeWebsocketClientConnection'
2
2
  import { IConnection, ConnectionType } from '../IConnection'
3
3
  import { ITransport } from '../../transport/ITransport'
4
4
  import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicator'
@@ -17,10 +17,10 @@ import { ManagedConnection } from '../ManagedConnection'
17
17
  import { WebsocketServer } from './WebsocketServer'
18
18
  import { sendConnectivityRequest } from '../connectivityChecker'
19
19
  import { NatType, PortRange, TlsCertificate } from '../ConnectionManager'
20
- import { ServerWebsocket } from './ServerWebsocket'
20
+ import { WebsocketServerConnection } from './WebsocketServerConnection'
21
21
  import { Handshaker } from '../Handshaker'
22
- import { ParsedUrlQuery } from 'querystring'
23
- import { range, sample } from 'lodash'
22
+ import queryString from 'querystring'
23
+ import { shuffle } from 'lodash'
24
24
  import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
25
25
  import { expectedConnectionType } from '../../helpers/Connectivity'
26
26
  import { WebsocketServerStartError } from '../../helpers/errors'
@@ -29,8 +29,7 @@ import { DISABLE_CONNECTIVITY_PROBE, attachConnectivityRequestHandler } from '..
29
29
  import * as Err from '../../helpers/errors'
30
30
  import { Empty } from '../../proto/google/protobuf/empty'
31
31
  import { DhtAddress, areEqualPeerDescriptors, getNodeIdFromPeerDescriptor } from '../../identifiers'
32
- import { version as localVersion } from '../../../package.json'
33
- import { isCompatibleVersion } from '../../helpers/versionCompatibility'
32
+ import { LOCAL_PROTOCOL_VERSION, isMaybeSupportedVersion } from '../../helpers/version'
34
33
 
35
34
  const logger = new Logger(module)
36
35
 
@@ -143,10 +142,10 @@ export class WebsocketConnector {
143
142
  public async start(): Promise<void> {
144
143
  if (!this.abortController.signal.aborted && this.websocketServer) {
145
144
  this.websocketServer.on('connected', (connection: IConnection) => {
146
- const serverSocket = connection as unknown as ServerWebsocket
147
- const query = serverSocket.resourceURL.query as unknown as (ParsedUrlQuery | null)
148
- const action = query?.action as (Action | undefined)
149
- 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 })
150
149
  if (action === 'connectivityRequest') {
151
150
  attachConnectivityRequestHandler(serverSocket)
152
151
  } else if (action === 'connectivityProbe') {
@@ -175,7 +174,7 @@ export class WebsocketConnector {
175
174
  host: '127.0.0.1',
176
175
  natType: NatType.UNKNOWN,
177
176
  ipAddress: ipv4ToNumber('127.0.0.1'),
178
- version: localVersion
177
+ version: LOCAL_PROTOCOL_VERSION
179
178
  }
180
179
  }
181
180
  if (!this.config.entrypoints || this.config.entrypoints.length === 0) {
@@ -190,11 +189,12 @@ export class WebsocketConnector {
190
189
  },
191
190
  // TODO: Resolve the given host name or or use as is if IP was given.
192
191
  ipAddress: ipv4ToNumber('127.0.0.1'),
193
- version: localVersion
192
+ version: LOCAL_PROTOCOL_VERSION
194
193
  }
195
194
  }
196
- for (const reattempt of range(ENTRY_POINT_CONNECTION_ATTEMPTS)) {
197
- const entryPoint = sample(this.config.entrypoints)!
195
+ const shuffledEntrypoints = shuffle(this.config.entrypoints)
196
+ while (shuffledEntrypoints.length > 0 && !this.abortController.signal.aborted) {
197
+ const entryPoint = shuffledEntrypoints[0]
198
198
  try {
199
199
  // Do real connectivity checking
200
200
  const connectivityRequest = {
@@ -204,17 +204,16 @@ export class WebsocketConnector {
204
204
  selfSigned
205
205
  }
206
206
  if (!this.abortController.signal.aborted) {
207
- return await sendConnectivityRequest(connectivityRequest, entryPoint, localVersion)
207
+ return await sendConnectivityRequest(connectivityRequest, entryPoint)
208
208
  } else {
209
209
  throw new Err.ConnectionFailed('ConnectivityChecker is destroyed')
210
210
  }
211
211
  } catch (err) {
212
- if (reattempt < ENTRY_POINT_CONNECTION_ATTEMPTS) {
213
- const error = `Failed to connect to entrypoint with id ${getNodeIdFromPeerDescriptor(entryPoint)} `
214
- + `and URL ${connectivityMethodToWebsocketUrl(entryPoint.websocket!)}`
215
- logger.error(error, { error: err })
216
- await wait(2000)
217
- }
212
+ const error = `Failed to connect to entrypoint with id ${getNodeIdFromPeerDescriptor(entryPoint)} `
213
+ + `and URL ${connectivityMethodToWebsocketUrl(entryPoint.websocket!)}`
214
+ logger.error(error, { err })
215
+ shuffledEntrypoints.shift()
216
+ await wait(2000, this.abortController.signal)
218
217
  }
219
218
  }
220
219
  throw new WebsocketServerStartError(`Failed to connect to the entrypoints after ${ENTRY_POINT_CONNECTION_ATTEMPTS} attempts`)
@@ -235,7 +234,7 @@ export class WebsocketConnector {
235
234
  if (this.localPeerDescriptor!.websocket && !targetPeerDescriptor.websocket) {
236
235
  return this.requestConnectionFromPeer(this.localPeerDescriptor!, targetPeerDescriptor)
237
236
  } else {
238
- const socket = new ClientWebsocket()
237
+ const socket = new WebsocketClientConnection()
239
238
 
240
239
  const url = connectivityMethodToWebsocketUrl(targetPeerDescriptor.websocket!)
241
240
 
@@ -299,17 +298,17 @@ export class WebsocketConnector {
299
298
 
300
299
  private onServerSocketHandshakeRequest(
301
300
  sourcePeerDescriptor: PeerDescriptor,
302
- serverWebsocket: IConnection,
303
- sourceVersion: string,
301
+ websocketServerConnection: IConnection,
302
+ remoteVersion: string,
304
303
  targetPeerDescriptor?: PeerDescriptor
305
304
  ) {
306
305
  const nodeId = getNodeIdFromPeerDescriptor(sourcePeerDescriptor)
307
306
  if (this.ongoingConnectRequests.has(nodeId)) {
308
307
  const ongoingConnectRequest = this.ongoingConnectRequests.get(nodeId)!
309
- if (!isCompatibleVersion(sourceVersion, localVersion)) {
308
+ if (!isMaybeSupportedVersion(remoteVersion)) {
310
309
  ongoingConnectRequest.rejectHandshake(HandshakeError.UNSUPPORTED_VERSION)
311
310
  } else {
312
- ongoingConnectRequest.attachImplementation(serverWebsocket)
311
+ ongoingConnectRequest.attachImplementation(websocketServerConnection)
313
312
  ongoingConnectRequest.acceptHandshake()
314
313
  }
315
314
  this.ongoingConnectRequests.delete(nodeId)
@@ -318,11 +317,11 @@ export class WebsocketConnector {
318
317
  this.localPeerDescriptor!,
319
318
  ConnectionType.WEBSOCKET_SERVER,
320
319
  undefined,
321
- serverWebsocket,
320
+ websocketServerConnection,
322
321
  targetPeerDescriptor
323
322
  )
324
323
  managedConnection.setRemotePeerDescriptor(sourcePeerDescriptor)
325
- if (!isCompatibleVersion(sourceVersion, localVersion)) {
324
+ if (!isMaybeSupportedVersion(remoteVersion)) {
326
325
  managedConnection.rejectHandshake(HandshakeError.UNSUPPORTED_VERSION)
327
326
  } else if (targetPeerDescriptor && !areEqualPeerDescriptors(this.localPeerDescriptor!, targetPeerDescriptor)) {
328
327
  managedConnection.rejectHandshake(HandshakeError.INVALID_TARGET_PEER_DESCRIPTOR)
@@ -1,8 +1,8 @@
1
1
  import { createServer as createHttpServer, Server as HttpServer, IncomingMessage, ServerResponse } from 'http'
2
2
  import { createServer as createHttpsServer, Server as HttpsServer } from 'https'
3
3
  import EventEmitter from 'eventemitter3'
4
- import { server as WsServer } from 'websocket'
5
- import { ServerWebsocket } from './ServerWebsocket'
4
+ import WebSocket from 'ws'
5
+ import { WebsocketServerConnection } from './WebsocketServerConnection'
6
6
  import { ConnectionSourceEvents } from '../IConnectionSource'
7
7
  import { Logger, asAbortable } from '@streamr/utils'
8
8
  import { createSelfSignedCertificate } from '@streamr/autocertifier-client'
@@ -11,16 +11,10 @@ import { PortRange, TlsCertificate } from '../ConnectionManager'
11
11
  import { range } from 'lodash'
12
12
  import fs from 'fs'
13
13
  import { v4 as uuid } from 'uuid'
14
+ import { parse } from 'url'
14
15
 
15
16
  const logger = new Logger(module)
16
17
 
17
- // NodeJsWsServer is declared as a global in test-browser Electron tests
18
- // in preload.js using "window.NodeJsWsServer = require('websocket').server".
19
- // This is done in order to use the real nodejs websocket server in tests
20
- // instead of a dummy polyfill.
21
-
22
- declare class NodeJsWsServer extends WsServer { }
23
-
24
18
  interface WebsocketServerConfig {
25
19
  portRange: PortRange
26
20
  enableTls: boolean
@@ -31,7 +25,7 @@ interface WebsocketServerConfig {
31
25
  export class WebsocketServer extends EventEmitter<ConnectionSourceEvents> {
32
26
 
33
27
  private httpServer?: HttpServer | HttpsServer
34
- private wsServer?: WsServer
28
+ private wsServer?: WebSocket.Server
35
29
  private readonly abortController = new AbortController()
36
30
  private readonly config: WebsocketServerConfig
37
31
 
@@ -88,28 +82,26 @@ export class WebsocketServer extends EventEmitter<ConnectionSourceEvents> {
88
82
  return true
89
83
  }
90
84
 
91
- this.wsServer = this.createWsServer(this.httpServer)
85
+ this.wsServer = this.createWsServer()
92
86
 
93
- this.wsServer.on('request', (request) => {
87
+ this.wsServer.on('connection', (ws: WebSocket, request: IncomingMessage) => {
88
+ logger.trace(`New connection from ${request.socket.remoteAddress}`)
94
89
  if (!originIsAllowed()) {
95
90
  // Make sure we only accept requests from an allowed origin
96
- request.reject()
97
- logger.trace('IConnection from origin ' + request.origin + ' rejected.')
91
+ ws.close()
92
+ logger.trace('IConnection from origin ' + request.headers.origin + ' rejected.')
98
93
  return
99
94
  }
100
-
101
- let connection
102
- try {
103
- connection = request.accept(undefined, request.origin)
104
- logger.trace('Connection accepted.', { remoteAddress: request.remoteAddress })
105
- } catch (err) {
106
- logger.debug('Accepting websocket connection failed', { remoteAddress: request.remoteAddress, err })
107
- }
95
+ this.emit('connected', new WebsocketServerConnection(ws, parse(request.url!), request.socket.remoteAddress!))
96
+ })
108
97
 
109
- if (connection) {
110
- this.emit('connected', new ServerWebsocket(connection, request.resourceURL))
111
- }
98
+ this.httpServer.on('upgrade', (request, socket, head) => {
99
+ logger.trace('Received upgrade request for ' + request.url)
100
+ this.wsServer!.handleUpgrade(request, socket, head, (ws: WebSocket) => {
101
+ this.wsServer!.emit('connection', ws, request)
102
+ })
112
103
  })
104
+
113
105
  this.httpServer.once('error', (err: Error) => {
114
106
  reject(new WebsocketServerStartError('Starting Websocket server failed', err))
115
107
  })
@@ -139,7 +131,10 @@ export class WebsocketServer extends EventEmitter<ConnectionSourceEvents> {
139
131
  this.abortController.abort()
140
132
  this.removeAllListeners()
141
133
  return new Promise((resolve, _reject) => {
142
- this.wsServer?.shutDown()
134
+ this.wsServer!.close()
135
+ for (const ws of this.wsServer!.clients) {
136
+ ws.terminate()
137
+ }
143
138
  this.httpServer?.once('close', () => {
144
139
  // removeAllListeners is maybe not needed?
145
140
  this.httpServer?.removeAllListeners()
@@ -155,21 +150,11 @@ export class WebsocketServer extends EventEmitter<ConnectionSourceEvents> {
155
150
  })
156
151
  }
157
152
 
158
- private createWsServer(httpServer: HttpServer | HttpsServer): WsServer {
159
- const maxReceivedMessageSize = this.config.maxMessageSize ?? 1048576
160
- // Use the real nodejs WebSocket server in Electron tests
161
- if (typeof NodeJsWsServer !== 'undefined') {
162
- return new NodeJsWsServer({
163
- httpServer,
164
- autoAcceptConnections: false,
165
- maxReceivedMessageSize
166
- })
167
- } else {
168
- return this.wsServer = new WsServer({
169
- httpServer,
170
- autoAcceptConnections: false,
171
- maxReceivedMessageSize
172
- })
173
- }
153
+ private createWsServer(): WebSocket.Server {
154
+ const maxPayload = this.config.maxMessageSize ?? 1048576
155
+ return this.wsServer = new WebSocket.Server({
156
+ noServer: true,
157
+ maxPayload
158
+ })
174
159
  }
175
160
  }
@@ -1,33 +1,23 @@
1
1
  import EventEmitter from 'eventemitter3'
2
2
  import { IConnection, ConnectionID, ConnectionEvents, ConnectionType } from '../IConnection'
3
- import { Message, connection as WsConnection } from 'websocket'
3
+ import WebSocket from 'ws'
4
4
  import { Logger } from '@streamr/utils'
5
5
  import { Url } from 'url'
6
- import { CUSTOM_GOING_AWAY, GOING_AWAY } from './ClientWebsocket'
6
+ import { CUSTOM_GOING_AWAY, GOING_AWAY } from './AbstractWebsocketClientConnection'
7
7
  import { createRandomConnectionId } from '../Connection'
8
8
 
9
9
  const logger = new Logger(module)
10
10
 
11
- // NodeJsBuffer is global defined in preload.js of Karma
12
- // It is used to make Karma/Electron tests to use the NodeJS
13
- // implementation of Buffer instead of the browser polyfill
14
-
15
- declare let NodeJsBuffer: BufferConstructor
16
-
17
- enum MessageType {
18
- UTF8 = 'utf8',
19
- BINARY = 'binary'
20
- }
21
-
22
- export class ServerWebsocket extends EventEmitter<ConnectionEvents> implements IConnection {
11
+ export class WebsocketServerConnection extends EventEmitter<ConnectionEvents> implements IConnection {
23
12
 
24
13
  public readonly connectionId: ConnectionID
25
14
  public readonly connectionType = ConnectionType.WEBSOCKET_SERVER
26
15
  public readonly resourceURL: Url
27
- private socket?: WsConnection
16
+ public readonly remoteIpAddress: string
17
+ private socket?: WebSocket
28
18
  private stopped = false
29
19
 
30
- constructor(socket: WsConnection, resourceURL: Url) {
20
+ constructor(socket: WebSocket, resourceURL: Url, remoteAddress: string) {
31
21
  super()
32
22
 
33
23
  this.onMessage = this.onMessage.bind(this)
@@ -36,6 +26,7 @@ export class ServerWebsocket extends EventEmitter<ConnectionEvents> implements I
36
26
 
37
27
  this.resourceURL = resourceURL
38
28
  this.connectionId = createRandomConnectionId()
29
+ this.remoteIpAddress = remoteAddress
39
30
 
40
31
  socket.on('message', this.onMessage)
41
32
  socket.on('close', this.onClose)
@@ -44,20 +35,17 @@ export class ServerWebsocket extends EventEmitter<ConnectionEvents> implements I
44
35
  this.socket = socket
45
36
  }
46
37
 
47
- private onMessage(message: Message): void {
48
- logger.trace('ServerWebsocket::onMessage')
49
- if (message.type === MessageType.UTF8) {
50
- logger.debug('Received string Message: ' + message.utf8Data)
51
- } else if (message.type === MessageType.BINARY) {
52
- logger.trace('Received Binary Message of ' + message.binaryData.length + ' bytes')
53
- this.emit('data',
54
- new Uint8Array(message.binaryData.buffer, message.binaryData.byteOffset,
55
- message.binaryData.byteLength / Uint8Array.BYTES_PER_ELEMENT))
38
+ private onMessage(message: WebSocket.RawData, isBinary: boolean): void {
39
+ if (!isBinary) {
40
+ logger.trace('Received string Message')
41
+ } else {
42
+ logger.trace('Websocket server received Message')
43
+ this.emit('data', new Uint8Array(message as Buffer))
56
44
  }
57
45
  }
58
46
 
59
47
  private onClose(reasonCode: number, description: string): void {
60
- logger.trace('Peer ' + this.socket?.remoteAddress + ' disconnected.')
48
+ logger.trace('Peer ' + this.remoteIpAddress + ' disconnected.')
61
49
  this.doDisconnect(reasonCode, description)
62
50
  }
63
51
 
@@ -80,16 +68,9 @@ export class ServerWebsocket extends EventEmitter<ConnectionEvents> implements I
80
68
  }
81
69
 
82
70
  public send(data: Uint8Array): void {
83
- // If in an Karma / Electron test, use the NodeJS implementation
84
- // of Buffer instead of the browser polyfill
85
-
86
71
  // TODO: no need to check this.socket as it is always defined when stopped is false?
87
72
  if (!this.stopped && this.socket) {
88
- if (typeof NodeJsBuffer !== 'undefined') {
89
- this.socket.sendBytes(NodeJsBuffer.from(data))
90
- } else {
91
- this.socket.sendBytes(Buffer.from(data))
92
- }
73
+ this.socket.send(data, { binary: true })
93
74
  } else {
94
75
  logger.debug('Tried to call send() on a stopped socket')
95
76
  }
@@ -120,26 +101,4 @@ export class ServerWebsocket extends EventEmitter<ConnectionEvents> implements I
120
101
  logger.debug('Tried to destroy() a stopped connection')
121
102
  }
122
103
  }
123
-
124
- public getRemoteAddress(): string {
125
- // TODO: no need to check this.socket as it is always defined when stopped is false?
126
- if (!this.stopped && this.socket) {
127
- return this.socket.remoteAddress
128
- } else {
129
- // TODO throw
130
- logger.error('Tried to get the remoteAddress of a stopped connection')
131
- return ''
132
- }
133
- }
134
-
135
- public getRemoteIp(): string {
136
- // TODO: no need to check this.socket as it is always defined when stopped is false?
137
- if (!this.stopped && this.socket) {
138
- return this.socket.socket.remoteAddress!
139
- } else {
140
- // TODO throw
141
- logger.error('Tried to get the remoteAddress of a stopped connection')
142
- return ''
143
- }
144
- }
145
104
  }