@streamr/dht 102.0.0-beta.1 → 102.0.0-beta.2

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 (210) hide show
  1. package/dist/generated/google/protobuf/any.d.ts +180 -0
  2. package/dist/generated/google/protobuf/any.js +155 -0
  3. package/dist/generated/google/protobuf/any.js.map +1 -0
  4. package/dist/generated/google/protobuf/empty.d.ts +31 -0
  5. package/dist/generated/google/protobuf/empty.js +32 -0
  6. package/dist/generated/google/protobuf/empty.js.map +1 -0
  7. package/dist/generated/google/protobuf/timestamp.d.ts +155 -0
  8. package/dist/generated/google/protobuf/timestamp.js +136 -0
  9. package/dist/generated/google/protobuf/timestamp.js.map +1 -0
  10. package/dist/generated/packages/dht/protos/DhtRpc.client.d.ts +361 -0
  11. package/dist/generated/packages/dht/protos/DhtRpc.client.js +285 -0
  12. package/dist/generated/packages/dht/protos/DhtRpc.client.js.map +1 -0
  13. package/dist/generated/packages/dht/protos/DhtRpc.d.ts +999 -0
  14. package/dist/generated/packages/dht/protos/DhtRpc.js +677 -0
  15. package/dist/generated/packages/dht/protos/DhtRpc.js.map +1 -0
  16. package/dist/generated/packages/dht/protos/DhtRpc.server.d.ts +162 -0
  17. package/dist/generated/packages/dht/protos/DhtRpc.server.js +3 -0
  18. package/dist/generated/packages/dht/protos/DhtRpc.server.js.map +1 -0
  19. package/dist/generated/packages/proto-rpc/protos/ProtoRpc.d.ts +87 -0
  20. package/dist/generated/packages/proto-rpc/protos/ProtoRpc.js +66 -0
  21. package/dist/generated/packages/proto-rpc/protos/ProtoRpc.js.map +1 -0
  22. package/dist/package.json +7 -7
  23. package/package.json +7 -7
  24. package/src/connection/Connection.ts +0 -28
  25. package/src/connection/ConnectionLockRpcLocal.ts +0 -78
  26. package/src/connection/ConnectionLockRpcRemote.ts +0 -64
  27. package/src/connection/ConnectionLockStates.ts +0 -131
  28. package/src/connection/ConnectionManager.ts +0 -661
  29. package/src/connection/ConnectionsView.ts +0 -8
  30. package/src/connection/ConnectorFacade.ts +0 -217
  31. package/src/connection/Handshaker.ts +0 -209
  32. package/src/connection/IConnection.ts +0 -40
  33. package/src/connection/ManagedConnection.ts +0 -113
  34. package/src/connection/OutputBuffer.ts +0 -28
  35. package/src/connection/PendingConnection.ts +0 -68
  36. package/src/connection/connectivityChecker.ts +0 -108
  37. package/src/connection/connectivityRequestHandler.ts +0 -116
  38. package/src/connection/simulator/Simulator.ts +0 -369
  39. package/src/connection/simulator/SimulatorConnection.ts +0 -137
  40. package/src/connection/simulator/SimulatorConnector.ts +0 -98
  41. package/src/connection/simulator/SimulatorTransport.ts +0 -15
  42. package/src/connection/simulator/pings.ts +0 -42
  43. package/src/connection/webrtc/BrowserWebrtcConnection.ts +0 -242
  44. package/src/connection/webrtc/IWebrtcConnection.ts +0 -24
  45. package/src/connection/webrtc/NodeWebrtcConnection.ts +0 -245
  46. package/src/connection/webrtc/WebrtcConnector.ts +0 -234
  47. package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +0 -108
  48. package/src/connection/webrtc/WebrtcConnectorRpcRemote.ts +0 -60
  49. package/src/connection/webrtc/iceServerAsString.ts +0 -15
  50. package/src/connection/websocket/AbstractWebsocketClientConnection.ts +0 -122
  51. package/src/connection/websocket/AutoCertifierClientFacade.ts +0 -89
  52. package/src/connection/websocket/BrowserWebsocketClientConnection.ts +0 -44
  53. package/src/connection/websocket/NodeWebsocketClientConnection.ts +0 -39
  54. package/src/connection/websocket/WebsocketClientConnector.ts +0 -119
  55. package/src/connection/websocket/WebsocketClientConnectorRpcLocal.ts +0 -38
  56. package/src/connection/websocket/WebsocketClientConnectorRpcRemote.ts +0 -19
  57. package/src/connection/websocket/WebsocketServer.ts +0 -164
  58. package/src/connection/websocket/WebsocketServerConnection.ts +0 -109
  59. package/src/connection/websocket/WebsocketServerConnector.ts +0 -290
  60. package/src/dht/DhtNode.ts +0 -683
  61. package/src/dht/DhtNodeRpcLocal.ts +0 -84
  62. package/src/dht/DhtNodeRpcRemote.ts +0 -107
  63. package/src/dht/ExternalApiRpcLocal.ts +0 -58
  64. package/src/dht/ExternalApiRpcRemote.ts +0 -41
  65. package/src/dht/PeerManager.ts +0 -305
  66. package/src/dht/contact/Contact.ts +0 -19
  67. package/src/dht/contact/ContactList.ts +0 -43
  68. package/src/dht/contact/RandomContactList.ts +0 -56
  69. package/src/dht/contact/RingContactList.ts +0 -143
  70. package/src/dht/contact/RpcRemote.ts +0 -72
  71. package/src/dht/contact/SortedContactList.ts +0 -173
  72. package/src/dht/contact/getClosestNodes.ts +0 -24
  73. package/src/dht/contact/ringIdentifiers.ts +0 -62
  74. package/src/dht/discovery/DiscoverySession.ts +0 -129
  75. package/src/dht/discovery/PeerDiscovery.ts +0 -244
  76. package/src/dht/discovery/RingDiscoverySession.ts +0 -148
  77. package/src/dht/recursive-operation/RecursiveOperationManager.ts +0 -251
  78. package/src/dht/recursive-operation/RecursiveOperationRpcLocal.ts +0 -34
  79. package/src/dht/recursive-operation/RecursiveOperationRpcRemote.ts +0 -43
  80. package/src/dht/recursive-operation/RecursiveOperationSession.ts +0 -231
  81. package/src/dht/recursive-operation/RecursiveOperationSessionRpcLocal.ts +0 -35
  82. package/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.ts +0 -30
  83. package/src/dht/routing/DuplicateDetector.ts +0 -34
  84. package/src/dht/routing/Router.ts +0 -246
  85. package/src/dht/routing/RouterRpcLocal.ts +0 -78
  86. package/src/dht/routing/RouterRpcRemote.ts +0 -80
  87. package/src/dht/routing/RoutingSession.ts +0 -243
  88. package/src/dht/routing/RoutingTablesCache.ts +0 -60
  89. package/src/dht/routing/getPreviousPeer.ts +0 -6
  90. package/src/dht/store/LocalDataStore.ts +0 -84
  91. package/src/dht/store/StoreManager.ts +0 -170
  92. package/src/dht/store/StoreRpcLocal.ts +0 -89
  93. package/src/dht/store/StoreRpcRemote.ts +0 -32
  94. package/src/exports.ts +0 -33
  95. package/src/helpers/AddressTools.ts +0 -28
  96. package/src/helpers/Connectivity.ts +0 -19
  97. package/src/helpers/browser/isBrowserEnvironment.ts +0 -1
  98. package/src/helpers/browser/isBrowserEnvironment_override.ts +0 -3
  99. package/src/helpers/createPeerDescriptor.ts +0 -57
  100. package/src/helpers/createPeerDescriptorSignaturePayload.ts +0 -28
  101. package/src/helpers/debugHelpers.ts +0 -9
  102. package/src/helpers/errors.ts +0 -49
  103. package/src/helpers/offering.ts +0 -15
  104. package/src/helpers/protoClasses.ts +0 -57
  105. package/src/helpers/protoToString.ts +0 -21
  106. package/src/helpers/version.ts +0 -32
  107. package/src/identifiers.ts +0 -29
  108. package/src/rpc-protocol/DhtCallContext.ts +0 -14
  109. package/src/rpc-protocol/DhtRpcOptions.ts +0 -10
  110. package/src/transport/ITransport.ts +0 -37
  111. package/src/transport/ListeningRpcCommunicator.ts +0 -32
  112. package/src/transport/RoutingRpcCommunicator.ts +0 -66
  113. package/src/types/ServiceID.ts +0 -1
  114. package/src/types/textencoding.d.ts +0 -6
  115. package/test/benchmark/Find.test.ts +0 -72
  116. package/test/benchmark/KademliaCorrectness.test.ts +0 -114
  117. package/test/benchmark/RingCorrectness.test.ts +0 -157
  118. package/test/benchmark/SortedContactListBenchmark.test.ts +0 -108
  119. package/test/benchmark/WebsocketServerMemoryLeak.test.ts +0 -41
  120. package/test/benchmark/hybrid-network-simulation/RingContactList.test.ts +0 -71
  121. package/test/end-to-end/GeoIpLayer0.test.ts +0 -55
  122. package/test/end-to-end/Layer0-Layer1.test.ts +0 -93
  123. package/test/end-to-end/Layer0.test.ts +0 -76
  124. package/test/end-to-end/Layer0MixedConnectionTypes.test.ts +0 -110
  125. package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +0 -137
  126. package/test/end-to-end/Layer0Webrtc.test.ts +0 -85
  127. package/test/end-to-end/Layer1-Scale-WebSocket.test.ts +0 -82
  128. package/test/end-to-end/Layer1-Scale-Webrtc.test.ts +0 -76
  129. package/test/end-to-end/RecoveryFromFailedAutoCertification.test.ts +0 -52
  130. package/test/end-to-end/WebsocketConnectionRequest.test.ts +0 -69
  131. package/test/end-to-end/memory-leak.test.ts +0 -80
  132. package/test/integration/ConnectionLocking.test.ts +0 -192
  133. package/test/integration/ConnectionManager.test.ts +0 -528
  134. package/test/integration/ConnectivityChecking.test.ts +0 -53
  135. package/test/integration/DhtJoinPeerDiscovery.test.ts +0 -49
  136. package/test/integration/DhtNode.test.ts +0 -66
  137. package/test/integration/DhtNodeExternalAPI.test.ts +0 -48
  138. package/test/integration/DhtNodeRpcRemote.test.ts +0 -66
  139. package/test/integration/DhtRpc.test.ts +0 -121
  140. package/test/integration/Find.test.ts +0 -45
  141. package/test/integration/GeoIpConnectivityChecking.test.ts +0 -72
  142. package/test/integration/Layer1-scale.test.ts +0 -189
  143. package/test/integration/Mock-Layer1-Layer0.test.ts +0 -85
  144. package/test/integration/MultipleEntryPointJoining.test.ts +0 -105
  145. package/test/integration/ReplicateData.test.ts +0 -104
  146. package/test/integration/RouteMessage.test.ts +0 -230
  147. package/test/integration/RouterRpcRemote.test.ts +0 -77
  148. package/test/integration/SimultaneousConnections.test.ts +0 -316
  149. package/test/integration/Store.test.ts +0 -85
  150. package/test/integration/StoreAndDelete.test.ts +0 -77
  151. package/test/integration/StoreOnDhtWithThreeNodes.test.ts +0 -59
  152. package/test/integration/StoreOnDhtWithTwoNodes.test.ts +0 -51
  153. package/test/integration/StoreRpcRemote.test.ts +0 -54
  154. package/test/integration/WebrtcConnectionManagement.test.ts +0 -191
  155. package/test/integration/WebrtcConnectorRpc.test.ts +0 -125
  156. package/test/integration/Websocket.test.ts +0 -65
  157. package/test/integration/WebsocketClientConnectorRpc.test.ts +0 -69
  158. package/test/integration/WebsocketConnectionManagement.test.ts +0 -191
  159. package/test/integration/rpc-connections-over-webrtc.test.ts +0 -123
  160. package/test/kademlia-simulation/data/nodeids.json +0 -13002
  161. package/test/kademlia-simulation/data/orderedneighbors.json +0 -1001
  162. package/test/types/global.d.ts +0 -1
  163. package/test/unit/AddressTools.test.ts +0 -44
  164. package/test/unit/AutoCertifierClientFacade.test.ts +0 -58
  165. package/test/unit/ConnectionManager.test.ts +0 -65
  166. package/test/unit/ConnectivityHelpers.test.ts +0 -61
  167. package/test/unit/DiscoverySession.test.ts +0 -87
  168. package/test/unit/DuplicateDetector.test.ts +0 -31
  169. package/test/unit/Handshaker.test.ts +0 -169
  170. package/test/unit/ListeningRpcCommunicator.test.ts +0 -52
  171. package/test/unit/LocalDataStore.test.ts +0 -108
  172. package/test/unit/ManagedConnection.test.ts +0 -58
  173. package/test/unit/PeerManager.test.ts +0 -93
  174. package/test/unit/PendingConnection.test.ts +0 -57
  175. package/test/unit/ProtobufMessage.test.ts +0 -21
  176. package/test/unit/RandomContactList.test.ts +0 -58
  177. package/test/unit/RecursiveOperationManager.test.ts +0 -161
  178. package/test/unit/RecursiveOperationSession.test.ts +0 -68
  179. package/test/unit/Router.test.ts +0 -137
  180. package/test/unit/RoutingSession.test.ts +0 -86
  181. package/test/unit/SortedContactList.test.ts +0 -115
  182. package/test/unit/StoreManager.test.ts +0 -146
  183. package/test/unit/StoreRpcLocal.test.ts +0 -167
  184. package/test/unit/WebrtcConnection.test.ts +0 -29
  185. package/test/unit/WebrtcConnector.test.ts +0 -56
  186. package/test/unit/WebsocketClientConnector.test.ts +0 -101
  187. package/test/unit/WebsocketServer.test.ts +0 -66
  188. package/test/unit/WebsocketServerConnector.test.ts +0 -102
  189. package/test/unit/connectivityRequestHandler.test.ts +0 -104
  190. package/test/unit/createPeerDescriptor.test.ts +0 -69
  191. package/test/unit/customMatchers.test.ts +0 -34
  192. package/test/unit/getClosestNodes.test.ts +0 -30
  193. package/test/unit/version.test.ts +0 -18
  194. package/test/unit/webrtcReplaceInternalIpWithExternalIp.test.ts +0 -18
  195. package/test/utils/FakeConnectorFacade.ts +0 -41
  196. package/test/utils/FakeRpcCommunicator.ts +0 -23
  197. package/test/utils/FakeTransport.ts +0 -79
  198. package/test/utils/customMatchers.ts +0 -71
  199. package/test/utils/mock/MockConnection.ts +0 -26
  200. package/test/utils/mock/MockConnectionsView.ts +0 -18
  201. package/test/utils/mock/MockRouter.ts +0 -62
  202. package/test/utils/mock/MockRpcCommunicator.ts +0 -7
  203. package/test/utils/mock/MockTransport.ts +0 -26
  204. package/test/utils/mock/mockDataEntry.ts +0 -38
  205. package/test/utils/topology.ts +0 -79
  206. package/test/utils/utils.ts +0 -268
  207. package/tsconfig.browser.json +0 -17
  208. package/tsconfig.jest.json +0 -25
  209. package/tsconfig.json +0 -3
  210. 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
- }