@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,683 +0,0 @@
1
- import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
2
- import {
3
- Logger,
4
- MetricsContext,
5
- merge,
6
- scheduleAtInterval,
7
- until
8
- } from '@streamr/utils'
9
- import { EventEmitter } from 'eventemitter3'
10
- import { sample } from 'lodash'
11
- import type { MarkRequired } from 'ts-essentials'
12
- import { ConnectionLocker, ConnectionManager, PortRange, TlsCertificate } from '../connection/ConnectionManager'
13
- import { ConnectionsView } from '../connection/ConnectionsView'
14
- import { DefaultConnectorFacade, DefaultConnectorFacadeOptions } from '../connection/ConnectorFacade'
15
- import { IceServer } from '../connection/webrtc/WebrtcConnector'
16
- import { isBrowserEnvironment } from '../helpers/browser/isBrowserEnvironment'
17
- import { createPeerDescriptor } from '../helpers/createPeerDescriptor'
18
- import { DhtAddress, KADEMLIA_ID_LENGTH_IN_BYTES, toNodeId } from '../identifiers'
19
- import { Any } from '../../generated/google/protobuf/any'
20
- import {
21
- ClosestPeersRequest,
22
- ClosestPeersResponse,
23
- ClosestRingPeersRequest,
24
- ClosestRingPeersResponse,
25
- ConnectivityResponse,
26
- DataEntry,
27
- ExternalFetchDataRequest,
28
- ExternalFetchDataResponse,
29
- ExternalStoreDataRequest,
30
- ExternalStoreDataResponse,
31
- LeaveNotice,
32
- Message,
33
- PeerDescriptor,
34
- PingRequest,
35
- PingResponse,
36
- RecursiveOperation
37
- } from '../../generated/packages/dht/protos/DhtRpc'
38
- import { ExternalApiRpcClient, StoreRpcClient } from '../../generated/packages/dht/protos/DhtRpc.client'
39
- import { ITransport, TransportEvents } from '../transport/ITransport'
40
- import { RoutingRpcCommunicator } from '../transport/RoutingRpcCommunicator'
41
- import { ServiceID } from '../types/ServiceID'
42
- import { DhtNodeRpcLocal } from './DhtNodeRpcLocal'
43
- import { DhtNodeRpcRemote } from './DhtNodeRpcRemote'
44
- import { ExternalApiRpcLocal } from './ExternalApiRpcLocal'
45
- import { ExternalApiRpcRemote } from './ExternalApiRpcRemote'
46
- import { PeerManager } from './PeerManager'
47
- import { RingContacts } from './contact/RingContactList'
48
- import { RingIdRaw } from './contact/ringIdentifiers'
49
- import { PeerDiscovery } from './discovery/PeerDiscovery'
50
- import { RecursiveOperationManager } from './recursive-operation/RecursiveOperationManager'
51
- import { Router } from './routing/Router'
52
- import { LocalDataStore } from './store/LocalDataStore'
53
- import { StoreManager } from './store/StoreManager'
54
- import { StoreRpcRemote } from './store/StoreRpcRemote'
55
- import { getLocalRegionByCoordinates, getLocalRegionWithCache } from '@streamr/cdn-location'
56
-
57
- export interface DhtNodeEvents {
58
- nearbyContactAdded: (peerDescriptor: PeerDescriptor) => void
59
- nearbyContactRemoved: (peerDescriptor: PeerDescriptor) => void
60
- randomContactAdded: (peerDescriptor: PeerDescriptor) => void
61
- randomContactRemoved: (peerDescriptor: PeerDescriptor) => void
62
- ringContactAdded: (peerDescriptor: PeerDescriptor) => void
63
- ringContactRemoved: (peerDescriptor: PeerDescriptor) => void
64
- manualRejoinRequired: () => void
65
- }
66
-
67
- export interface DhtNodeOptions {
68
- serviceId?: ServiceID
69
- joinParallelism?: number
70
- maxContactCount?: number
71
- numberOfNodesPerKBucket?: number
72
- joinNoProgressLimit?: number
73
- peerDiscoveryQueryBatchSize?: number
74
- dhtJoinTimeout?: number
75
- metricsContext?: MetricsContext
76
- storeHighestTtl?: number
77
- storeMaxTtl?: number
78
- networkConnectivityTimeout?: number
79
- storageRedundancyFactor?: number
80
- periodicallyPingNeighbors?: boolean
81
- periodicallyPingRingContacts?: boolean
82
- // Limit for how many new neighbors to ping. If number of neighbors is higher than the limit new neighbors
83
- // are not pinged when they are added. This is to prevent flooding the network with pings when joining.
84
- // Enable periodicallyPingNeighbors to eventually ping all neighbors.
85
- neighborPingLimit?: number
86
-
87
- transport?: ITransport
88
- connectionsView?: ConnectionsView
89
- connectionLocker?: ConnectionLocker
90
- peerDescriptor?: PeerDescriptor
91
- entryPoints?: PeerDescriptor[]
92
- websocketHost?: string
93
- websocketPortRange?: PortRange
94
- websocketServerEnableTls?: boolean
95
- nodeId?: DhtAddress
96
- region?: number
97
-
98
- rpcRequestTimeout?: number
99
- iceServers?: IceServer[]
100
- webrtcAllowPrivateAddresses?: boolean
101
- webrtcDatachannelBufferThresholdLow?: number
102
- webrtcDatachannelBufferThresholdHigh?: number
103
- webrtcPortRange?: PortRange
104
- maxMessageSize?: number
105
- maxConnections?: number
106
- tlsCertificate?: TlsCertificate
107
- externalIp?: string
108
- autoCertifierUrl?: string
109
- autoCertifierConfigFile?: string
110
- geoIpDatabaseFolder?: string
111
- allowIncomingPrivateConnections?: boolean
112
- }
113
-
114
- type StrictDhtNodeOptions = MarkRequired<DhtNodeOptions,
115
- 'serviceId' |
116
- 'joinParallelism' |
117
- 'maxContactCount' |
118
- 'numberOfNodesPerKBucket' |
119
- 'joinNoProgressLimit' |
120
- 'dhtJoinTimeout' |
121
- 'peerDiscoveryQueryBatchSize' |
122
- 'maxConnections' |
123
- 'storeHighestTtl' |
124
- 'storeMaxTtl' |
125
- 'networkConnectivityTimeout' |
126
- 'storageRedundancyFactor' |
127
- 'metricsContext'>
128
-
129
- const logger = new Logger(module)
130
-
131
- const PERIODICAL_PING_INTERVAL = 60 * 1000
132
-
133
- // TODO move this to trackerless-network package and change serviceId to be a required paramater
134
- export const CONTROL_LAYER_NODE_SERVICE_ID = 'layer0'
135
-
136
- export type Events = TransportEvents & DhtNodeEvents
137
-
138
- export class DhtNode extends EventEmitter<Events> implements ITransport {
139
-
140
- private readonly options: StrictDhtNodeOptions
141
- private rpcCommunicator?: RoutingRpcCommunicator
142
- private transport?: ITransport
143
- private localPeerDescriptor?: PeerDescriptor
144
- private router?: Router
145
- private storeManager?: StoreManager
146
- private localDataStore: LocalDataStore
147
- private recursiveOperationManager?: RecursiveOperationManager
148
- private peerDiscovery?: PeerDiscovery
149
- private peerManager?: PeerManager
150
- private connectionsView?: ConnectionsView
151
- public connectionLocker?: ConnectionLocker
152
- private started = false
153
- private abortController = new AbortController()
154
-
155
- constructor(conf: DhtNodeOptions) {
156
- super()
157
- this.options = merge({
158
- serviceId: CONTROL_LAYER_NODE_SERVICE_ID,
159
- joinParallelism: 3,
160
- maxContactCount: 200,
161
- numberOfNodesPerKBucket: 8,
162
- joinNoProgressLimit: 5,
163
- dhtJoinTimeout: 60000,
164
- peerDiscoveryQueryBatchSize: 5,
165
- maxConnections: 80,
166
- storeHighestTtl: 60000,
167
- storeMaxTtl: 60000,
168
- networkConnectivityTimeout: 10000,
169
- storageRedundancyFactor: 5, // TODO validate that this is > 1 (as each node should replicate the data to other node)
170
- metricsContext: new MetricsContext()
171
- }, conf)
172
- this.validateOptions()
173
- this.localDataStore = new LocalDataStore(this.options.storeMaxTtl)
174
- this.send = this.send.bind(this)
175
- }
176
-
177
- private validateOptions(): void {
178
- const expectedNodeIdLength = KADEMLIA_ID_LENGTH_IN_BYTES * 2
179
- if (this.options.nodeId !== undefined) {
180
- if (!/^[0-9a-fA-F]+$/.test(this.options.nodeId)) {
181
- throw new Error('Invalid nodeId, the nodeId should be a hex string')
182
- } else if (this.options.nodeId.length !== expectedNodeIdLength) {
183
- throw new Error(`Invalid nodeId, the length of the nodeId should be ${expectedNodeIdLength}`)
184
- }
185
- }
186
- if (this.options.peerDescriptor !== undefined) {
187
- if (this.options.peerDescriptor.nodeId.length !== KADEMLIA_ID_LENGTH_IN_BYTES) {
188
- throw new Error(`Invalid peerDescriptor, the length of the nodeId should be ${KADEMLIA_ID_LENGTH_IN_BYTES} bytes`)
189
- }
190
- }
191
- if (this.options.transport !== undefined && this.options.connectionsView === undefined) {
192
- throw new Error('connectionsView is required when transport is given')
193
- }
194
- }
195
-
196
- public async start(): Promise<void> {
197
- if (this.started || this.abortController.signal.aborted) {
198
- return
199
- }
200
- logger.trace(`Starting new Streamr Network DHT Node with serviceId ${this.options.serviceId}`)
201
- this.started = true
202
-
203
- if (isBrowserEnvironment()) {
204
- this.options.websocketPortRange = undefined
205
- if (this.options.peerDescriptor) {
206
- this.options.peerDescriptor.websocket = undefined
207
- }
208
- }
209
-
210
- // If transport is given, do not create a ConnectionManager
211
- if (this.options.transport) {
212
- this.transport = this.options.transport
213
- this.connectionsView = this.options.connectionsView
214
- this.connectionLocker = this.options.connectionLocker
215
- this.localPeerDescriptor = this.transport.getLocalPeerDescriptor()
216
- } else {
217
- const connectorFacadeOptions: DefaultConnectorFacadeOptions = {
218
- transport: this,
219
- entryPoints: this.options.entryPoints,
220
- iceServers: this.options.iceServers,
221
- webrtcAllowPrivateAddresses: this.options.webrtcAllowPrivateAddresses,
222
- webrtcDatachannelBufferThresholdLow: this.options.webrtcDatachannelBufferThresholdLow,
223
- webrtcDatachannelBufferThresholdHigh: this.options.webrtcDatachannelBufferThresholdHigh,
224
- webrtcPortRange: this.options.webrtcPortRange,
225
- maxMessageSize: this.options.maxMessageSize,
226
- websocketServerEnableTls: this.options.websocketServerEnableTls,
227
- tlsCertificate: this.options.tlsCertificate,
228
- externalIp: this.options.externalIp,
229
- autoCertifierUrl: this.options.autoCertifierUrl,
230
- autoCertifierConfigFile: this.options.autoCertifierConfigFile,
231
- geoIpDatabaseFolder: this.options.geoIpDatabaseFolder,
232
- createLocalPeerDescriptor: (connectivityResponse: ConnectivityResponse) => this.generatePeerDescriptorCallBack(connectivityResponse)
233
- }
234
- // If own PeerDescriptor is given in options, create a ConnectionManager with ws server
235
- if (this.options.peerDescriptor?.websocket) {
236
- connectorFacadeOptions.websocketHost = this.options.peerDescriptor.websocket.host
237
- connectorFacadeOptions.websocketPortRange = {
238
- min: this.options.peerDescriptor.websocket.port,
239
- max: this.options.peerDescriptor.websocket.port
240
- }
241
- // If websocketPortRange is given, create ws server using it, websocketHost can be undefined
242
- } else if (this.options.websocketPortRange) {
243
- connectorFacadeOptions.websocketHost = this.options.websocketHost
244
- connectorFacadeOptions.websocketPortRange = this.options.websocketPortRange
245
- }
246
-
247
- const connectionManager = new ConnectionManager({
248
- createConnectorFacade: () => new DefaultConnectorFacade(connectorFacadeOptions),
249
- maxConnections: this.options.maxConnections,
250
- metricsContext: this.options.metricsContext,
251
- allowIncomingPrivateConnections: this.options.allowIncomingPrivateConnections ?? false
252
- })
253
- await connectionManager.start()
254
- this.connectionsView = connectionManager
255
- this.connectionLocker = connectionManager
256
- this.transport = connectionManager
257
- }
258
-
259
- this.rpcCommunicator = new RoutingRpcCommunicator(
260
- this.options.serviceId,
261
- (msg, opts) => this.transport!.send(msg, opts),
262
- { rpcRequestTimeout: this.options.rpcRequestTimeout }
263
- )
264
-
265
- this.transport.on('message', (message: Message) => this.handleMessageFromTransport(message))
266
-
267
- this.initPeerManager()
268
-
269
- this.peerDiscovery = new PeerDiscovery({
270
- localPeerDescriptor: this.localPeerDescriptor!,
271
- joinNoProgressLimit: this.options.joinNoProgressLimit,
272
- joinTimeout: this.options.dhtJoinTimeout,
273
- serviceId: this.options.serviceId,
274
- parallelism: this.options.joinParallelism,
275
- connectionLocker: this.connectionLocker,
276
- peerManager: this.peerManager!,
277
- abortSignal: this.abortController.signal,
278
- createDhtNodeRpcRemote: (peerDescriptor: PeerDescriptor) => this.createDhtNodeRpcRemote(peerDescriptor),
279
- })
280
- this.router = new Router({
281
- rpcCommunicator: this.rpcCommunicator,
282
- localPeerDescriptor: this.localPeerDescriptor!,
283
- handleMessage: (message: Message) => this.handleMessageFromRouter(message),
284
- getConnections: () => this.connectionsView!.getConnections()
285
- })
286
- this.recursiveOperationManager = new RecursiveOperationManager({
287
- rpcCommunicator: this.rpcCommunicator,
288
- router: this.router,
289
- sessionTransport: this,
290
- connectionsView: this.connectionsView!,
291
- localPeerDescriptor: this.localPeerDescriptor!,
292
- serviceId: this.options.serviceId,
293
- localDataStore: this.localDataStore,
294
- addContact: (contact: PeerDescriptor) => this.peerManager!.addContact(contact),
295
- createDhtNodeRpcRemote: (peerDescriptor: PeerDescriptor) => this.createDhtNodeRpcRemote(peerDescriptor),
296
- })
297
- this.storeManager = new StoreManager({
298
- rpcCommunicator: this.rpcCommunicator,
299
- recursiveOperationManager: this.recursiveOperationManager,
300
- localPeerDescriptor: this.localPeerDescriptor!,
301
- serviceId: this.options.serviceId,
302
- highestTtl: this.options.storeHighestTtl,
303
- redundancyFactor: this.options.storageRedundancyFactor,
304
- localDataStore: this.localDataStore,
305
- getNeighbors: () => this.peerManager!.getNeighbors().map((n) => n.getPeerDescriptor()),
306
- createRpcRemote: (contact: PeerDescriptor) => {
307
- return new StoreRpcRemote(
308
- this.localPeerDescriptor!,
309
- contact,
310
- this.rpcCommunicator!,
311
- StoreRpcClient,
312
- this.options.rpcRequestTimeout
313
- )
314
- }
315
- })
316
- this.on('nearbyContactAdded', (peerDescriptor: PeerDescriptor) => {
317
- this.storeManager!.onContactAdded(peerDescriptor)
318
- })
319
- this.bindRpcLocalMethods()
320
-
321
- const pruneTargets = []
322
- if (this.options.periodicallyPingNeighbors === true) {
323
- pruneTargets.push(() => this.peerManager!.getNeighbors().map((node) => this.createDhtNodeRpcRemote(node.getPeerDescriptor())))
324
- }
325
- if (this.options.periodicallyPingRingContacts === true) {
326
- pruneTargets.push(() => this.peerManager!.getRingContacts().getAllContacts())
327
- }
328
- for (const pruneTarget of pruneTargets) {
329
- await scheduleAtInterval(
330
- async () => {
331
- const nodes = pruneTarget()
332
- await this.peerManager!.pruneOfflineNodes(nodes)
333
- }, PERIODICAL_PING_INTERVAL, false, this.abortController.signal
334
- )
335
- }
336
- }
337
-
338
- private initPeerManager() {
339
- this.peerManager = new PeerManager({
340
- numberOfNodesPerKBucket: this.options.numberOfNodesPerKBucket,
341
- maxContactCount: this.options.maxContactCount,
342
- localNodeId: this.getNodeId(),
343
- localPeerDescriptor: this.localPeerDescriptor!,
344
- connectionLocker: this.connectionLocker,
345
- lockId: this.options.serviceId,
346
- createDhtNodeRpcRemote: (peerDescriptor: PeerDescriptor) => this.createDhtNodeRpcRemote(peerDescriptor),
347
- hasConnection: (nodeId: DhtAddress) => this.connectionsView!.hasConnection(nodeId),
348
- neighborPingLimit: this.options.neighborPingLimit
349
- })
350
- this.peerManager.on('nearbyContactRemoved', (peerDescriptor: PeerDescriptor) => {
351
- this.emit('nearbyContactRemoved', peerDescriptor)
352
- })
353
- this.peerManager.on('nearbyContactAdded', (peerDescriptor: PeerDescriptor) =>
354
- this.emit('nearbyContactAdded', peerDescriptor)
355
- )
356
- this.peerManager.on('randomContactRemoved', (peerDescriptor: PeerDescriptor) =>
357
- this.emit('randomContactRemoved', peerDescriptor)
358
- )
359
- this.peerManager.on('randomContactAdded', (peerDescriptor: PeerDescriptor) =>
360
- this.emit('randomContactAdded', peerDescriptor)
361
- )
362
- this.peerManager.on('ringContactRemoved', (peerDescriptor: PeerDescriptor) => {
363
- this.emit('ringContactRemoved', peerDescriptor)
364
- })
365
- this.peerManager.on('ringContactAdded', (peerDescriptor: PeerDescriptor) => {
366
- this.emit('ringContactAdded', peerDescriptor)
367
- })
368
- this.peerManager.on('kBucketEmpty', () => {
369
- if (!this.peerDiscovery!.isJoinOngoing()) {
370
- if (this.options.entryPoints && this.options.entryPoints.length > 0) {
371
- setImmediate(async () => {
372
- const contactedPeers = new Set<DhtAddress>()
373
- const distantJoinContactPeers = new Set<DhtAddress>()
374
- // TODO should we catch possible promise rejection?
375
- await Promise.all(this.options.entryPoints!.map((entryPoint) =>
376
- this.peerDiscovery!.rejoinDht(entryPoint, contactedPeers, distantJoinContactPeers)
377
- ))
378
- })
379
- } else {
380
- this.emit('manualRejoinRequired')
381
- }
382
- }
383
- })
384
- this.transport!.on('connected', (peerDescriptor: PeerDescriptor) => {
385
- this.router!.onNodeConnected(peerDescriptor)
386
- this.emit('connected', peerDescriptor)
387
- })
388
- this.transport!.on('disconnected', (peerDescriptor: PeerDescriptor, gracefulLeave: boolean) => {
389
- const isControlLayerNode = (this.connectionLocker !== undefined)
390
- if (isControlLayerNode) {
391
- const nodeId = toNodeId(peerDescriptor)
392
- if (gracefulLeave) {
393
- this.peerManager!.removeContact(nodeId)
394
- } else {
395
- this.peerManager!.removeNeighbor(nodeId)
396
- }
397
- }
398
- this.router!.onNodeDisconnected(peerDescriptor)
399
- this.emit('disconnected', peerDescriptor, gracefulLeave)
400
- })
401
- }
402
-
403
- private bindRpcLocalMethods(): void {
404
- if (!this.started || this.abortController.signal.aborted) {
405
- return
406
- }
407
- const dhtNodeRpcLocal = new DhtNodeRpcLocal({
408
- peerDiscoveryQueryBatchSize: this.options.peerDiscoveryQueryBatchSize,
409
- getNeighbors: () => this.peerManager!.getNeighbors().map((n) => n.getPeerDescriptor()),
410
- getClosestRingContactsTo: (ringIdRaw: RingIdRaw, limit: number) => {
411
- return this.getClosestRingContactsTo(ringIdRaw, limit)
412
- },
413
- addContact: (contact: PeerDescriptor) => this.peerManager!.addContact(contact),
414
- removeContact: (nodeId: DhtAddress) => this.removeContact(nodeId)
415
- })
416
- this.rpcCommunicator!.registerRpcMethod(ClosestPeersRequest, ClosestPeersResponse, 'getClosestPeers',
417
- (req: ClosestPeersRequest, context) => dhtNodeRpcLocal.getClosestPeers(req, context))
418
- this.rpcCommunicator!.registerRpcMethod(ClosestRingPeersRequest, ClosestRingPeersResponse, 'getClosestRingPeers',
419
- (req: ClosestRingPeersRequest, context) => dhtNodeRpcLocal.getClosestRingPeers(req, context))
420
- this.rpcCommunicator!.registerRpcMethod(PingRequest, PingResponse, 'ping',
421
- (req: PingRequest, context) => dhtNodeRpcLocal.ping(req, context))
422
- this.rpcCommunicator!.registerRpcNotification(LeaveNotice, 'leaveNotice',
423
- (_req: LeaveNotice, context) => dhtNodeRpcLocal.leaveNotice(context))
424
- const externalApiRpcLocal = new ExternalApiRpcLocal({
425
- executeRecursiveOperation: (key: DhtAddress, operation: RecursiveOperation, excludedPeer: DhtAddress) => {
426
- return this.recursiveOperationManager!.execute(key, operation, excludedPeer)
427
- },
428
- storeDataToDht: (key: DhtAddress, data: Any, creator?: DhtAddress) => this.storeDataToDht(key, data, creator)
429
- })
430
- this.rpcCommunicator!.registerRpcMethod(
431
- ExternalFetchDataRequest,
432
- ExternalFetchDataResponse,
433
- 'externalFetchData',
434
- (req: ExternalFetchDataRequest, context: ServerCallContext) => externalApiRpcLocal.externalFetchData(req, context),
435
- { timeout: 10000 } // TODO use options option or named constant?
436
- )
437
- this.rpcCommunicator!.registerRpcMethod(
438
- ExternalStoreDataRequest,
439
- ExternalStoreDataResponse,
440
- 'externalStoreData',
441
- (req: ExternalStoreDataRequest, context: ServerCallContext) => externalApiRpcLocal.externalStoreData(req, context),
442
- { timeout: 10000 } // TODO use options option or named constant?
443
- )
444
- }
445
-
446
- private handleMessageFromTransport(message: Message): void {
447
- if (message.serviceId === this.options.serviceId) {
448
- this.rpcCommunicator?.handleMessageFromPeer(message)
449
- }
450
- }
451
-
452
- private handleMessageFromRouter(message: Message): void {
453
- if (message.serviceId === this.options.serviceId) {
454
- this.rpcCommunicator?.handleMessageFromPeer(message)
455
- } else {
456
- this.emit('message', message)
457
- }
458
- }
459
-
460
- private async generatePeerDescriptorCallBack(connectivityResponse: ConnectivityResponse) {
461
- if (this.options.peerDescriptor !== undefined) {
462
- this.localPeerDescriptor = this.options.peerDescriptor
463
- } else {
464
- let region: number | undefined = undefined
465
- if (this.options.region !== undefined) {
466
- region = this.options.region
467
- logger.debug(`Using region ${region} from options when generating local PeerDescriptor`)
468
- } else if (connectivityResponse.latitude !== undefined && connectivityResponse.longitude !== undefined) {
469
- region = getLocalRegionByCoordinates(connectivityResponse.latitude, connectivityResponse.longitude)
470
- logger.debug(`Using region ${region} from GeoIP when generating local PeerDescriptor`)
471
- } else {
472
- // as a fallback get the region from the CDN
473
- // and if it's not available, use a random region
474
- region = await getLocalRegionWithCache()
475
- logger.debug(`Using region ${region} from CDN when generating local PeerDescriptor`)
476
- }
477
-
478
- this.localPeerDescriptor = createPeerDescriptor(connectivityResponse, region, this.options.nodeId)
479
- }
480
- return this.localPeerDescriptor
481
- }
482
-
483
- public getClosestContacts(limit?: number): PeerDescriptor[] {
484
- return this.peerManager!.getNearbyContacts()
485
- .getClosestContacts(limit)
486
- .map((peer) => peer.getPeerDescriptor())
487
- }
488
-
489
- getRandomContacts(limit?: number): PeerDescriptor[] {
490
- return this.peerManager!.getRandomContacts().getContacts(limit).map((c) => c.getPeerDescriptor())
491
- }
492
-
493
- getRingContacts(): RingContacts {
494
- const contacts = this.peerManager!.getRingContacts().getClosestContacts()
495
- return {
496
- left: contacts.left.map((c) => c.getPeerDescriptor()),
497
- right: contacts.right.map((c) => c.getPeerDescriptor())
498
- }
499
- }
500
-
501
- public getClosestRingContactsTo(ringIdRaw: RingIdRaw, limit?: number): RingContacts {
502
- const closest = this.peerManager!.getClosestRingContactsTo(ringIdRaw, limit)
503
- return {
504
- left: closest.left.map((dhtPeer: DhtNodeRpcRemote) => dhtPeer.getPeerDescriptor()),
505
- right: closest.right.map((dhtPeer: DhtNodeRpcRemote) => dhtPeer.getPeerDescriptor())
506
- }
507
- }
508
-
509
- public getNodeId(): DhtAddress {
510
- return toNodeId(this.localPeerDescriptor!)
511
- }
512
-
513
- public getNeighborCount(): number {
514
- return this.peerManager!.getNeighborCount()
515
- }
516
-
517
- public removeContact(nodeId: DhtAddress): void {
518
- if (!this.started) { // the stopped state is checked in PeerManager
519
- return
520
- }
521
- this.peerManager!.removeContact(nodeId)
522
- }
523
-
524
- public async send(msg: Message): Promise<void> {
525
- if (!this.started || this.abortController.signal.aborted) {
526
- return
527
- }
528
- const reachableThrough = this.peerDiscovery!.isJoinOngoing() ? this.getConnectedEntryPoints() : []
529
- this.router!.send(msg, reachableThrough)
530
- }
531
-
532
- private getConnectedEntryPoints(): PeerDescriptor[] {
533
- return this.options.entryPoints !== undefined ? this.options.entryPoints.filter((entryPoint) =>
534
- this.connectionsView!.hasConnection(toNodeId(entryPoint))
535
- ) : []
536
- }
537
-
538
- public async joinDht(entryPointDescriptors: PeerDescriptor[], doAdditionalDistantPeerDiscovery?: boolean, retry?: boolean): Promise<void> {
539
- if (!this.started) {
540
- throw new Error('Cannot join DHT before calling start() on DhtNode')
541
- }
542
- await this.peerDiscovery!.joinDht(entryPointDescriptors, doAdditionalDistantPeerDiscovery, retry)
543
- }
544
-
545
- public async joinRing(): Promise<void> {
546
- if (!this.started) {
547
- throw new Error('Cannot join ring before calling start() on DhtNode')
548
- }
549
- await this.peerDiscovery!.joinRing()
550
- }
551
-
552
- public async storeDataToDht(key: DhtAddress, data: Any, creator?: DhtAddress): Promise<PeerDescriptor[]> {
553
- const connectedEntryPoints = this.getConnectedEntryPoints()
554
- if (this.peerDiscovery!.isJoinOngoing() && connectedEntryPoints.length > 0) {
555
- return this.storeDataToDhtViaPeer(key, data, sample(connectedEntryPoints)!)
556
- }
557
- return this.storeManager!.storeDataToDht(key, data, creator ?? this.getNodeId())
558
- }
559
-
560
- public async storeDataToDhtViaPeer(key: DhtAddress, data: Any, peer: PeerDescriptor): Promise<PeerDescriptor[]> {
561
- const rpcRemote = new ExternalApiRpcRemote(
562
- this.localPeerDescriptor!,
563
- peer,
564
- this.rpcCommunicator!,
565
- ExternalApiRpcClient
566
- )
567
- return await rpcRemote.storeData(key, data)
568
- }
569
-
570
- public async fetchDataFromDht(key: DhtAddress): Promise<DataEntry[]> {
571
- const connectedEntryPoints = this.getConnectedEntryPoints()
572
- if (this.peerDiscovery!.isJoinOngoing() && connectedEntryPoints.length > 0) {
573
- return this.fetchDataFromDhtViaPeer(key, sample(connectedEntryPoints)!)
574
- }
575
- const result = await this.recursiveOperationManager!.execute(key, RecursiveOperation.FETCH_DATA)
576
- return result.dataEntries ?? [] // TODO is this fallback needed?
577
- }
578
-
579
- public async fetchDataFromDhtViaPeer(key: DhtAddress, peer: PeerDescriptor): Promise<DataEntry[]> {
580
- const rpcRemote = new ExternalApiRpcRemote(
581
- this.localPeerDescriptor!,
582
- peer,
583
- this.rpcCommunicator!,
584
- ExternalApiRpcClient
585
- )
586
- return await rpcRemote.externalFetchData(key)
587
- }
588
-
589
- public async deleteDataFromDht(key: DhtAddress, waitForCompletion: boolean): Promise<void> {
590
- if (!this.abortController.signal.aborted) {
591
- await this.recursiveOperationManager!.execute(key, RecursiveOperation.DELETE_DATA, undefined, waitForCompletion)
592
- }
593
- }
594
-
595
- async findClosestNodesFromDht(key: DhtAddress): Promise<PeerDescriptor[]> {
596
- const result = await this.recursiveOperationManager!.execute(key, RecursiveOperation.FIND_CLOSEST_NODES)
597
- return result.closestNodes
598
- }
599
-
600
- public getTransport(): ITransport {
601
- return this.transport!
602
- }
603
-
604
- public getLocalPeerDescriptor(): PeerDescriptor {
605
- return this.localPeerDescriptor!
606
- }
607
-
608
- public getNeighbors(): PeerDescriptor[] {
609
- return this.started ? this.peerManager!.getNeighbors().map((remote: DhtNodeRpcRemote) => remote.getPeerDescriptor()) : []
610
- }
611
-
612
- getConnectionsView(): ConnectionsView {
613
- return this.connectionsView!
614
- }
615
-
616
- public getLocalLockedConnectionCount(): number {
617
- return this.connectionLocker!.getLocalLockedConnectionCount()
618
- }
619
-
620
- public getRemoteLockedConnectionCount(): number {
621
- return this.connectionLocker!.getRemoteLockedConnectionCount()
622
- }
623
-
624
- public getWeakLockedConnectionCount(): number {
625
- return this.connectionLocker!.getWeakLockedConnectionCount()
626
- }
627
-
628
- public async waitForNetworkConnectivity(): Promise<void> {
629
- await until(
630
- () => this.connectionsView!.getConnectionCount() > 0,
631
- this.options.networkConnectivityTimeout,
632
- 100,
633
- this.abortController.signal
634
- )
635
- }
636
-
637
- public hasJoined(): boolean {
638
- return this.peerDiscovery!.isJoinCalled()
639
- }
640
-
641
- public getDiagnosticInfo(): Record<string, unknown> {
642
- return {
643
- localPeerDescriptor: this.localPeerDescriptor,
644
- transport: this.transport!.getDiagnosticInfo(),
645
- router: this.router!.getDiagnosticInfo(),
646
- neighborCount: this.getNeighborCount(),
647
- nearbyContactCount: Array.from(this.peerManager!.getNearbyContacts().getAllContactsInUndefinedOrder()).length,
648
- randomContactCount: this.peerManager!.getRandomContacts().getSize()
649
- }
650
- }
651
-
652
- public async stop(): Promise<void> {
653
- if (this.abortController.signal.aborted || !this.started) {
654
- return
655
- }
656
- logger.trace('stop()')
657
- this.abortController.abort()
658
- await this.storeManager!.destroy()
659
- this.localDataStore.clear()
660
- this.peerManager?.stop()
661
- this.rpcCommunicator!.stop()
662
- this.router!.stop()
663
- this.recursiveOperationManager!.stop()
664
- if (this.options.transport === undefined) {
665
- // if the transport was not given in options, the instance was created in start() and
666
- // this component is responsible for stopping it
667
- await this.transport!.stop()
668
- }
669
- this.transport = undefined
670
- this.connectionLocker = undefined
671
- this.removeAllListeners()
672
- }
673
-
674
- private createDhtNodeRpcRemote(peerDescriptor: PeerDescriptor) {
675
- return new DhtNodeRpcRemote(
676
- this.localPeerDescriptor!,
677
- peerDescriptor,
678
- this.options.serviceId,
679
- this.rpcCommunicator!,
680
- this.options.rpcRequestTimeout
681
- )
682
- }
683
- }