@streamr/dht 100.2.4-beta.0 → 100.2.4

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 (151) hide show
  1. package/dist/package.json +8 -9
  2. package/dist/src/connection/ConnectionManager.d.ts +2 -1
  3. package/dist/src/connection/ConnectionManager.js +2 -10
  4. package/dist/src/connection/ConnectionManager.js.map +1 -1
  5. package/dist/src/connection/ConnectionsView.d.ts +7 -0
  6. package/dist/src/connection/ConnectionsView.js +3 -0
  7. package/dist/src/connection/ConnectionsView.js.map +1 -0
  8. package/dist/src/connection/ConnectorFacade.d.ts +2 -1
  9. package/dist/src/connection/ConnectorFacade.js +5 -4
  10. package/dist/src/connection/ConnectorFacade.js.map +1 -1
  11. package/dist/src/connection/connectivityRequestHandler.d.ts +2 -1
  12. package/dist/src/connection/connectivityRequestHandler.js +12 -5
  13. package/dist/src/connection/connectivityRequestHandler.js.map +1 -1
  14. package/dist/src/connection/{ManagedWebrtcConnection.d.ts → webrtc/ManagedWebrtcConnection.d.ts} +3 -3
  15. package/dist/src/connection/{ManagedWebrtcConnection.js → webrtc/ManagedWebrtcConnection.js} +2 -2
  16. package/dist/src/connection/webrtc/ManagedWebrtcConnection.js.map +1 -0
  17. package/dist/src/connection/webrtc/NodeWebrtcConnection.js +3 -26
  18. package/dist/src/connection/webrtc/NodeWebrtcConnection.js.map +1 -1
  19. package/dist/src/connection/webrtc/WebrtcConnector.js +1 -1
  20. package/dist/src/connection/webrtc/WebrtcConnector.js.map +1 -1
  21. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.d.ts +1 -1
  22. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js +1 -1
  23. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js.map +1 -1
  24. package/dist/src/connection/websocket/WebsocketConnector.d.ts +2 -0
  25. package/dist/src/connection/websocket/WebsocketConnector.js +21 -13
  26. package/dist/src/connection/websocket/WebsocketConnector.js.map +1 -1
  27. package/dist/src/connection/websocket/WebsocketServerConnection.d.ts +2 -1
  28. package/dist/src/connection/websocket/WebsocketServerConnection.js +4 -0
  29. package/dist/src/connection/websocket/WebsocketServerConnection.js.map +1 -1
  30. package/dist/src/dht/DhtNode.d.ts +14 -11
  31. package/dist/src/dht/DhtNode.js +74 -61
  32. package/dist/src/dht/DhtNode.js.map +1 -1
  33. package/dist/src/dht/DhtNodeRpcLocal.d.ts +3 -3
  34. package/dist/src/dht/DhtNodeRpcLocal.js +5 -2
  35. package/dist/src/dht/DhtNodeRpcLocal.js.map +1 -1
  36. package/dist/src/dht/PeerManager.d.ts +14 -14
  37. package/dist/src/dht/PeerManager.js +51 -42
  38. package/dist/src/dht/PeerManager.js.map +1 -1
  39. package/dist/src/dht/contact/ContactList.d.ts +1 -2
  40. package/dist/src/dht/contact/ContactList.js +1 -3
  41. package/dist/src/dht/contact/ContactList.js.map +1 -1
  42. package/dist/src/dht/contact/RandomContactList.d.ts +1 -1
  43. package/dist/src/dht/contact/RandomContactList.js +7 -4
  44. package/dist/src/dht/contact/RandomContactList.js.map +1 -1
  45. package/dist/src/dht/contact/getClosestNodes.d.ts +6 -0
  46. package/dist/src/dht/contact/{getClosestContacts.js → getClosestNodes.js} +7 -6
  47. package/dist/src/dht/contact/getClosestNodes.js.map +1 -0
  48. package/dist/src/dht/discovery/DiscoverySession.d.ts +4 -0
  49. package/dist/src/dht/discovery/DiscoverySession.js +27 -21
  50. package/dist/src/dht/discovery/DiscoverySession.js.map +1 -1
  51. package/dist/src/dht/discovery/PeerDiscovery.d.ts +8 -5
  52. package/dist/src/dht/discovery/PeerDiscovery.js +34 -24
  53. package/dist/src/dht/discovery/PeerDiscovery.js.map +1 -1
  54. package/dist/src/dht/discovery/RingDiscoverySession.d.ts +4 -4
  55. package/dist/src/dht/discovery/RingDiscoverySession.js +10 -19
  56. package/dist/src/dht/discovery/RingDiscoverySession.js.map +1 -1
  57. package/dist/src/dht/recursive-operation/RecursiveOperationManager.d.ts +2 -0
  58. package/dist/src/dht/recursive-operation/RecursiveOperationManager.js +3 -3
  59. package/dist/src/dht/recursive-operation/RecursiveOperationManager.js.map +1 -1
  60. package/dist/src/dht/store/StoreManager.d.ts +5 -6
  61. package/dist/src/dht/store/StoreManager.js +21 -76
  62. package/dist/src/dht/store/StoreManager.js.map +1 -1
  63. package/dist/src/dht/store/StoreRpcLocal.d.ts +5 -2
  64. package/dist/src/dht/store/StoreRpcLocal.js +22 -5
  65. package/dist/src/dht/store/StoreRpcLocal.js.map +1 -1
  66. package/dist/src/exports.d.ts +2 -1
  67. package/dist/src/exports.js.map +1 -1
  68. package/dist/src/helpers/version.d.ts +1 -1
  69. package/dist/src/helpers/version.js +1 -1
  70. package/dist/src/proto/google/protobuf/any.d.ts +8 -5
  71. package/dist/src/proto/google/protobuf/any.js.map +1 -1
  72. package/dist/src/proto/google/protobuf/empty.d.ts +0 -1
  73. package/dist/src/proto/google/protobuf/empty.js.map +1 -1
  74. package/dist/src/proto/google/protobuf/timestamp.d.ts +10 -1
  75. package/dist/src/proto/google/protobuf/timestamp.js.map +1 -1
  76. package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +8 -0
  77. package/dist/src/proto/packages/dht/protos/DhtRpc.js +3 -1
  78. package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
  79. package/dist/src/transport/ITransport.d.ts +0 -4
  80. package/dist/src/transport/ITransport.js.map +1 -1
  81. package/karma.config.js +2 -2
  82. package/package.json +8 -9
  83. package/protos/DhtRpc.proto +2 -0
  84. package/src/connection/ConnectionManager.ts +4 -10
  85. package/src/connection/ConnectionsView.ts +8 -0
  86. package/src/connection/ConnectorFacade.ts +7 -5
  87. package/src/connection/connectivityRequestHandler.ts +18 -5
  88. package/src/connection/{ManagedWebrtcConnection.ts → webrtc/ManagedWebrtcConnection.ts} +4 -4
  89. package/src/connection/webrtc/NodeWebrtcConnection.ts +3 -3
  90. package/src/connection/webrtc/WebrtcConnector.ts +1 -1
  91. package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +1 -1
  92. package/src/connection/websocket/WebsocketConnector.ts +26 -16
  93. package/src/connection/websocket/WebsocketServerConnection.ts +6 -1
  94. package/src/dht/DhtNode.ts +102 -74
  95. package/src/dht/DhtNodeRpcLocal.ts +12 -5
  96. package/src/dht/PeerManager.ts +58 -49
  97. package/src/dht/contact/ContactList.ts +1 -4
  98. package/src/dht/contact/RandomContactList.ts +7 -5
  99. package/src/dht/contact/{getClosestContacts.ts → getClosestNodes.ts} +8 -6
  100. package/src/dht/discovery/DiscoverySession.ts +34 -22
  101. package/src/dht/discovery/PeerDiscovery.ts +44 -30
  102. package/src/dht/discovery/RingDiscoverySession.ts +15 -29
  103. package/src/dht/recursive-operation/RecursiveOperationManager.ts +5 -3
  104. package/src/dht/store/StoreManager.ts +46 -84
  105. package/src/dht/store/StoreRpcLocal.ts +32 -9
  106. package/src/exports.ts +2 -1
  107. package/src/helpers/version.ts +1 -1
  108. package/src/proto/google/protobuf/any.ts +8 -5
  109. package/src/proto/google/protobuf/empty.ts +0 -1
  110. package/src/proto/google/protobuf/timestamp.ts +10 -1
  111. package/src/proto/packages/dht/protos/DhtRpc.ts +11 -1
  112. package/src/transport/ITransport.ts +0 -4
  113. package/test/benchmark/Find.test.ts +1 -1
  114. package/test/end-to-end/GeoIpLayer0.test.ts +55 -0
  115. package/test/end-to-end/Layer0-Layer1.test.ts +4 -4
  116. package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +11 -5
  117. package/test/end-to-end/Layer1-Scale-WebSocket.test.ts +7 -1
  118. package/test/end-to-end/Layer1-Scale-Webrtc.test.ts +11 -2
  119. package/test/integration/ConnectionLocking.test.ts +1 -1
  120. package/test/integration/ConnectionManager.test.ts +3 -3
  121. package/test/integration/ConnectivityChecking.test.ts +2 -2
  122. package/test/integration/DhtNode.test.ts +5 -20
  123. package/test/integration/GeoIpConnectivityChecking.test.ts +71 -0
  124. package/test/integration/Layer1-scale.test.ts +6 -6
  125. package/test/integration/RouteMessage.test.ts +4 -0
  126. package/test/integration/ScaleDownDht.test.ts +1 -1
  127. package/test/integration/SimultaneousConnections.test.ts +2 -2
  128. package/test/integration/WebrtcConnectionManagement.test.ts +1 -1
  129. package/test/integration/WebsocketConnectionManagement.test.ts +1 -1
  130. package/test/integration/rpc-connections-over-webrpc.test.ts +1 -1
  131. package/test/unit/AutoCertifierClientFacade.test.ts +1 -1
  132. package/test/unit/DiscoverySession.test.ts +4 -2
  133. package/test/unit/PeerManager.test.ts +45 -51
  134. package/test/unit/RandomContactList.test.ts +10 -0
  135. package/test/unit/RecursiveOperationManager.test.ts +4 -2
  136. package/test/unit/StoreManager.test.ts +42 -34
  137. package/test/unit/StoreRpcLocal.test.ts +167 -0
  138. package/test/unit/WebsocketConnector.test.ts +1 -1
  139. package/test/unit/connectivityRequestHandler.test.ts +1 -1
  140. package/test/unit/getClosestNodes.test.ts +30 -0
  141. package/test/utils/FakeTransport.ts +4 -2
  142. package/test/utils/mock/MockConnectionsView.ts +18 -0
  143. package/test/utils/mock/{Transport.ts → MockTransport.ts} +0 -15
  144. package/test/utils/utils.ts +4 -1
  145. package/tsconfig.jest.json +2 -1
  146. package/tsconfig.node.json +2 -1
  147. package/dist/src/connection/ManagedWebrtcConnection.js.map +0 -1
  148. package/dist/src/dht/contact/getClosestContacts.d.ts +0 -7
  149. package/dist/src/dht/contact/getClosestContacts.js.map +0 -1
  150. package/test/unit/getClosestContacts.test.ts +0 -28
  151. /package/test/utils/mock/{Router.ts → MockRouter.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamr/dht",
3
- "version": "100.2.4-beta.0",
3
+ "version": "100.2.4",
4
4
  "description": "Streamr Network DHT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,17 +29,18 @@
29
29
  "@js-sdsl/ordered-map": "^4.4.2",
30
30
  "@protobuf-ts/runtime": "^2.8.2",
31
31
  "@protobuf-ts/runtime-rpc": "^2.8.2",
32
- "@streamr/autocertifier-client": "100.2.4-beta.0",
33
- "@streamr/cdn-location": "100.2.4-beta.0",
34
- "@streamr/proto-rpc": "100.2.4-beta.0",
35
- "@streamr/utils": "100.2.4-beta.0",
32
+ "@streamr/autocertifier-client": "100.2.4",
33
+ "@streamr/cdn-location": "100.2.4",
34
+ "@streamr/geoip-location": "100.2.4",
35
+ "@streamr/proto-rpc": "100.2.4",
36
+ "@streamr/utils": "100.2.4",
36
37
  "eventemitter3": "^5.0.0",
37
38
  "heap": "^0.2.6",
38
39
  "ipaddr.js": "^2.0.1",
39
40
  "k-bucket": "^5.1.0",
40
41
  "lodash": "^4.17.21",
41
42
  "lru-cache": "10.2.0",
42
- "node-datachannel": "^0.4.3",
43
+ "node-datachannel": "^0.8.0",
43
44
  "querystring": "0.2.1",
44
45
  "uuid": "^9.0.1",
45
46
  "websocket": "^1.0.34",
@@ -47,15 +48,13 @@
47
48
  },
