@streamr/dht 100.2.4-beta.0 → 100.2.5-beta.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.
- package/dist/package.json +8 -9
- package/dist/src/connection/ConnectionManager.d.ts +2 -1
- package/dist/src/connection/ConnectionManager.js +2 -10
- package/dist/src/connection/ConnectionManager.js.map +1 -1
- package/dist/src/connection/ConnectionsView.d.ts +7 -0
- package/dist/src/connection/ConnectionsView.js +3 -0
- package/dist/src/connection/ConnectionsView.js.map +1 -0
- package/dist/src/connection/ConnectorFacade.d.ts +2 -1
- package/dist/src/connection/ConnectorFacade.js +5 -4
- package/dist/src/connection/ConnectorFacade.js.map +1 -1
- package/dist/src/connection/connectivityChecker.d.ts +3 -3
- package/dist/src/connection/connectivityChecker.js +3 -3
- package/dist/src/connection/connectivityChecker.js.map +1 -1
- package/dist/src/connection/connectivityRequestHandler.d.ts +2 -1
- package/dist/src/connection/connectivityRequestHandler.js +13 -6
- package/dist/src/connection/connectivityRequestHandler.js.map +1 -1
- package/dist/src/connection/{ManagedWebrtcConnection.d.ts → webrtc/ManagedWebrtcConnection.d.ts} +3 -3
- package/dist/src/connection/{ManagedWebrtcConnection.js → webrtc/ManagedWebrtcConnection.js} +2 -2
- package/dist/src/connection/webrtc/ManagedWebrtcConnection.js.map +1 -0
- package/dist/src/connection/webrtc/NodeWebrtcConnection.js +3 -26
- package/dist/src/connection/webrtc/NodeWebrtcConnection.js.map +1 -1
- package/dist/src/connection/webrtc/WebrtcConnector.js +1 -1
- package/dist/src/connection/webrtc/WebrtcConnector.js.map +1 -1
- package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.d.ts +1 -1
- package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js +1 -1
- package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js.map +1 -1
- package/dist/src/connection/websocket/AbstractWebsocketClientConnection.d.ts +1 -1
- package/dist/src/connection/websocket/WebsocketConnector.d.ts +3 -1
- package/dist/src/connection/websocket/WebsocketConnector.js +26 -18
- package/dist/src/connection/websocket/WebsocketConnector.js.map +1 -1
- package/dist/src/connection/websocket/WebsocketServerConnection.d.ts +2 -1
- package/dist/src/connection/websocket/WebsocketServerConnection.js +4 -0
- package/dist/src/connection/websocket/WebsocketServerConnection.js.map +1 -1
- package/dist/src/dht/DhtNode.d.ts +14 -11
- package/dist/src/dht/DhtNode.js +74 -61
- package/dist/src/dht/DhtNode.js.map +1 -1
- package/dist/src/dht/DhtNodeRpcLocal.d.ts +3 -3
- package/dist/src/dht/DhtNodeRpcLocal.js +5 -2
- package/dist/src/dht/DhtNodeRpcLocal.js.map +1 -1
- package/dist/src/dht/PeerManager.d.ts +14 -14
- package/dist/src/dht/PeerManager.js +51 -42
- package/dist/src/dht/PeerManager.js.map +1 -1
- package/dist/src/dht/contact/ContactList.d.ts +1 -2
- package/dist/src/dht/contact/ContactList.js +1 -3
- package/dist/src/dht/contact/ContactList.js.map +1 -1
- package/dist/src/dht/contact/RandomContactList.d.ts +1 -1
- package/dist/src/dht/contact/RandomContactList.js +7 -4
- package/dist/src/dht/contact/RandomContactList.js.map +1 -1
- package/dist/src/dht/contact/getClosestNodes.d.ts +6 -0
- package/dist/src/dht/contact/{getClosestContacts.js → getClosestNodes.js} +7 -6
- package/dist/src/dht/contact/getClosestNodes.js.map +1 -0
- package/dist/src/dht/discovery/DiscoverySession.d.ts +4 -0
- package/dist/src/dht/discovery/DiscoverySession.js +27 -21
- package/dist/src/dht/discovery/DiscoverySession.js.map +1 -1
- package/dist/src/dht/discovery/PeerDiscovery.d.ts +8 -5
- package/dist/src/dht/discovery/PeerDiscovery.js +34 -24
- package/dist/src/dht/discovery/PeerDiscovery.js.map +1 -1
- package/dist/src/dht/discovery/RingDiscoverySession.d.ts +4 -4
- package/dist/src/dht/discovery/RingDiscoverySession.js +10 -19
- package/dist/src/dht/discovery/RingDiscoverySession.js.map +1 -1
- package/dist/src/dht/recursive-operation/RecursiveOperationManager.d.ts +2 -0
- package/dist/src/dht/recursive-operation/RecursiveOperationManager.js +3 -3
- package/dist/src/dht/recursive-operation/RecursiveOperationManager.js.map +1 -1
- package/dist/src/dht/store/StoreManager.d.ts +5 -6
- package/dist/src/dht/store/StoreManager.js +21 -76
- package/dist/src/dht/store/StoreManager.js.map +1 -1
- package/dist/src/dht/store/StoreRpcLocal.d.ts +5 -2
- package/dist/src/dht/store/StoreRpcLocal.js +22 -5
- package/dist/src/dht/store/StoreRpcLocal.js.map +1 -1
- package/dist/src/exports.d.ts +2 -1
- package/dist/src/exports.js.map +1 -1
- package/dist/src/helpers/version.d.ts +1 -1
- package/dist/src/helpers/version.js +1 -1
- package/dist/src/proto/google/protobuf/any.d.ts +8 -5
- package/dist/src/proto/google/protobuf/any.js.map +1 -1
- package/dist/src/proto/google/protobuf/empty.d.ts +0 -1
- package/dist/src/proto/google/protobuf/empty.js.map +1 -1
- package/dist/src/proto/google/protobuf/timestamp.d.ts +10 -1
- package/dist/src/proto/google/protobuf/timestamp.js.map +1 -1
- package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +10 -2
- package/dist/src/proto/packages/dht/protos/DhtRpc.js +4 -2
- package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
- package/dist/src/transport/ITransport.d.ts +0 -4
- package/dist/src/transport/ITransport.js.map +1 -1
- package/karma.config.js +2 -2
- package/package.json +8 -9
- package/protos/DhtRpc.proto +3 -1
- package/src/connection/ConnectionManager.ts +4 -10
- package/src/connection/ConnectionsView.ts +8 -0
- package/src/connection/ConnectorFacade.ts +7 -5
- package/src/connection/connectivityChecker.ts +4 -4
- package/src/connection/connectivityRequestHandler.ts +19 -6
- package/src/connection/{ManagedWebrtcConnection.ts → webrtc/ManagedWebrtcConnection.ts} +4 -4
- package/src/connection/webrtc/NodeWebrtcConnection.ts +3 -3
- package/src/connection/webrtc/WebrtcConnector.ts +1 -1
- package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +3 -3
- package/src/connection/websocket/AbstractWebsocketClientConnection.ts +1 -1
- package/src/connection/websocket/WebsocketConnector.ts +33 -21
- package/src/connection/websocket/WebsocketServerConnection.ts +6 -1
- package/src/dht/DhtNode.ts +102 -74
- package/src/dht/DhtNodeRpcLocal.ts +12 -5
- package/src/dht/PeerManager.ts +58 -49
- package/src/dht/contact/ContactList.ts +1 -4
- package/src/dht/contact/RandomContactList.ts +7 -5
- package/src/dht/contact/{getClosestContacts.ts → getClosestNodes.ts} +8 -6
- package/src/dht/discovery/DiscoverySession.ts +34 -22
- package/src/dht/discovery/PeerDiscovery.ts +44 -30
- package/src/dht/discovery/RingDiscoverySession.ts +15 -29
- package/src/dht/recursive-operation/RecursiveOperationManager.ts +5 -3
- package/src/dht/store/StoreManager.ts +46 -84
- package/src/dht/store/StoreRpcLocal.ts +32 -9
- package/src/exports.ts +2 -1
- package/src/helpers/version.ts +1 -1
- package/src/proto/google/protobuf/any.ts +8 -5
- package/src/proto/google/protobuf/empty.ts +0 -1
- package/src/proto/google/protobuf/timestamp.ts +10 -1
- package/src/proto/packages/dht/protos/DhtRpc.ts +14 -4
- package/src/transport/ITransport.ts +0 -4
- package/test/benchmark/Find.test.ts +1 -1
- package/test/benchmark/WebsocketServerMemoryLeak.test.ts +1 -1
- package/test/end-to-end/GeoIpLayer0.test.ts +55 -0
- package/test/end-to-end/Layer0-Layer1.test.ts +4 -4
- package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +11 -5
- package/test/end-to-end/Layer1-Scale-WebSocket.test.ts +7 -1
- package/test/end-to-end/Layer1-Scale-Webrtc.test.ts +11 -2
- package/test/integration/ConnectionLocking.test.ts +1 -1
- package/test/integration/ConnectionManager.test.ts +3 -3
- package/test/integration/ConnectivityChecking.test.ts +3 -3
- package/test/integration/DhtNode.test.ts +5 -20
- package/test/integration/GeoIpConnectivityChecking.test.ts +71 -0
- package/test/integration/Layer1-scale.test.ts +6 -6
- package/test/integration/RouteMessage.test.ts +4 -0
- package/test/integration/ScaleDownDht.test.ts +1 -1
- package/test/integration/SimultaneousConnections.test.ts +2 -2
- package/test/integration/WebrtcConnectionManagement.test.ts +1 -1
- package/test/integration/Websocket.test.ts +1 -1
- package/test/integration/WebsocketConnectionManagement.test.ts +1 -1
- package/test/integration/rpc-connections-over-webrpc.test.ts +1 -1
- package/test/unit/AutoCertifierClientFacade.test.ts +1 -1
- package/test/unit/DiscoverySession.test.ts +4 -2
- package/test/unit/PeerManager.test.ts +45 -51
- package/test/unit/RandomContactList.test.ts +10 -0
- package/test/unit/RecursiveOperationManager.test.ts +4 -2
- package/test/unit/StoreManager.test.ts +42 -34
- package/test/unit/StoreRpcLocal.test.ts +167 -0
- package/test/unit/WebsocketConnector.test.ts +1 -1
- package/test/unit/connectivityRequestHandler.test.ts +3 -3
- package/test/unit/getClosestNodes.test.ts +30 -0
- package/test/utils/FakeTransport.ts +4 -2
- package/test/utils/mock/MockConnectionsView.ts +18 -0
- package/test/utils/mock/{Transport.ts → MockTransport.ts} +0 -15
- package/test/utils/utils.ts +4 -1
- package/tsconfig.jest.json +2 -1
- package/tsconfig.node.json +2 -1
- package/dist/src/connection/ManagedWebrtcConnection.js.map +0 -1
- package/dist/src/dht/contact/getClosestContacts.d.ts +0 -7
- package/dist/src/dht/contact/getClosestContacts.js.map +0 -1
- package/test/unit/getClosestContacts.test.ts +0 -28
- /package/test/utils/mock/{Router.ts → MockRouter.ts} +0 -0
package/karma.config.js
CHANGED
|
@@ -4,8 +4,8 @@ const { createKarmaConfig, createWebpackConfig } = require('@streamr/browser-tes
|
|
|
4
4
|
|
|
5
5
|
const TEST_PATHS = [
|
|
6
6
|
'test/unit/**/!(connectivityRequestHandler*).ts',
|
|
7
|
-
'./test/integration/**/!(DhtWith*|ReplicateData*).ts/',
|
|
8
|
-
'./test/end-to-end/**/!(RecoveryFromFailedAutoCertification*|memory-leak*).ts'
|
|
7
|
+
'./test/integration/**/!(DhtWith*|ReplicateData*|GeoIpConnectivityChecking*).ts/',
|
|
8
|
+
'./test/end-to-end/**/!(RecoveryFromFailedAutoCertification*|memory-leak*|GeoIpLayer0*).ts'
|
|
9
9
|
]
|
|
10
10
|
|
|
11
11
|
const NodeWebrtcConnection = path.resolve(__dirname, 'src/connection/webrtc/NodeWebrtcConnection.ts')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamr/dht",
|
|
3
|
-
"version": "100.2.
|
|
3
|
+
"version": "100.2.5-beta.0",
|
|
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.
|
|
33
|
-
"@streamr/cdn-location": "100.2.
|
|
34
|
-
"@streamr/
|
|
35
|
-
"@streamr/
|
|
32
|
+
"@streamr/autocertifier-client": "100.2.5-beta.0",
|
|
33
|
+
"@streamr/cdn-location": "100.2.5-beta.0",
|
|
34
|
+
"@streamr/geoip-location": "100.2.5-beta.0",
|
|
35
|
+
"@streamr/proto-rpc": "100.2.5-beta.0",
|
|
36
|
+
"@streamr/utils": "100.2.5-beta.0",
|
|
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.
|
|
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.
|
|
51
|
-
"@types/express": "^4.17.21",
|
|
51
|
+
"@streamr/test-utils": "100.2.5-beta.0",
|
|
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",
|
package/protos/DhtRpc.proto
CHANGED
|
@@ -206,7 +206,7 @@ message ConnectivityRequest {
|
|
|
206
206
|
uint32 port = 1;
|
|
207
207
|
bool tls = 2;
|
|
208
208
|
optional string host = 3;
|
|
209
|
-
bool
|
|
209
|
+
bool allowSelfSignedCertificate = 4;
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
message ConnectivityResponse {
|
|
@@ -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
|
|
162
|
-
|
|
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
|
-
|
|
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
|
|
|
@@ -13,14 +13,14 @@ import { isMaybeSupportedVersion } from '../helpers/version'
|
|
|
13
13
|
const logger = new Logger(module)
|
|
14
14
|
|
|
15
15
|
// TODO use config option or named constant?
|
|
16
|
-
export const connectAsync = async ({ url,
|
|
17
|
-
{ url: string,
|
|
16
|
+
export const connectAsync = async ({ url, allowSelfSignedCertificate, timeoutMs = 1000 }:
|
|
17
|
+
{ url: string, allowSelfSignedCertificate: boolean, timeoutMs?: number }
|
|
18
18
|
): Promise<IConnection> => {
|
|
19
19
|
const socket = new WebsocketClientConnection()
|
|
20
20
|
let result: RunAndRaceEventsReturnType<ConnectionEvents>
|
|
21
21
|
try {
|
|
22
22
|
result = await runAndRaceEvents3<ConnectionEvents>([
|
|
23
|
-
() => { socket.connect(url,
|
|
23
|
+
() => { socket.connect(url, allowSelfSignedCertificate) }],
|
|
24
24
|
socket, ['connected', 'error'],
|
|
25
25
|
timeoutMs)
|
|
26
26
|
} catch (e) {
|
|
@@ -50,7 +50,7 @@ export const sendConnectivityRequest = async (
|
|
|
50
50
|
try {
|
|
51
51
|
outgoingConnection = await connectAsync({
|
|
52
52
|
url,
|
|
53
|
-
|
|
53
|
+
allowSelfSignedCertificate: request.allowSelfSignedCertificate
|
|
54
54
|
})
|
|
55
55
|
} catch (e) {
|
|
56
56
|
throw new Err.ConnectionFailed(`Failed to connect to entrypoint for connectivity check: ${url}`, e)
|
|
@@ -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,
|
|
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 (
|
|
40
|
-
|
|
41
|
-
|
|
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(),
|
|
@@ -76,7 +89,7 @@ const connectivityProbe = async (connectivityRequest: ConnectivityRequest, ipAdd
|
|
|
76
89
|
logger.trace(`Attempting Connectivity Check to ${url}`)
|
|
77
90
|
outgoingConnection = await connectAsync({
|
|
78
91
|
url,
|
|
79
|
-
|
|
92
|
+
allowSelfSignedCertificate: connectivityRequest.allowSelfSignedCertificate
|
|
80
93
|
})
|
|
81
94
|
logger.trace('Connectivity test produced positive result, communicating reply to the requester ' + host + ':' + connectivityRequest.port)
|
|
82
95
|
connectivityResponseMessage = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { PeerDescriptor } from '
|
|
2
|
-
import { ConnectionType } from '
|
|
3
|
-
import { ManagedConnection } from '
|
|
4
|
-
import { NodeWebrtcConnection } from './
|
|
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
|
|
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
|
-
|
|
19
|
+
cleanup()
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -42,7 +42,7 @@ enum RtcPeerConnectionStateEnum {
|
|
|
42
42
|
new = 'new'
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
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 '
|
|
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 '
|
|
17
|
+
import { ManagedWebrtcConnection } from './ManagedWebrtcConnection'
|
|
18
18
|
import { NodeWebrtcConnection } from './NodeWebrtcConnection'
|
|
19
19
|
import { WebrtcConnectorRpcRemote } from './WebrtcConnectorRpcRemote'
|
|
20
20
|
import { DhtAddress, getNodeIdFromPeerDescriptor } from '../../identifiers'
|
|
@@ -89,9 +89,9 @@ export class WebrtcConnectorRpcLocal implements IWebrtcConnectorRpc {
|
|
|
89
89
|
this.config.ongoingConnectAttempts.delete(nodeId)
|
|
90
90
|
}
|
|
91
91
|
if (!isMaybeSupportedVersion(remoteVersion)) {
|
|
92
|
-
managedConnection
|
|
92
|
+
managedConnection.rejectHandshake(HandshakeError.UNSUPPORTED_VERSION)
|
|
93
93
|
} else {
|
|
94
|
-
managedConnection
|
|
94
|
+
managedConnection.acceptHandshake()
|
|
95
95
|
}
|
|
96
96
|
})
|
|
97
97
|
return {}
|
|
@@ -34,7 +34,7 @@ export abstract class AbstractWebsocketClientConnection extends EventEmitter<Con
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// TODO explicit default value for "selfSigned" or make it required
|
|
37
|
-
public abstract connect(address: string,
|
|
37
|
+
public abstract connect(address: string, allowSelfSignedCertificate: boolean): void
|
|
38
38
|
|
|
39
39
|
protected abstract stopListening(): void
|
|
40
40
|
|
|
@@ -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
|
|
|
@@ -39,7 +40,6 @@ export const connectivityMethodToWebsocketUrl = (ws: ConnectivityMethod, action?
|
|
|
39
40
|
return (ws.tls ? 'wss://' : 'ws://') + ws.host + ':' + ws.port + ((action !== undefined) ? '?action=' + action : '')
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
const ENTRY_POINT_CONNECTION_ATTEMPTS = 5
|
|
43
43
|
export interface WebsocketConnectorConfig {
|
|
44
44
|
transport: ITransport
|
|
45
45
|
onNewConnection: (connection: ManagedConnection) => boolean
|
|
@@ -53,6 +53,7 @@ export interface WebsocketConnectorConfig {
|
|
|
53
53
|
autoCertifierUrl: string
|
|
54
54
|
autoCertifierConfigFile: string
|
|
55
55
|
serverEnableTls: boolean
|
|
56
|
+
geoIpDatabaseFolder?: string
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
export class WebsocketConnector {
|
|
@@ -60,6 +61,7 @@ export class WebsocketConnector {
|
|
|
60
61
|
private static readonly WEBSOCKET_CONNECTOR_SERVICE_ID = 'system/websocket-connector'
|
|
61
62
|
private readonly rpcCommunicator: ListeningRpcCommunicator
|
|
62
63
|
private readonly websocketServer?: WebsocketServer
|
|
64
|
+
private geoIpLocator?: GeoIpLocator
|
|
63
65
|
private readonly ongoingConnectRequests: Map<DhtAddress, ManagedConnection> = new Map()
|
|
64
66
|
private host?: string
|
|
65
67
|
private autoCertifierClient?: AutoCertifierClientFacade
|
|
@@ -87,17 +89,10 @@ export class WebsocketConnector {
|
|
|
87
89
|
private registerLocalRpcMethods(config: WebsocketConnectorConfig) {
|
|
88
90
|
const rpcLocal = new WebsocketConnectorRpcLocal({
|
|
89
91
|
connect: (targetPeerDescriptor: PeerDescriptor) => this.connect(targetPeerDescriptor),
|
|
90
|
-
hasConnection: (nodeId: DhtAddress): boolean =>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|| config.hasConnection(nodeId)
|
|
95
|
-
) {
|
|
96
|
-
return true
|
|
97
|
-
} else {
|
|
98
|
-
return false
|
|
99
|
-
}
|
|
100
|
-
},
|
|
92
|
+
hasConnection: (nodeId: DhtAddress): boolean => (this.connectingConnections.has(nodeId)
|
|
93
|
+
|| this.ongoingConnectRequests.has(nodeId)
|
|
94
|
+
|| config.hasConnection(nodeId))
|
|
95
|
+
,
|
|
101
96
|
onNewConnection: (connection: ManagedConnection) => config.onNewConnection(connection),
|
|
102
97
|
abortSignal: this.abortController.signal
|
|
103
98
|
})
|
|
@@ -145,9 +140,9 @@ export class WebsocketConnector {
|
|
|
145
140
|
const serverSocket = connection as unknown as WebsocketServerConnection
|
|
146
141
|
const query = queryString.parse(serverSocket.resourceURL.query as string ?? '')
|
|
147
142
|
const action = query.action as (Action | undefined)
|
|
148
|
-
logger.trace('WebSocket client connected', { action, remoteAddress: serverSocket.
|
|
143
|
+
logger.trace('WebSocket client connected', { action, remoteAddress: serverSocket.getRemoteIpAddress() })
|
|
149
144
|
if (action === 'connectivityRequest') {
|
|
150
|
-
attachConnectivityRequestHandler(serverSocket)
|
|
145
|
+
attachConnectivityRequestHandler(serverSocket, this.geoIpLocator)
|
|
151
146
|
} else if (action === 'connectivityProbe') {
|
|
152
147
|
// no-op
|
|
153
148
|
} else {
|
|
@@ -163,12 +158,23 @@ export class WebsocketConnector {
|
|
|
163
158
|
}
|
|
164
159
|
}
|
|
165
160
|
})
|
|
161
|
+
|
|
162
|
+
if (this.config.geoIpDatabaseFolder) {
|
|
163
|
+
const geoIpLocator = new GeoIpLocator(this.config.geoIpDatabaseFolder)
|
|
164
|
+
try {
|
|
165
|
+
await geoIpLocator.start()
|
|
166
|
+
this.geoIpLocator = geoIpLocator
|
|
167
|
+
} catch (err) {
|
|
168
|
+
logger.error('Failed to start GeoIpLocator', { err })
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
166
172
|
const port = await this.websocketServer.start()
|
|
167
173
|
this.selectedPort = port
|
|
168
174
|
}
|
|
169
175
|
}
|
|
170
176
|
|
|
171
|
-
public async checkConnectivity(
|
|
177
|
+
public async checkConnectivity(allowSelfSignedCertificate: boolean): Promise<ConnectivityResponse> {
|
|
172
178
|
// TODO: this could throw?
|
|
173
179
|
if (this.abortController.signal.aborted) {
|
|
174
180
|
return {
|
|
@@ -183,9 +189,9 @@ export class WebsocketConnector {
|
|
|
183
189
|
return {
|
|
184
190
|
host: this.host!,
|
|
185
191
|
natType: NatType.OPEN_INTERNET,
|
|
186
|
-
websocket: {
|
|
187
|
-
host: this.host!,
|
|
188
|
-
port: this.selectedPort!,
|
|
192
|
+
websocket: {
|
|
193
|
+
host: this.host!,
|
|
194
|
+
port: this.selectedPort!,
|
|
189
195
|
tls: this.config.tlsCertificate !== undefined
|
|
190
196
|
},
|
|
191
197
|
// TODO: Resolve the given host name or or use as is if IP was given.
|
|
@@ -202,7 +208,7 @@ export class WebsocketConnector {
|
|
|
202
208
|
port: this.selectedPort ?? DISABLE_CONNECTIVITY_PROBE,
|
|
203
209
|
host: this.host,
|
|
204
210
|
tls: this.websocketServer ? this.config.serverEnableTls : false,
|
|
205
|
-
|
|
211
|
+
allowSelfSignedCertificate
|
|
206
212
|
}
|
|
207
213
|
if (!this.abortController.signal.aborted) {
|
|
208
214
|
return await sendConnectivityRequest(connectivityRequest, entryPoint)
|
|
@@ -217,7 +223,10 @@ export class WebsocketConnector {
|
|
|
217
223
|
await wait(2000, this.abortController.signal)
|
|
218
224
|
}
|
|
219
225
|
}
|
|
220
|
-
throw new WebsocketServerStartError(
|
|
226
|
+
throw new WebsocketServerStartError(
|
|
227
|
+
`Failed to connect to the entrypoints after ${this.config.entrypoints.length} attempts\n`
|
|
228
|
+
+ `Attempted hosts: ${this.config.entrypoints.map((entry) => `${entry.websocket!.host}:${entry.websocket!.port}`).join(', ')}`
|
|
229
|
+
)
|
|
221
230
|
}
|
|
222
231
|
|
|
223
232
|
public isPossibleToFormConnection(targetPeerDescriptor: PeerDescriptor): boolean {
|
|
@@ -260,7 +269,7 @@ export class WebsocketConnector {
|
|
|
260
269
|
socket.on('disconnected', delFunc)
|
|
261
270
|
managedConnection.on('handshakeCompleted', delFunc)
|
|
262
271
|
|
|
263
|
-
socket.connect(url)
|
|
272
|
+
socket.connect(url, false)
|
|
264
273
|
|
|
265
274
|
return managedConnection
|
|
266
275
|
}
|
|
@@ -307,6 +316,8 @@ export class WebsocketConnector {
|
|
|
307
316
|
const ongoingConnectRequest = this.ongoingConnectRequests.get(nodeId)!
|
|
308
317
|
if (!isMaybeSupportedVersion(remoteVersion)) {
|
|
309
318
|
ongoingConnectRequest.rejectHandshake(HandshakeError.UNSUPPORTED_VERSION)
|
|
319
|
+
} else if (targetPeerDescriptor && !areEqualPeerDescriptors(this.localPeerDescriptor!, targetPeerDescriptor)) {
|
|
320
|
+
ongoingConnectRequest.rejectHandshake(HandshakeError.INVALID_TARGET_PEER_DESCRIPTOR)
|
|
310
321
|
} else {
|
|
311
322
|
ongoingConnectRequest.attachImplementation(websocketServerConnection)
|
|
312
323
|
ongoingConnectRequest.acceptHandshake()
|
|
@@ -347,5 +358,6 @@ export class WebsocketConnector {
|
|
|
347
358
|
const attempts = Array.from(this.connectingConnections.values())
|
|
348
359
|
await Promise.allSettled(attempts.map((conn) => conn.close(false)))
|
|
349
360
|
await this.websocketServer?.stop()
|
|
361
|
+
await this.geoIpLocator?.stop()
|
|
350
362
|
}
|
|
351
363
|
}
|
|
@@ -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
|
-
|
|
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) {
|