@streamr/dht 102.0.0-beta.1 → 102.0.0-beta.3
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/generated/google/protobuf/any.d.ts +180 -0
- package/dist/generated/google/protobuf/any.js +155 -0
- package/dist/generated/google/protobuf/any.js.map +1 -0
- package/dist/generated/google/protobuf/empty.d.ts +31 -0
- package/dist/generated/google/protobuf/empty.js +32 -0
- package/dist/generated/google/protobuf/empty.js.map +1 -0
- package/dist/generated/google/protobuf/timestamp.d.ts +155 -0
- package/dist/generated/google/protobuf/timestamp.js +136 -0
- package/dist/generated/google/protobuf/timestamp.js.map +1 -0
- package/dist/generated/packages/dht/protos/DhtRpc.client.d.ts +361 -0
- package/dist/generated/packages/dht/protos/DhtRpc.client.js +285 -0
- package/dist/generated/packages/dht/protos/DhtRpc.client.js.map +1 -0
- package/dist/generated/packages/dht/protos/DhtRpc.d.ts +999 -0
- package/dist/generated/packages/dht/protos/DhtRpc.js +677 -0
- package/dist/generated/packages/dht/protos/DhtRpc.js.map +1 -0
- package/dist/generated/packages/dht/protos/DhtRpc.server.d.ts +162 -0
- package/dist/generated/packages/dht/protos/DhtRpc.server.js +3 -0
- package/dist/generated/packages/dht/protos/DhtRpc.server.js.map +1 -0
- package/dist/generated/packages/proto-rpc/protos/ProtoRpc.d.ts +87 -0
- package/dist/generated/packages/proto-rpc/protos/ProtoRpc.js +66 -0
- package/dist/generated/packages/proto-rpc/protos/ProtoRpc.js.map +1 -0
- package/dist/package.json +7 -7
- package/package.json +7 -7
- package/eslint.config.mjs +0 -12
- package/src/connection/Connection.ts +0 -28
- package/src/connection/ConnectionLockRpcLocal.ts +0 -78
- package/src/connection/ConnectionLockRpcRemote.ts +0 -64
- package/src/connection/ConnectionLockStates.ts +0 -131
- package/src/connection/ConnectionManager.ts +0 -661
- package/src/connection/ConnectionsView.ts +0 -8
- package/src/connection/ConnectorFacade.ts +0 -217
- package/src/connection/Handshaker.ts +0 -209
- package/src/connection/IConnection.ts +0 -40
- package/src/connection/ManagedConnection.ts +0 -113
- package/src/connection/OutputBuffer.ts +0 -28
- package/src/connection/PendingConnection.ts +0 -68
- package/src/connection/connectivityChecker.ts +0 -108
- package/src/connection/connectivityRequestHandler.ts +0 -116
- package/src/connection/simulator/Simulator.ts +0 -369
- package/src/connection/simulator/SimulatorConnection.ts +0 -137
- package/src/connection/simulator/SimulatorConnector.ts +0 -98
- package/src/connection/simulator/SimulatorTransport.ts +0 -15
- package/src/connection/simulator/pings.ts +0 -42
- package/src/connection/webrtc/BrowserWebrtcConnection.ts +0 -242
- package/src/connection/webrtc/IWebrtcConnection.ts +0 -24
- package/src/connection/webrtc/NodeWebrtcConnection.ts +0 -245
- package/src/connection/webrtc/WebrtcConnector.ts +0 -234
- package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +0 -108
- package/src/connection/webrtc/WebrtcConnectorRpcRemote.ts +0 -60
- package/src/connection/webrtc/iceServerAsString.ts +0 -15
- package/src/connection/websocket/AbstractWebsocketClientConnection.ts +0 -122
- package/src/connection/websocket/AutoCertifierClientFacade.ts +0 -89
- package/src/connection/websocket/BrowserWebsocketClientConnection.ts +0 -44
- package/src/connection/websocket/NodeWebsocketClientConnection.ts +0 -39
- package/src/connection/websocket/WebsocketClientConnector.ts +0 -119
- package/src/connection/websocket/WebsocketClientConnectorRpcLocal.ts +0 -38
- package/src/connection/websocket/WebsocketClientConnectorRpcRemote.ts +0 -19
- package/src/connection/websocket/WebsocketServer.ts +0 -164
- package/src/connection/websocket/WebsocketServerConnection.ts +0 -109
- package/src/connection/websocket/WebsocketServerConnector.ts +0 -290
- package/src/dht/DhtNode.ts +0 -683
- package/src/dht/DhtNodeRpcLocal.ts +0 -84
- package/src/dht/DhtNodeRpcRemote.ts +0 -107
- package/src/dht/ExternalApiRpcLocal.ts +0 -58
- package/src/dht/ExternalApiRpcRemote.ts +0 -41
- package/src/dht/PeerManager.ts +0 -305
- package/src/dht/contact/Contact.ts +0 -19
- package/src/dht/contact/ContactList.ts +0 -43
- package/src/dht/contact/RandomContactList.ts +0 -56
- package/src/dht/contact/RingContactList.ts +0 -143
- package/src/dht/contact/RpcRemote.ts +0 -72
- package/src/dht/contact/SortedContactList.ts +0 -173
- package/src/dht/contact/getClosestNodes.ts +0 -24
- package/src/dht/contact/ringIdentifiers.ts +0 -62
- package/src/dht/discovery/DiscoverySession.ts +0 -129
- package/src/dht/discovery/PeerDiscovery.ts +0 -244
- package/src/dht/discovery/RingDiscoverySession.ts +0 -148
- package/src/dht/recursive-operation/RecursiveOperationManager.ts +0 -251
- package/src/dht/recursive-operation/RecursiveOperationRpcLocal.ts +0 -34
- package/src/dht/recursive-operation/RecursiveOperationRpcRemote.ts +0 -43
- package/src/dht/recursive-operation/RecursiveOperationSession.ts +0 -231
- package/src/dht/recursive-operation/RecursiveOperationSessionRpcLocal.ts +0 -35
- package/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.ts +0 -30
- package/src/dht/routing/DuplicateDetector.ts +0 -34
- package/src/dht/routing/Router.ts +0 -246
- package/src/dht/routing/RouterRpcLocal.ts +0 -78
- package/src/dht/routing/RouterRpcRemote.ts +0 -80
- package/src/dht/routing/RoutingSession.ts +0 -243
- package/src/dht/routing/RoutingTablesCache.ts +0 -60
- package/src/dht/routing/getPreviousPeer.ts +0 -6
- package/src/dht/store/LocalDataStore.ts +0 -84
- package/src/dht/store/StoreManager.ts +0 -170
- package/src/dht/store/StoreRpcLocal.ts +0 -89
- package/src/dht/store/StoreRpcRemote.ts +0 -32
- package/src/exports.ts +0 -33
- package/src/helpers/AddressTools.ts +0 -28
- package/src/helpers/Connectivity.ts +0 -19
- package/src/helpers/browser/isBrowserEnvironment.ts +0 -1
- package/src/helpers/browser/isBrowserEnvironment_override.ts +0 -3
- package/src/helpers/createPeerDescriptor.ts +0 -57
- package/src/helpers/createPeerDescriptorSignaturePayload.ts +0 -28
- package/src/helpers/debugHelpers.ts +0 -9
- package/src/helpers/errors.ts +0 -49
- package/src/helpers/offering.ts +0 -15
- package/src/helpers/protoClasses.ts +0 -57
- package/src/helpers/protoToString.ts +0 -21
- package/src/helpers/version.ts +0 -32
- package/src/identifiers.ts +0 -29
- package/src/rpc-protocol/DhtCallContext.ts +0 -14
- package/src/rpc-protocol/DhtRpcOptions.ts +0 -10
- package/src/transport/ITransport.ts +0 -37
- package/src/transport/ListeningRpcCommunicator.ts +0 -32
- package/src/transport/RoutingRpcCommunicator.ts +0 -66
- package/src/types/ServiceID.ts +0 -1
- package/src/types/textencoding.d.ts +0 -6
- package/test/benchmark/Find.test.ts +0 -72
- package/test/benchmark/KademliaCorrectness.test.ts +0 -114
- package/test/benchmark/RingCorrectness.test.ts +0 -157
- package/test/benchmark/SortedContactListBenchmark.test.ts +0 -108
- package/test/benchmark/WebsocketServerMemoryLeak.test.ts +0 -41
- package/test/benchmark/hybrid-network-simulation/RingContactList.test.ts +0 -71
- package/test/end-to-end/GeoIpLayer0.test.ts +0 -55
- package/test/end-to-end/Layer0-Layer1.test.ts +0 -93
- package/test/end-to-end/Layer0.test.ts +0 -76
- package/test/end-to-end/Layer0MixedConnectionTypes.test.ts +0 -110
- package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +0 -137
- package/test/end-to-end/Layer0Webrtc.test.ts +0 -85
- package/test/end-to-end/Layer1-Scale-WebSocket.test.ts +0 -82
- package/test/end-to-end/Layer1-Scale-Webrtc.test.ts +0 -76
- package/test/end-to-end/RecoveryFromFailedAutoCertification.test.ts +0 -52
- package/test/end-to-end/WebsocketConnectionRequest.test.ts +0 -69
- package/test/end-to-end/memory-leak.test.ts +0 -80
- package/test/integration/ConnectionLocking.test.ts +0 -192
- package/test/integration/ConnectionManager.test.ts +0 -528
- package/test/integration/ConnectivityChecking.test.ts +0 -53
- package/test/integration/DhtJoinPeerDiscovery.test.ts +0 -49
- package/test/integration/DhtNode.test.ts +0 -66
- package/test/integration/DhtNodeExternalAPI.test.ts +0 -48
- package/test/integration/DhtNodeRpcRemote.test.ts +0 -66
- package/test/integration/DhtRpc.test.ts +0 -121
- package/test/integration/Find.test.ts +0 -45
- package/test/integration/GeoIpConnectivityChecking.test.ts +0 -72
- package/test/integration/Layer1-scale.test.ts +0 -189
- package/test/integration/Mock-Layer1-Layer0.test.ts +0 -85
- package/test/integration/MultipleEntryPointJoining.test.ts +0 -105
- package/test/integration/ReplicateData.test.ts +0 -104
- package/test/integration/RouteMessage.test.ts +0 -230
- package/test/integration/RouterRpcRemote.test.ts +0 -77
- package/test/integration/SimultaneousConnections.test.ts +0 -316
- package/test/integration/Store.test.ts +0 -85
- package/test/integration/StoreAndDelete.test.ts +0 -77
- package/test/integration/StoreOnDhtWithThreeNodes.test.ts +0 -59
- package/test/integration/StoreOnDhtWithTwoNodes.test.ts +0 -51
- package/test/integration/StoreRpcRemote.test.ts +0 -54
- package/test/integration/WebrtcConnectionManagement.test.ts +0 -191
- package/test/integration/WebrtcConnectorRpc.test.ts +0 -125
- package/test/integration/Websocket.test.ts +0 -65
- package/test/integration/WebsocketClientConnectorRpc.test.ts +0 -69
- package/test/integration/WebsocketConnectionManagement.test.ts +0 -191
- package/test/integration/rpc-connections-over-webrtc.test.ts +0 -123
- package/test/kademlia-simulation/data/nodeids.json +0 -13002
- package/test/kademlia-simulation/data/orderedneighbors.json +0 -1001
- package/test/types/global.d.ts +0 -1
- package/test/unit/AddressTools.test.ts +0 -44
- package/test/unit/AutoCertifierClientFacade.test.ts +0 -58
- package/test/unit/ConnectionManager.test.ts +0 -65
- package/test/unit/ConnectivityHelpers.test.ts +0 -61
- package/test/unit/DiscoverySession.test.ts +0 -87
- package/test/unit/DuplicateDetector.test.ts +0 -31
- package/test/unit/Handshaker.test.ts +0 -169
- package/test/unit/ListeningRpcCommunicator.test.ts +0 -52
- package/test/unit/LocalDataStore.test.ts +0 -108
- package/test/unit/ManagedConnection.test.ts +0 -58
- package/test/unit/PeerManager.test.ts +0 -93
- package/test/unit/PendingConnection.test.ts +0 -57
- package/test/unit/ProtobufMessage.test.ts +0 -21
- package/test/unit/RandomContactList.test.ts +0 -58
- package/test/unit/RecursiveOperationManager.test.ts +0 -161
- package/test/unit/RecursiveOperationSession.test.ts +0 -68
- package/test/unit/Router.test.ts +0 -137
- package/test/unit/RoutingSession.test.ts +0 -86
- package/test/unit/SortedContactList.test.ts +0 -115
- package/test/unit/StoreManager.test.ts +0 -146
- package/test/unit/StoreRpcLocal.test.ts +0 -167
- package/test/unit/WebrtcConnection.test.ts +0 -29
- package/test/unit/WebrtcConnector.test.ts +0 -56
- package/test/unit/WebsocketClientConnector.test.ts +0 -101
- package/test/unit/WebsocketServer.test.ts +0 -66
- package/test/unit/WebsocketServerConnector.test.ts +0 -102
- package/test/unit/connectivityRequestHandler.test.ts +0 -104
- package/test/unit/createPeerDescriptor.test.ts +0 -69
- package/test/unit/customMatchers.test.ts +0 -34
- package/test/unit/getClosestNodes.test.ts +0 -30
- package/test/unit/version.test.ts +0 -18
- package/test/unit/webrtcReplaceInternalIpWithExternalIp.test.ts +0 -18
- package/test/utils/FakeConnectorFacade.ts +0 -41
- package/test/utils/FakeRpcCommunicator.ts +0 -23
- package/test/utils/FakeTransport.ts +0 -79
- package/test/utils/customMatchers.ts +0 -71
- package/test/utils/mock/MockConnection.ts +0 -26
- package/test/utils/mock/MockConnectionsView.ts +0 -18
- package/test/utils/mock/MockRouter.ts +0 -62
- package/test/utils/mock/MockRpcCommunicator.ts +0 -7
- package/test/utils/mock/MockTransport.ts +0 -26
- package/test/utils/mock/mockDataEntry.ts +0 -38
- package/test/utils/topology.ts +0 -79
- package/test/utils/utils.ts +0 -268
- package/tsconfig.browser.json +0 -17
- package/tsconfig.jest.json +0 -25
- package/tsconfig.json +0 -3
- package/tsconfig.node.json +0 -24
|
@@ -1,661 +0,0 @@
|
|
|
1
|
-
import { CountMetric, LevelMetric, Logger, Metric, MetricsContext, MetricsDefinition, RateMetric, waitForEvent3 } from '@streamr/utils'
|
|
2
|
-
import { EventEmitter } from 'eventemitter3'
|
|
3
|
-
import { SortedContactList } from '../dht/contact/SortedContactList'
|
|
4
|
-
import { DuplicateDetector } from '../dht/routing/DuplicateDetector'
|
|
5
|
-
import * as Err from '../helpers/errors'
|
|
6
|
-
import {
|
|
7
|
-
DisconnectMode,
|
|
8
|
-
DisconnectNotice,
|
|
9
|
-
LockRequest,
|
|
10
|
-
LockResponse,
|
|
11
|
-
Message,
|
|
12
|
-
PeerDescriptor,
|
|
13
|
-
UnlockRequest,
|
|
14
|
-
SetPrivateRequest
|
|
15
|
-
} from '../../generated/packages/dht/protos/DhtRpc'
|
|
16
|
-
import { ConnectionLockRpcClient } from '../../generated/packages/dht/protos/DhtRpc.client'
|
|
17
|
-
import { DEFAULT_SEND_OPTIONS, ITransport, SendOptions, TransportEvents } from '../transport/ITransport'
|
|
18
|
-
import { RoutingRpcCommunicator } from '../transport/RoutingRpcCommunicator'
|
|
19
|
-
import { ConnectionLockStates, LockID } from './ConnectionLockStates'
|
|
20
|
-
import { ConnectorFacade } from './ConnectorFacade'
|
|
21
|
-
import { ManagedConnection, Events as ManagedConnectionEvents } from './ManagedConnection'
|
|
22
|
-
import { ConnectionLockRpcRemote } from './ConnectionLockRpcRemote'
|
|
23
|
-
import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
|
|
24
|
-
import { ConnectionLockRpcLocal } from './ConnectionLockRpcLocal'
|
|
25
|
-
import { DhtAddress, areEqualPeerDescriptors, toNodeId } from '../identifiers'
|
|
26
|
-
import { getOfferer } from '../helpers/offering'
|
|
27
|
-
import { ConnectionsView } from './ConnectionsView'
|
|
28
|
-
import { OutputBuffer } from './OutputBuffer'
|
|
29
|
-
import { IConnection } from './IConnection'
|
|
30
|
-
import { PendingConnection } from './PendingConnection'
|
|
31
|
-
|
|
32
|
-
export interface ConnectionManagerOptions {
|
|
33
|
-
maxConnections?: number
|
|
34
|
-
metricsContext: MetricsContext
|
|
35
|
-
allowIncomingPrivateConnections: boolean
|
|
36
|
-
createConnectorFacade: () => ConnectorFacade
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export enum NatType {
|
|
40
|
-
OPEN_INTERNET = 'open_internet',
|
|
41
|
-
UNKNOWN = 'unknown'
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
interface ConnectionManagerMetrics extends MetricsDefinition {
|
|
45
|
-
sendMessagesPerSecond: Metric
|
|
46
|
-
sendBytesPerSecond: Metric
|
|
47
|
-
receiveMessagesPerSecond: Metric
|
|
48
|
-
receiveBytesPerSecond: Metric
|
|
49
|
-
connectionAverageCount: Metric
|
|
50
|
-
connectionTotalFailureCount: Metric
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const logger = new Logger(module)
|
|
54
|
-
|
|
55
|
-
enum ConnectionManagerState {
|
|
56
|
-
IDLE = 'idle',
|
|
57
|
-
RUNNING = 'running',
|
|
58
|
-
STOPPING = 'stopping',
|
|
59
|
-
STOPPED = 'stopped'
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface ConnectionLocker {
|
|
63
|
-
lockConnection(targetDescriptor: PeerDescriptor, lockId: LockID): void
|
|
64
|
-
unlockConnection(targetDescriptor: PeerDescriptor, lockId: LockID): void
|
|
65
|
-
weakLockConnection(nodeId: DhtAddress, lockId: LockID): void
|
|
66
|
-
weakUnlockConnection(nodeId: DhtAddress, lockId: LockID): void
|
|
67
|
-
getLocalLockedConnectionCount(): number
|
|
68
|
-
getRemoteLockedConnectionCount(): number
|
|
69
|
-
getWeakLockedConnectionCount(): number
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export interface PortRange {
|
|
73
|
-
min: number
|
|
74
|
-
max: number
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export interface TlsCertificate {
|
|
78
|
-
privateKeyFileName: string
|
|
79
|
-
certFileName: string
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
interface ConnectingEndpoint {
|
|
83
|
-
connected: false
|
|
84
|
-
// TODO: Handle PendingConnections in ConnectorFacade only? ConnectionManager knows buffer and reacts to events from below.
|
|
85
|
-
// Difficulties arise from duplicate connection handling. Sometimes a connected connection is replaced as duplicate in which case
|
|
86
|
-
// a managed connection has to be replaced in the ConnectionManager.
|
|
87
|
-
connection: PendingConnection
|
|
88
|
-
// Could the buffer be in the PendingConnection or encapsulated endpoint?
|
|
89
|
-
buffer: OutputBuffer
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
interface ConnectedEndpoint {
|
|
93
|
-
connected: true
|
|
94
|
-
connection: ManagedConnection
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// TODO: Could encapsulate all endpoint logic to its own module
|
|
98
|
-
type Endpoint = ConnectedEndpoint | ConnectingEndpoint
|
|
99
|
-
|
|
100
|
-
const INTERNAL_SERVICE_ID = 'system/connection-manager'
|
|
101
|
-
|
|
102
|
-
// Form an string representation from a peer description which can be undefined. This output
|
|
103
|
-
// should only be used only for log output. TODO remove this method if we no longer use
|
|
104
|
-
// peerDescriptors which can be undefined, e.g.
|
|
105
|
-
// - if we refactor ConnectionManager so that it doesn't process handshake requests too early
|
|
106
|
-
// and therefore this.localPeerDescriptor can't be undefine (NET-1129)
|
|
107
|
-
// - if the peerDescriptor of ManagedConnection is always available
|
|
108
|
-
// - if we create stricter types for incoming messages (message.sourceDescriptor or
|
|
109
|
-
// disconnectNotice.peerDescriptor)
|
|
110
|
-
// - if ManagedConnection#peerDescriptor is never undefined
|
|
111
|
-
export const getNodeIdOrUnknownFromPeerDescriptor = (peerDescriptor: PeerDescriptor | undefined): string => {
|
|
112
|
-
if (peerDescriptor !== undefined) {
|
|
113
|
-
return toNodeId(peerDescriptor)
|
|
114
|
-
} else {
|
|
115
|
-
return 'unknown'
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export class ConnectionManager extends EventEmitter<TransportEvents> implements ITransport, ConnectionsView, ConnectionLocker {
|
|
120
|
-
|
|
121
|
-
private options: ConnectionManagerOptions
|
|
122
|
-
private readonly metricsContext: MetricsContext
|
|
123
|
-
// TODO use options option or named constant?
|
|
124
|
-
private readonly duplicateMessageDetector: DuplicateDetector = new DuplicateDetector(10000)
|
|
125
|
-
private readonly metrics: ConnectionManagerMetrics
|
|
126
|
-
private locks = new ConnectionLockStates()
|
|
127
|
-
private endpoints: Map<DhtAddress, Endpoint> = new Map()
|
|
128
|
-
private readonly connectorFacade: ConnectorFacade
|
|
129
|
-
private rpcCommunicator?: RoutingRpcCommunicator
|
|
130
|
-
private disconnectorIntervalRef?: NodeJS.Timeout
|
|
131
|
-
private state = ConnectionManagerState.IDLE
|
|
132
|
-
private privateClientMode = false
|
|
133
|
-
|
|
134
|
-
constructor(options: ConnectionManagerOptions) {
|
|
135
|
-
super()
|
|
136
|
-
this.options = options
|
|
137
|
-
this.onData = this.onData.bind(this)
|
|
138
|
-
this.send = this.send.bind(this)
|
|
139
|
-
this.onNewConnection = this.onNewConnection.bind(this)
|
|
140
|
-
this.metricsContext = this.options.metricsContext ?? new MetricsContext()
|
|
141
|
-
this.metrics = {
|
|
142
|
-
sendMessagesPerSecond: new RateMetric(),
|
|
143
|
-
sendBytesPerSecond: new RateMetric(),
|
|
144
|
-
receiveMessagesPerSecond: new RateMetric(),
|
|
145
|
-
receiveBytesPerSecond: new RateMetric(),
|
|
146
|
-
connectionAverageCount: new LevelMetric(0),
|
|
147
|
-
connectionTotalFailureCount: new CountMetric()
|
|
148
|
-
}
|
|
149
|
-
this.metricsContext.addMetrics('node', this.metrics)
|
|
150
|
-
this.connectorFacade = this.options.createConnectorFacade()
|
|
151
|
-
this.send = this.send.bind(this)
|
|
152
|
-
this.rpcCommunicator = new RoutingRpcCommunicator(INTERNAL_SERVICE_ID, this.send, {
|
|
153
|
-
rpcRequestTimeout: 10000 // TODO use options option or named constant?
|
|
154
|
-
})
|
|
155
|
-
const lockRpcLocal = new ConnectionLockRpcLocal({
|
|
156
|
-
addRemoteLocked: (id: DhtAddress, lockId: LockID) => this.locks.addRemoteLocked(id, lockId),
|
|
157
|
-
removeRemoteLocked: (id: DhtAddress, lockId: LockID) => this.locks.removeRemoteLocked(id, lockId),
|
|
158
|
-
closeConnection: (peerDescriptor: PeerDescriptor, gracefulLeave: boolean, reason?: string) =>
|
|
159
|
-
this.closeConnection(peerDescriptor, gracefulLeave, reason),
|
|
160
|
-
getLocalPeerDescriptor: () => this.getLocalPeerDescriptor(),
|
|
161
|
-
setPrivate: (id: DhtAddress, isPrivate: boolean) => {
|
|
162
|
-
if (!this.options.allowIncomingPrivateConnections) {
|
|
163
|
-
logger.debug(`node ${id} attemted to set a connection as private, but it is not allowed`)
|
|
164
|
-
return
|
|
165
|
-
}
|
|
166
|
-
if (isPrivate) {
|
|
167
|
-
this.locks.addPrivate(id)
|
|
168
|
-
} else {
|
|
169
|
-
this.locks.removePrivate(id)
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
})
|
|
173
|
-
this.rpcCommunicator.registerRpcMethod(LockRequest, LockResponse, 'lockRequest',
|
|
174
|
-
(req: LockRequest, context: ServerCallContext) => lockRpcLocal.lockRequest(req, context))
|
|
175
|
-
this.rpcCommunicator.registerRpcNotification(UnlockRequest, 'unlockRequest',
|
|
176
|
-
(req: UnlockRequest, context: ServerCallContext) => lockRpcLocal.unlockRequest(req, context))
|
|
177
|
-
this.rpcCommunicator.registerRpcNotification(DisconnectNotice, 'gracefulDisconnect',
|
|
178
|
-
(req: DisconnectNotice, context: ServerCallContext) => lockRpcLocal.gracefulDisconnect(req, context))
|
|
179
|
-
this.rpcCommunicator.registerRpcNotification(SetPrivateRequest, 'setPrivate',
|
|
180
|
-
(req: SetPrivateRequest, context: ServerCallContext) => lockRpcLocal.setPrivate(req, context))
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/*
|
|
184
|
-
* Removes connections if there are more than maxConnections: in that case we remove unlocked connections
|
|
185
|
-
* which hasn't been used within maxIdleTime.
|
|
186
|
-
*/
|
|
187
|
-
public garbageCollectConnections(maxConnections: number, maxIdleTime: number): void {
|
|
188
|
-
if (this.endpoints.size <= maxConnections) {
|
|
189
|
-
return
|
|
190
|
-
}
|
|
191
|
-
const disconnectionCandidates = new SortedContactList<ManagedConnection>({
|
|
192
|
-
referenceId: toNodeId(this.getLocalPeerDescriptor()),
|
|
193
|
-
maxSize: 100000, // TODO use options option or named constant?
|
|
194
|
-
allowToContainReferenceId: false
|
|
195
|
-
})
|
|
196
|
-
this.endpoints.forEach((endpoint) => {
|
|
197
|
-
if (endpoint.connected) {
|
|
198
|
-
const connection = endpoint.connection
|
|
199
|
-
const nodeId = connection.getNodeId()
|
|
200
|
-
if (!this.locks.isLocked(nodeId) && !this.locks.isPrivate(nodeId) && Date.now() - connection.getLastUsedTimestamp() > maxIdleTime) {
|
|
201
|
-
logger.trace('disconnecting in timeout interval: ' + getNodeIdOrUnknownFromPeerDescriptor(connection.getPeerDescriptor()))
|
|
202
|
-
disconnectionCandidates.addContact(connection)
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
})
|
|
206
|
-
const disconnectables = disconnectionCandidates.getFurthestContacts(this.endpoints.size - maxConnections)
|
|
207
|
-
for (const disconnectable of disconnectables) {
|
|
208
|
-
const peerDescriptor = disconnectable.getPeerDescriptor()!
|
|
209
|
-
logger.trace('garbageCollecting ' + toNodeId(peerDescriptor))
|
|
210
|
-
this.gracefullyDisconnectAsync(peerDescriptor, DisconnectMode.NORMAL).catch((_e) => { })
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
public async start(): Promise<void> {
|
|
215
|
-
if (this.state === ConnectionManagerState.RUNNING || this.state === ConnectionManagerState.STOPPED) {
|
|
216
|
-
throw new Err.CouldNotStart(`Cannot start already ${this.state} module`)
|
|
217
|
-
}
|
|
218
|
-
this.state = ConnectionManagerState.RUNNING
|
|
219
|
-
logger.trace(`Starting ConnectionManager...`)
|
|
220
|
-
await this.connectorFacade.start(
|
|
221
|
-
(connection: PendingConnection) => this.onNewConnection(connection),
|
|
222
|
-
(nodeId: DhtAddress) => this.hasConnection(nodeId),
|
|
223
|
-
this
|
|
224
|
-
)
|
|
225
|
-
// Garbage collection of connections
|
|
226
|
-
this.disconnectorIntervalRef = setInterval(() => {
|
|
227
|
-
logger.trace('disconnectorInterval')
|
|
228
|
-
const LAST_USED_LIMIT = 20000
|
|
229
|
-
this.garbageCollectConnections(this.options.maxConnections ?? 80, LAST_USED_LIMIT)
|
|
230
|
-
}, 5000) // TODO use options option or named constant?
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
public async stop(): Promise<void> {
|
|
234
|
-
if (this.state === ConnectionManagerState.STOPPED || this.state === ConnectionManagerState.STOPPING) {
|
|
235
|
-
return
|
|
236
|
-
}
|
|
237
|
-
this.state = ConnectionManagerState.STOPPING
|
|
238
|
-
logger.trace(`Stopping ConnectionManager`)
|
|
239
|
-
if (this.disconnectorIntervalRef) {
|
|
240
|
-
clearInterval(this.disconnectorIntervalRef)
|
|
241
|
-
}
|
|
242
|
-
await Promise.all(Array.from(this.endpoints.values()).map(async (endpoint) => {
|
|
243
|
-
if (endpoint.connected) {
|
|
244
|
-
try {
|
|
245
|
-
await this.gracefullyDisconnectAsync(endpoint.connection.getPeerDescriptor()!, DisconnectMode.LEAVING)
|
|
246
|
-
} catch (e) {
|
|
247
|
-
logger.error(e)
|
|
248
|
-
}
|
|
249
|
-
} else {
|
|
250
|
-
const connection = endpoint.connection
|
|
251
|
-
logger.trace('handshake of connection not completed, force-closing')
|
|
252
|
-
// TODO use options option or named constant?
|
|
253
|
-
const eventReceived = waitForEvent3(connection as any, 'disconnected', 2000)
|
|
254
|
-
// TODO should we have some handling for this floating promise?
|
|
255
|
-
connection.close(true)
|
|
256
|
-
try {
|
|
257
|
-
await eventReceived
|
|
258
|
-
logger.trace('resolving after receiving disconnected event from non-handshaked connection')
|
|
259
|
-
} catch (e) {
|
|
260
|
-
endpoint.buffer.reject()
|
|
261
|
-
logger.trace('force-closing non-handshaked connection timed out ' + e)
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}))
|
|
265
|
-
await this.connectorFacade.stop()
|
|
266
|
-
this.state = ConnectionManagerState.STOPPED
|
|
267
|
-
this.rpcCommunicator!.stop()
|
|
268
|
-
this.duplicateMessageDetector.clear()
|
|
269
|
-
this.locks.clear()
|
|
270
|
-
this.removeAllListeners()
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
public getLocalLockedConnectionCount(): number {
|
|
274
|
-
return this.locks.getLocalLockedConnectionCount()
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
public getRemoteLockedConnectionCount(): number {
|
|
278
|
-
return this.locks.getRemoteLockedConnectionCount()
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
public getWeakLockedConnectionCount(): number {
|
|
282
|
-
return this.locks.getWeakLockedConnectionCount()
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
public async send(message: Message, opts: SendOptions = DEFAULT_SEND_OPTIONS): Promise<void> {
|
|
286
|
-
if ((this.state === ConnectionManagerState.STOPPED || this.state === ConnectionManagerState.STOPPING) && !opts.sendIfStopped) {
|
|
287
|
-
return
|
|
288
|
-
}
|
|
289
|
-
const peerDescriptor = message.targetDescriptor!
|
|
290
|
-
if (this.isConnectionToSelf(peerDescriptor)) {
|
|
291
|
-
throw new Err.CannotConnectToSelf('Cannot send to self')
|
|
292
|
-
}
|
|
293
|
-
const nodeId = toNodeId(peerDescriptor)
|
|
294
|
-
logger.trace(`Sending message to: ${nodeId}`)
|
|
295
|
-
message = {
|
|
296
|
-
...message,
|
|
297
|
-
sourceDescriptor: this.getLocalPeerDescriptor()
|
|
298
|
-
}
|
|
299
|
-
let connection = this.endpoints.get(nodeId)?.connection
|
|
300
|
-
if (!connection && opts.connect) {
|
|
301
|
-
connection = this.connectorFacade.createConnection(peerDescriptor)
|
|
302
|
-
this.onNewConnection(connection)
|
|
303
|
-
} else if (!connection || (connection && !this.endpoints.get(nodeId)!.connected && !opts.connect)) {
|
|
304
|
-
throw new Err.SendFailed('No connection to target, connect flag is false')
|
|
305
|
-
}
|
|
306
|
-
const binary = Message.toBinary(message)
|
|
307
|
-
this.metrics.sendBytesPerSecond.record(binary.byteLength)
|
|
308
|
-
this.metrics.sendMessagesPerSecond.record(1)
|
|
309
|
-
|
|
310
|
-
if (this.endpoints.get(nodeId)!.connected) {
|
|
311
|
-
(connection as ManagedConnection).send(binary)
|
|
312
|
-
} else {
|
|
313
|
-
return (this.endpoints.get(nodeId)! as ConnectingEndpoint).buffer.push(binary)
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
private isConnectionToSelf(peerDescriptor: PeerDescriptor): boolean {
|
|
318
|
-
return areEqualPeerDescriptors(peerDescriptor, this.getLocalPeerDescriptor()) || this.isOwnWebsocketServer(peerDescriptor)
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
private isOwnWebsocketServer(peerDescriptor: PeerDescriptor): boolean {
|
|
322
|
-
const localPeerDescriptor = this.getLocalPeerDescriptor()
|
|
323
|
-
if ((peerDescriptor.websocket !== undefined) && (localPeerDescriptor.websocket !== undefined)) {
|
|
324
|
-
return ((peerDescriptor.websocket.port === localPeerDescriptor.websocket.port)
|
|
325
|
-
&& (peerDescriptor.websocket.host === localPeerDescriptor.websocket.host))
|
|
326
|
-
} else {
|
|
327
|
-
return false
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
public getLocalPeerDescriptor(): PeerDescriptor {
|
|
332
|
-
return this.connectorFacade.getLocalPeerDescriptor()!
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
public hasConnection(nodeId: DhtAddress): boolean {
|
|
336
|
-
// TODO if we remove filtering in getConnections, this can just be this.connection.has(nodeId)
|
|
337
|
-
return this.getConnections().some((c) => toNodeId(c) == nodeId)
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
public getConnectionCount(): number {
|
|
341
|
-
// TODO if we remove filtering in getConnections, this can just be this.connection.length
|
|
342
|
-
return this.getConnections().length
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
public hasLocalLockedConnection(nodeId: DhtAddress): boolean {
|
|
346
|
-
return this.locks.isLocalLocked(nodeId)
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
public hasRemoteLockedConnection(nodeId: DhtAddress): boolean {
|
|
350
|
-
return this.locks.isRemoteLocked(nodeId)
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
private handleMessage(message: Message): void {
|
|
354
|
-
const messageType = message.body.oneofKind
|
|
355
|
-
logger.trace('Received message of type ' + messageType)
|
|
356
|
-
if (messageType !== 'rpcMessage') {
|
|
357
|
-
logger.trace('Filtered out non-RPC message of type ' + messageType)
|
|
358
|
-
return
|
|
359
|
-
}
|
|
360
|
-
if (this.duplicateMessageDetector.isMostLikelyDuplicate(message.messageId)) {
|
|
361
|
-
logger.trace('handleMessage filtered duplicate ' + toNodeId(message.sourceDescriptor!)
|
|
362
|
-
+ ' ' + message.serviceId + ' ' + message.messageId)
|
|
363
|
-
return
|
|
364
|
-
}
|
|
365
|
-
this.duplicateMessageDetector.add(message.messageId)
|
|
366
|
-
if (message.serviceId === INTERNAL_SERVICE_ID) {
|
|
367
|
-
this.rpcCommunicator?.handleMessageFromPeer(message)
|
|
368
|
-
} else {
|
|
369
|
-
logger.trace('emit "message" ' + toNodeId(message.sourceDescriptor!)
|
|
370
|
-
+ ' ' + message.serviceId + ' ' + message.messageId)
|
|
371
|
-
this.emit('message', message)
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
private onData(data: Uint8Array, peerDescriptor: PeerDescriptor): void {
|
|
376
|
-
if (this.state === ConnectionManagerState.STOPPED) {
|
|
377
|
-
return
|
|
378
|
-
}
|
|
379
|
-
this.metrics.receiveBytesPerSecond.record(data.byteLength)
|
|
380
|
-
this.metrics.receiveMessagesPerSecond.record(1)
|
|
381
|
-
let message: Message | undefined
|
|
382
|
-
try {
|
|
383
|
-
message = Message.fromBinary(data)
|
|
384
|
-
} catch (e) {
|
|
385
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
386
|
-
logger.debug(`Parsing incoming data into Message failed: ${e}`)
|
|
387
|
-
return
|
|
388
|
-
}
|
|
389
|
-
message.sourceDescriptor = peerDescriptor
|
|
390
|
-
try {
|
|
391
|
-
this.handleMessage(message)
|
|
392
|
-
} catch (e) {
|
|
393
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
394
|
-
logger.debug(`Handling incoming data failed: ${e}`)
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
private onConnected(peerDescriptor: PeerDescriptor, connection: IConnection) {
|
|
399
|
-
const managedConnection = new ManagedConnection(peerDescriptor, connection)
|
|
400
|
-
managedConnection.on('managedData', this.onData)
|
|
401
|
-
managedConnection.once('disconnected', (gracefulLeave: boolean) => this.onDisconnected(peerDescriptor, gracefulLeave))
|
|
402
|
-
|
|
403
|
-
const nodeId = toNodeId(peerDescriptor)
|
|
404
|
-
const endpoint = this.endpoints.get(nodeId)! as ConnectingEndpoint
|
|
405
|
-
const outputBuffer = endpoint.buffer
|
|
406
|
-
const pendingConnection = endpoint.connection
|
|
407
|
-
const buffer = outputBuffer.getBuffer()
|
|
408
|
-
while (buffer.length > 0) {
|
|
409
|
-
logger.trace('emptying buffer')
|
|
410
|
-
managedConnection.send(buffer.shift()!)
|
|
411
|
-
}
|
|
412
|
-
outputBuffer.resolve()
|
|
413
|
-
pendingConnection.destroy()
|
|
414
|
-
this.endpoints.set(nodeId, {
|
|
415
|
-
connected: true,
|
|
416
|
-
connection: managedConnection
|
|
417
|
-
})
|
|
418
|
-
if (this.privateClientMode) {
|
|
419
|
-
this.setPrivateForConnection(peerDescriptor, this.privateClientMode).catch(() => {})
|
|
420
|
-
}
|
|
421
|
-
this.emit('connected', peerDescriptor)
|
|
422
|
-
this.onConnectionCountChange()
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
private onDisconnected(peerDescriptor: PeerDescriptor, gracefulLeave: boolean) {
|
|
426
|
-
const nodeId = toNodeId(peerDescriptor)
|
|
427
|
-
logger.trace(nodeId + ' onDisconnected() gracefulLeave: ' + gracefulLeave)
|
|
428
|
-
const endpoint = this.endpoints.get(nodeId)
|
|
429
|
-
if (endpoint) {
|
|
430
|
-
this.locks.clearAllLocks(nodeId)
|
|
431
|
-
if (endpoint.connected === false) {
|
|
432
|
-
endpoint.buffer.reject()
|
|
433
|
-
}
|
|
434
|
-
this.endpoints.delete(nodeId)
|
|
435
|
-
logger.trace(nodeId + ' deleted connection in onDisconnected() gracefulLeave: ' + gracefulLeave)
|
|
436
|
-
this.emit('disconnected', peerDescriptor, gracefulLeave)
|
|
437
|
-
this.onConnectionCountChange()
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
private onNewConnection(connection: PendingConnection): boolean {
|
|
442
|
-
if (this.state === ConnectionManagerState.STOPPED) {
|
|
443
|
-
return false
|
|
444
|
-
}
|
|
445
|
-
logger.trace('onNewConnection()')
|
|
446
|
-
if (!this.acceptNewConnection(connection)) {
|
|
447
|
-
return false
|
|
448
|
-
}
|
|
449
|
-
connection.once('connected', (peerDescriptor: PeerDescriptor, connection: IConnection) => this.onConnected(peerDescriptor, connection))
|
|
450
|
-
connection.once('disconnected', (gracefulLeave: boolean) => this.onDisconnected(connection.getPeerDescriptor(), gracefulLeave))
|
|
451
|
-
return true
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
private acceptNewConnection(newConnection: PendingConnection): boolean {
|
|
455
|
-
const nodeId = toNodeId(newConnection.getPeerDescriptor())
|
|
456
|
-
logger.trace(nodeId + ' acceptNewConnection()')
|
|
457
|
-
if (this.endpoints.has(nodeId)) {
|
|
458
|
-
if (getOfferer(toNodeId(this.getLocalPeerDescriptor()), nodeId) === 'remote') {
|
|
459
|
-
let buffer: OutputBuffer | undefined
|
|
460
|
-
const endpoint = this.endpoints.get(nodeId)!
|
|
461
|
-
// This is a rare occurance but it does happen from time to time.
|
|
462
|
-
// Could be related to WS client connections not realizing that they have been disconnected.
|
|
463
|
-
// Makes refactoring duplicate connection handling to the connectors very difficult.
|
|
464
|
-
if (this.endpoints.get(nodeId)!.connected) {
|
|
465
|
-
logger.debug('replacing connected connection', { nodeId })
|
|
466
|
-
buffer = new OutputBuffer()
|
|
467
|
-
} else {
|
|
468
|
-
buffer = (endpoint as ConnectingEndpoint).buffer
|
|
469
|
-
}
|
|
470
|
-
const oldConnection = endpoint.connection
|
|
471
|
-
logger.trace('replaced: ' + nodeId)
|
|
472
|
-
|
|
473
|
-
oldConnection.replaceAsDuplicate()
|
|
474
|
-
this.endpoints.set(nodeId, { connected: false, connection: newConnection, buffer: buffer })
|
|
475
|
-
return true
|
|
476
|
-
} else {
|
|
477
|
-
return false
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
logger.trace(nodeId + ' added to connections at acceptNewConnection')
|
|
482
|
-
this.endpoints.set(nodeId, {
|
|
483
|
-
connected: false,
|
|
484
|
-
buffer: new OutputBuffer(),
|
|
485
|
-
connection: newConnection
|
|
486
|
-
})
|
|
487
|
-
|
|
488
|
-
return true
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
private async closeConnection(peerDescriptor: PeerDescriptor, gracefulLeave: boolean, reason?: string): Promise<void> {
|
|
492
|
-
const nodeId = toNodeId(peerDescriptor)
|
|
493
|
-
logger.trace(nodeId + ' ' + 'closeConnection() ' + reason)
|
|
494
|
-
this.locks.clearAllLocks(nodeId)
|
|
495
|
-
if (this.endpoints.has(nodeId)) {
|
|
496
|
-
const connectionToClose = this.endpoints.get(nodeId)!.connection
|
|
497
|
-
await connectionToClose.close(gracefulLeave)
|
|
498
|
-
} else {
|
|
499
|
-
logger.trace(nodeId + ' ' + 'closeConnection() this.endpoints did not have the id')
|
|
500
|
-
this.emit('disconnected', peerDescriptor, false)
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
public lockConnection(targetDescriptor: PeerDescriptor, lockId: LockID): void {
|
|
505
|
-
if (this.state === ConnectionManagerState.STOPPED || areEqualPeerDescriptors(targetDescriptor, this.getLocalPeerDescriptor())) {
|
|
506
|
-
return
|
|
507
|
-
}
|
|
508
|
-
const nodeId = toNodeId(targetDescriptor)
|
|
509
|
-
const rpcRemote = new ConnectionLockRpcRemote(
|
|
510
|
-
this.getLocalPeerDescriptor(),
|
|
511
|
-
targetDescriptor,
|
|
512
|
-
this.rpcCommunicator!,
|
|
513
|
-
ConnectionLockRpcClient
|
|
514
|
-
)
|
|
515
|
-
this.locks.addLocalLocked(nodeId, lockId)
|
|
516
|
-
rpcRemote.lockRequest(lockId)
|
|
517
|
-
.then((_accepted) => logger.trace('LockRequest successful'))
|
|
518
|
-
.catch((err) => { logger.debug(err) })
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
public unlockConnection(targetDescriptor: PeerDescriptor, lockId: LockID): void {
|
|
522
|
-
if (this.state === ConnectionManagerState.STOPPED || areEqualPeerDescriptors(targetDescriptor, this.getLocalPeerDescriptor())) {
|
|
523
|
-
return
|
|
524
|
-
}
|
|
525
|
-
const nodeId = toNodeId(targetDescriptor)
|
|
526
|
-
this.locks.removeLocalLocked(nodeId, lockId)
|
|
527
|
-
const rpcRemote = new ConnectionLockRpcRemote(
|
|
528
|
-
this.getLocalPeerDescriptor(),
|
|
529
|
-
targetDescriptor,
|
|
530
|
-
this.rpcCommunicator!,
|
|
531
|
-
ConnectionLockRpcClient
|
|
532
|
-
)
|
|
533
|
-
if (this.endpoints.has(nodeId)) {
|
|
534
|
-
rpcRemote.unlockRequest(lockId)
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
public weakLockConnection(nodeId: DhtAddress, lockId: LockID): void {
|
|
539
|
-
if (this.state === ConnectionManagerState.STOPPED || (nodeId === toNodeId(this.getLocalPeerDescriptor()))) {
|
|
540
|
-
return
|
|
541
|
-
}
|
|
542
|
-
this.locks.addWeakLocked(nodeId, lockId)
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
public weakUnlockConnection(nodeId: DhtAddress, lockId: LockID): void {
|
|
546
|
-
if (this.state === ConnectionManagerState.STOPPED || (nodeId === toNodeId(this.getLocalPeerDescriptor()))) {
|
|
547
|
-
return
|
|
548
|
-
}
|
|
549
|
-
this.locks.removeWeakLocked(nodeId, lockId)
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
public async enablePrivateClientMode(): Promise<void> {
|
|
553
|
-
this.privateClientMode = true
|
|
554
|
-
await Promise.all(Array.from(this.endpoints.values()).map((endpoint) => {
|
|
555
|
-
if (endpoint.connected) {
|
|
556
|
-
const peerDescription = endpoint.connection.getPeerDescriptor()
|
|
557
|
-
return this.setPrivateForConnection(peerDescription!, true)
|
|
558
|
-
}
|
|
559
|
-
}))
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
public async disablePrivateClientMode(): Promise<void> {
|
|
563
|
-
this.privateClientMode = false
|
|
564
|
-
await Promise.all(Array.from(this.endpoints.values()).map((endpoint) => {
|
|
565
|
-
if (endpoint.connected) {
|
|
566
|
-
const peerDescription = endpoint.connection.getPeerDescriptor()
|
|
567
|
-
return this.setPrivateForConnection(peerDescription!, false)
|
|
568
|
-
}
|
|
569
|
-
}))
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
public isPrivateClientMode(): boolean {
|
|
573
|
-
return this.privateClientMode
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
private async setPrivateForConnection(targetDescriptor: PeerDescriptor, isPrivate: boolean): Promise<void> {
|
|
577
|
-
const rpcRemote = new ConnectionLockRpcRemote(
|
|
578
|
-
this.getLocalPeerDescriptor(),
|
|
579
|
-
targetDescriptor,
|
|
580
|
-
this.rpcCommunicator!,
|
|
581
|
-
ConnectionLockRpcClient
|
|
582
|
-
)
|
|
583
|
-
await rpcRemote.setPrivate(isPrivate)
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
private async gracefullyDisconnectAsync(targetDescriptor: PeerDescriptor, disconnectMode: DisconnectMode): Promise<void> {
|
|
587
|
-
const endpoint = this.endpoints.get(toNodeId(targetDescriptor))
|
|
588
|
-
|
|
589
|
-
if (!endpoint) {
|
|
590
|
-
logger.debug('gracefullyDisconnectedAsync() tried on a non-existing connection')
|
|
591
|
-
return
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
if (endpoint.connected) {
|
|
595
|
-
const connection = endpoint.connection
|
|
596
|
-
const promise = new Promise<void>((resolve, _reject) => {
|
|
597
|
-
// TODO use options option or named constant?
|
|
598
|
-
// eslint-disable-next-line promise/catch-or-return
|
|
599
|
-
waitForEvent3<ManagedConnectionEvents>(connection, 'disconnected', 2000).then(() => {
|
|
600
|
-
logger.trace('disconnected event received in gracefullyDisconnectAsync()')
|
|
601
|
-
})
|
|
602
|
-
.catch((e) => {
|
|
603
|
-
logger.trace('force-closing connection after timeout ' + e)
|
|
604
|
-
// TODO should we have some handling for this floating promise?
|
|
605
|
-
connection.close(true)
|
|
606
|
-
})
|
|
607
|
-
.finally(() => {
|
|
608
|
-
logger.trace('resolving after receiving disconnected event')
|
|
609
|
-
resolve()
|
|
610
|
-
})
|
|
611
|
-
})
|
|
612
|
-
|
|
613
|
-
await Promise.all([
|
|
614
|
-
promise,
|
|
615
|
-
this.doGracefullyDisconnectAsync(targetDescriptor, disconnectMode)
|
|
616
|
-
])
|
|
617
|
-
} else {
|
|
618
|
-
endpoint.connection.close(true)
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
private async doGracefullyDisconnectAsync(targetDescriptor: PeerDescriptor, disconnectMode: DisconnectMode): Promise<void> {
|
|
624
|
-
const nodeId = toNodeId(targetDescriptor)
|
|
625
|
-
logger.trace(nodeId + ' gracefullyDisconnectAsync()')
|
|
626
|
-
const rpcRemote = new ConnectionLockRpcRemote(
|
|
627
|
-
this.getLocalPeerDescriptor(),
|
|
628
|
-
targetDescriptor,
|
|
629
|
-
this.rpcCommunicator!,
|
|
630
|
-
ConnectionLockRpcClient
|
|
631
|
-
)
|
|
632
|
-
try {
|
|
633
|
-
await rpcRemote.gracefulDisconnect(disconnectMode)
|
|
634
|
-
} catch (ex) {
|
|
635
|
-
logger.trace(nodeId + ' remote.gracefulDisconnect() failed' + ex)
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
public getConnections(): PeerDescriptor[] {
|
|
640
|
-
return Array.from(this.endpoints.values())
|
|
641
|
-
.map((endpoint) => endpoint)
|
|
642
|
-
// TODO is this filtering needed? (if it is, should we do the same filtering e.g.
|
|
643
|
-
// in getConnection() or in other methods which access this.endpoints directly?)
|
|
644
|
-
.filter((endpoint) => endpoint.connected && !this.locks.isPrivate(toNodeId(endpoint.connection.getPeerDescriptor()!)))
|
|
645
|
-
.map((endpoint) => endpoint.connection.getPeerDescriptor()!)
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
private onConnectionCountChange() {
|
|
649
|
-
this.metrics.connectionAverageCount.record(this.endpoints.size)
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
public getDiagnosticInfo(): Record<string, unknown> {
|
|
653
|
-
const managedConnections: ManagedConnection[] = Array.from(this.endpoints.values())
|
|
654
|
-
.filter((endpoint) => endpoint.connected)
|
|
655
|
-
.map((endpoint) => endpoint.connection)
|
|
656
|
-
return {
|
|
657
|
-
connections: managedConnections.map((connection) => connection.getDiagnosticInfo()),
|
|
658
|
-
connectionCount: this.endpoints.size
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { DhtAddress } from '../identifiers'
|
|
2
|
-
import { PeerDescriptor } from '../../generated/packages/dht/protos/DhtRpc'
|
|
3
|
-
|
|
4
|
-
export interface ConnectionsView {
|
|
5
|
-
getConnections: () => PeerDescriptor[]
|
|
6
|
-
getConnectionCount: () => number
|
|
7
|
-
hasConnection: (nodeId: DhtAddress) => boolean
|
|
8
|
-
}
|