48
49
  "devDependencies": {
49
50
  "@streamr/browser-test-runner": "^0.0.1",
50
- "@streamr/test-utils": "100.2.4-beta.0",
51
- "@types/express": "^4.17.21",
51
+ "@streamr/test-utils": "100.2.4",
52
52
  "@types/heap": "^0.2.34",
53
53
  "@types/k-bucket": "^5.0.1",
54
54
  "@types/lodash": "^4.14.202",
55
55
  "@types/uuid": "^9.0.8",
56
56
  "@types/websocket": "^1.0.10",
57
57
  "@types/ws": "^8.5.10",
58
- "express": "^4.19.2",
59
58
  "jest-leak-detector": "^27.3.1",
60
59
  "patch-package": "^8.0.0",
61
60
  "ts-essentials": "^9.4.1",
@@ -215,6 +215,8 @@ message ConnectivityResponse {
215
215
  ConnectivityMethod websocket = 3;
216
216
  uint32 ipAddress = 4;
217
217
  string version = 5;
218
+ optional double latitude = 6;
219
+ optional double longitude = 7;
218
220
  }
219
221
 
220
222
  message HandshakeRequest {
@@ -24,6 +24,7 @@ import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
24
24
  import { ConnectionLockRpcLocal } from './ConnectionLockRpcLocal'
25
25
  import { DhtAddress, areEqualPeerDescriptors, getNodeIdFromPeerDescriptor } from '../identifiers'
26
26
  import { getOfferer } from '../helpers/offering'
27
+ import { ConnectionsView } from './ConnectionsView'
27
28
 
28
29
  export interface ConnectionManagerConfig {
29
30
  maxConnections?: number
@@ -93,7 +94,7 @@ export const getNodeIdOrUnknownFromPeerDescriptor = (peerDescriptor: PeerDescrip
93
94
  }
94
95
  }
95
96
 
96
- export class ConnectionManager extends EventEmitter<TransportEvents> implements ITransport, ConnectionLocker {
97
+ export class ConnectionManager extends EventEmitter<TransportEvents> implements ITransport, ConnectionsView, ConnectionLocker {
97
98
 
98
99
  private config: ConnectionManagerConfig
99
100
  private readonly metricsContext: MetricsContext
@@ -158,15 +159,8 @@ export class ConnectionManager extends EventEmitter<TransportEvents> implements
158
159
  maxSize: 100000, // TODO use config option or named constant?
159
160
  allowToContainReferenceId: false
160
161
  })
161
- this.connections.forEach((connection, key) => {
162
- // TODO: Investigate why multiple invalid WS client connections to the same
163
- // server with a different nodeId can remain in the this.connections map.
164
- // Seems to only happen if the ConnectionManager acting as client is not running a WS server itself.
165
- if (connection.getPeerDescriptor() !== undefined && !this.hasConnection(getNodeIdFromPeerDescriptor(connection.getPeerDescriptor()!))) {
166
- logger.trace(`Attempting to disconnect a hanging connection to ${getNodeIdFromPeerDescriptor(connection.getPeerDescriptor()!)}`)
167
- connection.close(false).catch(() => {})
168
- this.connections.delete(key)
169
- } else if (!this.locks.isLocked(connection.getNodeId()) && Date.now() - connection.getLastUsedTimestamp() > maxIdleTime) {
162
+ this.connections.forEach((connection) => {
163
+ if (!this.locks.isLocked(connection.getNodeId()) && Date.now() - connection.getLastUsedTimestamp() > maxIdleTime) {
170
164
  logger.trace('disconnecting in timeout interval: ' + getNodeIdOrUnknownFromPeerDescriptor(connection.getPeerDescriptor()))
171
165
  disconnectionCandidates.addContact(connection)
172
166
  }
@@ -0,0 +1,8 @@
1
+ import { DhtAddress } from '../identifiers'
2
+ import { PeerDescriptor } from '../proto/packages/dht/protos/DhtRpc'
3
+
4
+ export interface ConnectionsView {
5
+ getConnections: () => PeerDescriptor[]
6
+ getConnectionCount: () => number
7
+ hasConnection: (nodeId: DhtAddress) => boolean
8
+ }
@@ -44,7 +44,8 @@ export interface DefaultConnectorFacadeConfig {
44
44
  websocketServerEnableTls?: boolean
45
45
  autoCertifierUrl?: string
46
46
  autoCertifierConfigFile?: string
47
- createLocalPeerDescriptor: (connectivityResponse: ConnectivityResponse) => PeerDescriptor
47
+ geoIpDatabaseFolder?: string
48
+ createLocalPeerDescriptor: (connectivityResponse: ConnectivityResponse) => Promise<PeerDescriptor>
48
49
  }
49
50
 
50
51
  export class DefaultConnectorFacade implements ConnectorFacade {
@@ -76,7 +77,8 @@ export class DefaultConnectorFacade implements ConnectorFacade {
76
77
  autoCertifierUrl: this.config.autoCertifierUrl!,
77
78
  autoCertifierConfigFile: this.config.autoCertifierConfigFile!,
78
79
  autoCertifierTransport,
79
- maxMessageSize: this.config.maxMessageSize
80
+ maxMessageSize: this.config.maxMessageSize,
81
+ geoIpDatabaseFolder: this.config.geoIpDatabaseFolder
80
82
  }
81
83
  this.websocketConnector = new WebsocketConnector(webSocketConnectorConfig)
82
84
  logger.trace(`Creating WebRtcConnectorRpcLocal`)
@@ -98,13 +100,13 @@ export class DefaultConnectorFacade implements ConnectorFacade {
98
100
  // LocalPeerDescriptor could be stored in one place and passed from there to the connectors
99
101
  const temporarilySelfSigned = (!this.config.tlsCertificate && this.config.websocketServerEnableTls === true)
100
102
  const connectivityResponse = await this.websocketConnector.checkConnectivity(temporarilySelfSigned)
101
- const localPeerDescriptor = this.config.createLocalPeerDescriptor(connectivityResponse)
103
+ const localPeerDescriptor = await this.config.createLocalPeerDescriptor(connectivityResponse)
102
104
  this.setLocalPeerDescriptor(localPeerDescriptor)
103
105
  if (localPeerDescriptor.websocket && !this.config.tlsCertificate && this.config.websocketServerEnableTls) {
104
106
  try {
105
107
  await this.websocketConnector.autoCertify()
106
108
  const connectivityResponse = await this.websocketConnector.checkConnectivity(false)
107
- const autocertifiedLocalPeerDescriptor = this.config.createLocalPeerDescriptor(connectivityResponse)
109
+ const autocertifiedLocalPeerDescriptor = await this.config.createLocalPeerDescriptor(connectivityResponse)
108
110
  if (autocertifiedLocalPeerDescriptor.websocket !== undefined) {
109
111
  this.setLocalPeerDescriptor(autocertifiedLocalPeerDescriptor)
110
112
  } else {
@@ -135,7 +137,7 @@ export class DefaultConnectorFacade implements ConnectorFacade {
135
137
  this.websocketConnector = new WebsocketConnector(webSocketConnectorConfig)
136
138
  await this.websocketConnector.start()
137
139
  const connectivityResponse = await this.websocketConnector.checkConnectivity(false)
138
- const localPeerDescriptor = this.config.createLocalPeerDescriptor(connectivityResponse)
140
+ const localPeerDescriptor = await this.config.createLocalPeerDescriptor(connectivityResponse)
139
141
  this.setLocalPeerDescriptor(localPeerDescriptor)
140
142
  }
141
143
 
@@ -11,12 +11,13 @@ import { IConnection } from './IConnection'
11
11
  import { WebsocketServerConnection } from './websocket/WebsocketServerConnection'
12
12
  import { connectivityMethodToWebsocketUrl } from './websocket/WebsocketConnector'
13
13
  import { LOCAL_PROTOCOL_VERSION } from '../helpers/version'
14
+ import { GeoIpLocator } from '@streamr/geoip-location'
14
15
 
15
16
  export const DISABLE_CONNECTIVITY_PROBE = 0
16
17
 
17
18
  const logger = new Logger(module)
18
19
 
19
- export const attachConnectivityRequestHandler = (connectionToListenTo: WebsocketServerConnection): void => {
20
+ export const attachConnectivityRequestHandler = (connectionToListenTo: WebsocketServerConnection, geoIpLocator?: GeoIpLocator): void => {
20
21
  connectionToListenTo.on('data', async (data: Uint8Array) => {
21
22
  logger.trace('server received data')
22
23
  try {
@@ -24,7 +25,8 @@ export const attachConnectivityRequestHandler = (connectionToListenTo: Websocket
24
25
  if (message.body.oneofKind === 'connectivityRequest') {
25
26
  logger.trace('ConnectivityRequest received: ' + JSON.stringify(Message.toJson(message)))
26
27
  try {
27
- await handleIncomingConnectivityRequest(connectionToListenTo, message.body.connectivityRequest)
28
+ await handleIncomingConnectivityRequest(connectionToListenTo,
29
+ message.body.connectivityRequest, geoIpLocator)
28
30
  logger.trace('handleIncomingConnectivityRequest ok')
29
31
  } catch (err1) {
30
32
  logger.error('handleIncomingConnectivityRequest', { err: err1 })
@@ -36,9 +38,13 @@ export const attachConnectivityRequestHandler = (connectionToListenTo: Websocket
36
38
  })
37
39
  }
38
40
 
39
- const handleIncomingConnectivityRequest = async (connection: WebsocketServerConnection, connectivityRequest: ConnectivityRequest): Promise<void> => {
40
- const host = connectivityRequest.host ?? connection.remoteIpAddress
41
- const ipAddress = connection.remoteIpAddress
41
+ const handleIncomingConnectivityRequest = async (
42
+ connection: WebsocketServerConnection,
43
+ connectivityRequest: ConnectivityRequest,
44
+ geoIpLocator?: GeoIpLocator
45
+ ): Promise<void> => {
46
+ const host = connectivityRequest.host ?? connection.getRemoteIpAddress()
47
+ const ipAddress = connection.getRemoteIpAddress()
42
48
  let connectivityResponse: ConnectivityResponse
43
49
  if (connectivityRequest.port !== DISABLE_CONNECTIVITY_PROBE) {
44
50
  connectivityResponse = await connectivityProbe(connectivityRequest, ipAddress, host)
@@ -51,6 +57,13 @@ const handleIncomingConnectivityRequest = async (connection: WebsocketServerConn
51
57
  version: LOCAL_PROTOCOL_VERSION
52
58
  }
53
59
  }
60
+ if (geoIpLocator !== undefined) {
61
+ const location = geoIpLocator.lookup(ipAddress)
62
+ if (location !== undefined) {
63
+ connectivityResponse.latitude = location.latitude
64
+ connectivityResponse.longitude = location.longitude
65
+ }
66
+ }
54
67
  const msg: Message = {
55
68
  serviceId: CONNECTIVITY_CHECKER_SERVICE_ID,
56
69
  messageId: v4(),
@@ -1,7 +1,7 @@
1
- import { PeerDescriptor } from '../proto/packages/dht/protos/DhtRpc'
2
- import { ConnectionType } from './IConnection'
3
- import { ManagedConnection } from './ManagedConnection'
4
- import { NodeWebrtcConnection } from './webrtc/NodeWebrtcConnection'
1
+ import { PeerDescriptor } from '../../proto/packages/dht/protos/DhtRpc'
2
+ import { ConnectionType } from '../IConnection'
3
+ import { ManagedConnection } from '../ManagedConnection'
4
+ import { NodeWebrtcConnection } from './NodeWebrtcConnection'
5
5
 
6
6
  export class ManagedWebrtcConnection extends ManagedConnection {
7
7
 
@@ -2,7 +2,7 @@ import { IWebrtcConnection, WebrtcConnectionEvents } from './IWebrtcConnection'
2
2
  import { ConnectionType, IConnection, ConnectionID, ConnectionEvents } from '../IConnection'
3
3
  import { PeerDescriptor } from '../../proto/packages/dht/protos/DhtRpc'
4
4
  import EventEmitter from 'eventemitter3'
5
- import nodeDatachannel, { DataChannel, DescriptionType, PeerConnection } from 'node-datachannel'
5
+ import { DataChannel, DescriptionType, PeerConnection, cleanup, initLogger } from 'node-datachannel'
6
6
  import { Logger } from '@streamr/utils'
7
7
  import { IllegalRtcPeerConnectionState } from '../../helpers/errors'
8
8
  import { iceServerAsString } from './iceServerAsString'
@@ -16,7 +16,7 @@ const logger = new Logger(module)
16
16
  export const WEBRTC_CLEANUP = new class {
17
17
  // eslint-disable-next-line class-methods-use-this
18
18
  cleanUp(): void {
19
- nodeDatachannel.cleanup()
19
+ cleanup()
20
20
  }
21
21
  }
22
22
 
@@ -42,7 +42,7 @@ enum RtcPeerConnectionStateEnum {
42
42
  new = 'new'
43
43
  }
44
44
 
45
- nodeDatachannel.initLogger('Fatal')
45
+ initLogger('Fatal')
46
46
 
47
47
  type RtcPeerConnectionState = keyof typeof RtcPeerConnectionStateEnum
48
48
 
@@ -9,7 +9,7 @@ import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicat
9
9
  import { NodeWebrtcConnection } from './NodeWebrtcConnection'
10
10
  import { WebrtcConnectorRpcRemote } from './WebrtcConnectorRpcRemote'
11
11
  import { WebrtcConnectorRpcClient } from '../../proto/packages/dht/protos/DhtRpc.client'
12
- import { ManagedWebrtcConnection } from '../ManagedWebrtcConnection'
12
+ import { ManagedWebrtcConnection } from './ManagedWebrtcConnection'
13
13
  import { Logger } from '@streamr/utils'
14
14
  import * as Err from '../../helpers/errors'
15
15
  import { ManagedConnection } from '../ManagedConnection'
@@ -14,7 +14,7 @@ import { IWebrtcConnectorRpc } from '../../proto/packages/dht/protos/DhtRpc.serv
14
14
  import { DhtCallContext } from '../../rpc-protocol/DhtCallContext'
15
15
  import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicator'
16
16
  import { ManagedConnection } from '../ManagedConnection'
17
- import { ManagedWebrtcConnection } from '../ManagedWebrtcConnection'
17
+ import { ManagedWebrtcConnection } from './ManagedWebrtcConnection'
18
18
  import { NodeWebrtcConnection } from './NodeWebrtcConnection'
19
19
  import { WebrtcConnectorRpcRemote } from './WebrtcConnectorRpcRemote'
20
20
  import { DhtAddress, getNodeIdFromPeerDescriptor } from '../../identifiers'
@@ -30,6 +30,7 @@ import * as Err from '../../helpers/errors'
30
30
  import { Empty } from '../../proto/google/protobuf/empty'
31
31
  import { DhtAddress, areEqualPeerDescriptors, getNodeIdFromPeerDescriptor } from '../../identifiers'
32
32
  import { LOCAL_PROTOCOL_VERSION, isMaybeSupportedVersion } from '../../helpers/version'
33
+ import { GeoIpLocator } from '@streamr/geoip-location'
33
34
 
34
35
  const logger = new Logger(module)
35
36
 
@@ -53,6 +54,7 @@ export interface WebsocketConnectorConfig {
53
54
  autoCertifierUrl: string
54
55
  autoCertifierConfigFile: string
55
56
  serverEnableTls: boolean
57
+ geoIpDatabaseFolder?: string
56
58
  }
57
59
 
58
60
  export class WebsocketConnector {
@@ -60,6 +62,7 @@ export class WebsocketConnector {
60
62
  private static readonly WEBSOCKET_CONNECTOR_SERVICE_ID = 'system/websocket-connector'
61
63
  private readonly rpcCommunicator: ListeningRpcCommunicator
62
64
  private readonly websocketServer?: WebsocketServer
65
+ private geoIpLocator?: GeoIpLocator
63
66
  private readonly ongoingConnectRequests: Map<DhtAddress, ManagedConnection> = new Map()
64
67
  private host?: string
65
68
  private autoCertifierClient?: AutoCertifierClientFacade
@@ -87,17 +90,10 @@ export class WebsocketConnector {
87
90
  private registerLocalRpcMethods(config: WebsocketConnectorConfig) {
88
91
  const rpcLocal = new WebsocketConnectorRpcLocal({
89
92
  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
- },
93
+ hasConnection: (nodeId: DhtAddress): boolean => (this.connectingConnections.has(nodeId)
94
+ || this.ongoingConnectRequests.has(nodeId)
95
+ || config.hasConnection(nodeId))
96
+ ,
101
97
  onNewConnection: (connection: ManagedConnection) => config.onNewConnection(connection),
102
98
  abortSignal: this.abortController.signal
103
99
  })
@@ -145,9 +141,9 @@ export class WebsocketConnector {
145
141
  const serverSocket = connection as unknown as WebsocketServerConnection
146
142
  const query = queryString.parse(serverSocket.resourceURL.query as string ?? '')
147
143
  const action = query.action as (Action | undefined)
148
- logger.trace('WebSocket client connected', { action, remoteAddress: serverSocket.remoteIpAddress })
144
+ logger.trace('WebSocket client connected', { action, remoteAddress: serverSocket.getRemoteIpAddress() })
149
145
  if (action === 'connectivityRequest') {
150
- attachConnectivityRequestHandler(serverSocket)
146
+ attachConnectivityRequestHandler(serverSocket, this.geoIpLocator)
151
147
  } else if (action === 'connectivityProbe') {
152
148
  // no-op
153
149
  } else {
@@ -163,6 +159,17 @@ export class WebsocketConnector {
163
159
  }
164
160
  }
165
161
  })
162
+
163
+ if (this.config.geoIpDatabaseFolder) {
164
+ const geoIpLocator = new GeoIpLocator(this.config.geoIpDatabaseFolder)
165
+ try {
166
+ await geoIpLocator.start()
167
+ this.geoIpLocator = geoIpLocator
168
+ } catch (err) {
169
+ logger.error('Failed to start GeoIpLocator', { err })
170
+ }
171
+ }
172
+
166
173
  const port = await this.websocketServer.start()
167
174
  this.selectedPort = port
168
175
  }
@@ -183,9 +190,9 @@ export class WebsocketConnector {
183
190
  return {
184
191
  host: this.host!,
185
192
  natType: NatType.OPEN_INTERNET,
186
- websocket: {
187
- host: this.host!,
188
- port: this.selectedPort!,
193
+ websocket: {
194
+ host: this.host!,
195
+ port: this.selectedPort!,
189
196
  tls: this.config.tlsCertificate !== undefined
190
197
  },
191
198
  // TODO: Resolve the given host name or or use as is if IP was given.
@@ -307,6 +314,8 @@ export class WebsocketConnector {
307
314
  const ongoingConnectRequest = this.ongoingConnectRequests.get(nodeId)!
308
315
  if (!isMaybeSupportedVersion(remoteVersion)) {
309
316
  ongoingConnectRequest.rejectHandshake(HandshakeError.UNSUPPORTED_VERSION)
317
+ } else if (targetPeerDescriptor && !areEqualPeerDescriptors(this.localPeerDescriptor!, targetPeerDescriptor)) {
318
+ ongoingConnectRequest.rejectHandshake(HandshakeError.INVALID_TARGET_PEER_DESCRIPTOR)
310
319
  } else {
311
320
  ongoingConnectRequest.attachImplementation(websocketServerConnection)
312
321
  ongoingConnectRequest.acceptHandshake()
@@ -347,5 +356,6 @@ export class WebsocketConnector {
347
356
  const attempts = Array.from(this.connectingConnections.values())
348
357
  await Promise.allSettled(attempts.map((conn) => conn.close(false)))
349
358
  await this.websocketServer?.stop()
359
+ await this.geoIpLocator?.stop()
350
360
  }
351
361
  }
@@ -13,7 +13,7 @@ export class WebsocketServerConnection extends EventEmitter<ConnectionEvents> im
13
13
  public readonly connectionId: ConnectionID
14
14
  public readonly connectionType = ConnectionType.WEBSOCKET_SERVER
15
15
  public readonly resourceURL: Url
16
- public readonly remoteIpAddress: string
16
+ private readonly remoteIpAddress: string
17
17
  private socket?: WebSocket
18
18
  private stopped = false
19
19
 
@@ -34,6 +34,11 @@ export class WebsocketServerConnection extends EventEmitter<ConnectionEvents> im
34
34
 
35
35
  this.socket = socket
36
36
  }
37
+
38
+ // use a getter to make it possible to mock the value in tests
39
+ public getRemoteIpAddress(): string {
40
+ return this.remoteIpAddress
41
+ }
37
42
 
38
43
  private onMessage(message: WebSocket.RawData, isBinary: boolean): void {
39
44
  if (!isBinary) {