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