libp2p 0.37.2 → 0.37.3-2836acc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/src/address-manager/index.d.ts +2 -2
- package/dist/src/address-manager/index.d.ts.map +1 -1
- package/dist/src/circuit/auto-relay.d.ts +4 -4
- package/dist/src/circuit/auto-relay.d.ts.map +1 -1
- package/dist/src/circuit/circuit/hop.d.ts +2 -2
- package/dist/src/circuit/circuit/hop.d.ts.map +1 -1
- package/dist/src/circuit/circuit/hop.js +2 -2
- package/dist/src/circuit/circuit/hop.js.map +1 -1
- package/dist/src/circuit/circuit/stop.d.ts +1 -1
- package/dist/src/circuit/circuit/stop.d.ts.map +1 -1
- package/dist/src/circuit/circuit/stop.js +1 -1
- package/dist/src/circuit/circuit/stop.js.map +1 -1
- package/dist/src/circuit/circuit/stream-handler.d.ts +1 -1
- package/dist/src/circuit/circuit/stream-handler.d.ts.map +1 -1
- package/dist/src/circuit/index.d.ts +2 -2
- package/dist/src/circuit/index.d.ts.map +1 -1
- package/dist/src/circuit/listener.d.ts +3 -3
- package/dist/src/circuit/listener.d.ts.map +1 -1
- package/dist/src/circuit/transport.d.ts +5 -5
- package/dist/src/circuit/transport.d.ts.map +1 -1
- package/dist/src/circuit/transport.js +2 -2
- package/dist/src/circuit/transport.js.map +1 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +11 -3
- package/dist/src/config.js.map +1 -1
- package/dist/src/connection-manager/auto-dialler.d.ts +1 -1
- package/dist/src/connection-manager/auto-dialler.d.ts.map +1 -1
- package/dist/src/connection-manager/dialer/auto-dialer.d.ts +2 -2
- package/dist/src/connection-manager/dialer/auto-dialer.d.ts.map +1 -1
- package/dist/src/connection-manager/dialer/dial-request.d.ts +1 -1
- package/dist/src/connection-manager/dialer/dial-request.d.ts.map +1 -1
- package/dist/src/connection-manager/dialer/index.d.ts +5 -5
- package/dist/src/connection-manager/dialer/index.d.ts.map +1 -1
- package/dist/src/connection-manager/dialer/index.js +1 -1
- package/dist/src/connection-manager/dialer/index.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +16 -19
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +95 -59
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/content-routing/index.d.ts +4 -4
- package/dist/src/content-routing/index.d.ts.map +1 -1
- package/dist/src/content-routing/utils.d.ts +2 -2
- package/dist/src/content-routing/utils.d.ts.map +1 -1
- package/dist/src/dht/dht-content-routing.d.ts +3 -3
- package/dist/src/dht/dht-content-routing.d.ts.map +1 -1
- package/dist/src/dht/dht-peer-routing.d.ts +5 -5
- package/dist/src/dht/dht-peer-routing.d.ts.map +1 -1
- package/dist/src/dht/dummy-dht.d.ts +3 -3
- package/dist/src/dht/dummy-dht.d.ts.map +1 -1
- package/dist/src/dht/dummy-dht.js +1 -1
- package/dist/src/dht/dummy-dht.js.map +1 -1
- package/dist/src/errors.d.ts +4 -1
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +3 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/fetch/index.d.ts +7 -4
- package/dist/src/fetch/index.d.ts.map +1 -1
- package/dist/src/fetch/index.js +61 -39
- package/dist/src/fetch/index.js.map +1 -1
- package/dist/src/get-peer.d.ts +2 -2
- package/dist/src/get-peer.d.ts.map +1 -1
- package/dist/src/get-peer.js +1 -1
- package/dist/src/get-peer.js.map +1 -1
- package/dist/src/identify/index.d.ts +7 -7
- package/dist/src/identify/index.d.ts.map +1 -1
- package/dist/src/identify/index.js +15 -23
- package/dist/src/identify/index.js.map +1 -1
- package/dist/src/index.d.ts +17 -17
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/insecure/index.d.ts +2 -2
- package/dist/src/insecure/index.d.ts.map +1 -1
- package/dist/src/insecure/index.js +1 -1
- package/dist/src/insecure/index.js.map +1 -1
- package/dist/src/keychain/index.d.ts +2 -2
- package/dist/src/keychain/index.d.ts.map +1 -1
- package/dist/src/libp2p.d.ts +14 -14
- package/dist/src/libp2p.d.ts.map +1 -1
- package/dist/src/libp2p.js +14 -15
- package/dist/src/libp2p.js.map +1 -1
- package/dist/src/metrics/index.d.ts +2 -2
- package/dist/src/metrics/index.d.ts.map +1 -1
- package/dist/src/metrics/moving-average.d.ts +1 -1
- package/dist/src/metrics/moving-average.d.ts.map +1 -1
- package/dist/src/metrics/stats.d.ts +1 -1
- package/dist/src/metrics/stats.d.ts.map +1 -1
- package/dist/src/nat-manager.d.ts +1 -1
- package/dist/src/nat-manager.d.ts.map +1 -1
- package/dist/src/peer-record-updater.d.ts +1 -1
- package/dist/src/peer-record-updater.d.ts.map +1 -1
- package/dist/src/peer-routing.d.ts +4 -4
- package/dist/src/peer-routing.d.ts.map +1 -1
- package/dist/src/ping/index.d.ts +6 -3
- package/dist/src/ping/index.d.ts.map +1 -1
- package/dist/src/ping/index.js +6 -2
- package/dist/src/ping/index.js.map +1 -1
- package/dist/src/pnet/index.d.ts +1 -2
- package/dist/src/pnet/index.d.ts.map +1 -1
- package/dist/src/pnet/index.js.map +1 -1
- package/dist/src/pubsub/dummy-pubsub.d.ts +2 -2
- package/dist/src/pubsub/dummy-pubsub.d.ts.map +1 -1
- package/dist/src/registrar.d.ts +10 -8
- package/dist/src/registrar.d.ts.map +1 -1
- package/dist/src/registrar.js +63 -44
- package/dist/src/registrar.js.map +1 -1
- package/dist/src/transport-manager.d.ts +3 -3
- package/dist/src/transport-manager.d.ts.map +1 -1
- package/dist/src/upgrader.d.ts +6 -6
- package/dist/src/upgrader.d.ts.map +1 -1
- package/dist/src/upgrader.js +69 -8
- package/dist/src/upgrader.js.map +1 -1
- package/package.json +53 -30
- package/src/address-manager/index.ts +2 -2
- package/src/circuit/auto-relay.ts +4 -4
- package/src/circuit/circuit/hop.ts +4 -4
- package/src/circuit/circuit/stop.ts +2 -2
- package/src/circuit/circuit/stream-handler.ts +1 -1
- package/src/circuit/index.ts +2 -2
- package/src/circuit/listener.ts +3 -3
- package/src/circuit/transport.ts +5 -5
- package/src/config.ts +11 -3
- package/src/connection-manager/auto-dialler.ts +1 -1
- package/src/connection-manager/dialer/auto-dialer.ts +2 -2
- package/src/connection-manager/dialer/dial-request.ts +1 -1
- package/src/connection-manager/dialer/index.ts +5 -5
- package/src/connection-manager/index.ts +126 -71
- package/src/content-routing/index.ts +2 -2
- package/src/content-routing/utils.ts +2 -2
- package/src/dht/dht-content-routing.ts +2 -2
- package/src/dht/dht-peer-routing.ts +3 -3
- package/src/dht/dummy-dht.ts +3 -3
- package/src/errors.ts +4 -1
- package/src/fetch/index.ts +91 -50
- package/src/get-peer.ts +3 -3
- package/src/identify/index.ts +24 -29
- package/src/index.ts +17 -17
- package/src/insecure/index.ts +3 -3
- package/src/keychain/index.ts +2 -2
- package/src/libp2p.ts +31 -27
- package/src/metrics/index.ts +2 -2
- package/src/metrics/moving-average.ts +1 -1
- package/src/metrics/stats.ts +1 -1
- package/src/nat-manager.ts +1 -1
- package/src/peer-record-updater.ts +1 -1
- package/src/peer-routing.ts +4 -4
- package/src/ping/index.ts +12 -5
- package/src/pnet/index.ts +1 -2
- package/src/pubsub/dummy-pubsub.ts +2 -2
- package/src/registrar.ts +79 -55
- package/src/transport-manager.ts +3 -3
- package/src/upgrader.ts +94 -16
|
@@ -5,7 +5,7 @@ import { setMaxListeners } from 'events'
|
|
|
5
5
|
import { codes } from '../../errors.js'
|
|
6
6
|
import { logger } from '@libp2p/logger'
|
|
7
7
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
8
|
-
import type { Connection } from '@libp2p/
|
|
8
|
+
import type { Connection } from '@libp2p/interface-connection'
|
|
9
9
|
import type { AbortOptions } from '@libp2p/interfaces'
|
|
10
10
|
import type { Dialer } from './index.js'
|
|
11
11
|
|
|
@@ -18,16 +18,16 @@ import {
|
|
|
18
18
|
MAX_PER_PEER_DIALS,
|
|
19
19
|
MAX_ADDRS_TO_DIAL
|
|
20
20
|
} from '../../constants.js'
|
|
21
|
-
import type { Connection } from '@libp2p/
|
|
21
|
+
import type { Connection } from '@libp2p/interface-connection'
|
|
22
22
|
import type { AbortOptions } from '@libp2p/interfaces'
|
|
23
23
|
import type { Startable } from '@libp2p/interfaces/startable'
|
|
24
|
-
import type { PeerId } from '@libp2p/
|
|
24
|
+
import type { PeerId } from '@libp2p/interface-peer-id'
|
|
25
25
|
import { getPeer } from '../../get-peer.js'
|
|
26
26
|
import sort from 'it-sort'
|
|
27
|
-
import { Components, Initializable } from '@libp2p/
|
|
27
|
+
import { Components, Initializable } from '@libp2p/components'
|
|
28
28
|
import map from 'it-map'
|
|
29
|
-
import type { AddressSorter } from '@libp2p/
|
|
30
|
-
import type { ComponentMetricsTracker } from '@libp2p/
|
|
29
|
+
import type { AddressSorter } from '@libp2p/interface-peer-store'
|
|
30
|
+
import type { ComponentMetricsTracker } from '@libp2p/interface-metrics'
|
|
31
31
|
|
|
32
32
|
const log = logger('libp2p:dialer')
|
|
33
33
|
|
|
@@ -9,15 +9,18 @@ import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events'
|
|
|
9
9
|
import type { Startable } from '@libp2p/interfaces/startable'
|
|
10
10
|
import { trackedMap } from '@libp2p/tracked-map'
|
|
11
11
|
import { codes } from '../errors.js'
|
|
12
|
-
import { isPeerId, PeerId } from '@libp2p/
|
|
12
|
+
import { isPeerId, PeerId } from '@libp2p/interface-peer-id'
|
|
13
13
|
import { setMaxListeners } from 'events'
|
|
14
|
-
import type { Connection } from '@libp2p/
|
|
15
|
-
import type { ConnectionManager } from '@libp2p/
|
|
16
|
-
import { Components, Initializable } from '@libp2p/
|
|
17
|
-
import * as STATUS from '@libp2p/
|
|
14
|
+
import type { Connection } from '@libp2p/interface-connection'
|
|
15
|
+
import type { ConnectionManager } from '@libp2p/interface-connection-manager'
|
|
16
|
+
import { Components, Initializable } from '@libp2p/components'
|
|
17
|
+
import * as STATUS from '@libp2p/interface-connection/status'
|
|
18
18
|
import { Dialer } from './dialer/index.js'
|
|
19
|
-
import type { AddressSorter } from '@libp2p/
|
|
19
|
+
import type { AddressSorter } from '@libp2p/interface-peer-store'
|
|
20
20
|
import type { Resolver } from '@multiformats/multiaddr'
|
|
21
|
+
import { PeerMap } from '@libp2p/peer-collections'
|
|
22
|
+
import { TimeoutController } from 'timeout-abort-controller'
|
|
23
|
+
import { KEEP_ALIVE } from '@libp2p/interface-peer-store/tags'
|
|
21
24
|
|
|
22
25
|
const log = logger('libp2p:connection-manager')
|
|
23
26
|
|
|
@@ -30,13 +33,12 @@ const defaultOptions: Partial<ConnectionManagerInit> = {
|
|
|
30
33
|
maxEventLoopDelay: Infinity,
|
|
31
34
|
pollInterval: 2000,
|
|
32
35
|
autoDialInterval: 10000,
|
|
33
|
-
movingAverageInterval: 60000
|
|
34
|
-
defaultPeerValue: 1
|
|
36
|
+
movingAverageInterval: 60000
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
const METRICS_COMPONENT = 'connection-manager'
|
|
38
40
|
const METRICS_PEER_CONNECTIONS = 'peer-connections'
|
|
39
|
-
const
|
|
41
|
+
const STARTUP_RECONNECT_TIMEOUT = 60000
|
|
40
42
|
|
|
41
43
|
export interface ConnectionManagerInit {
|
|
42
44
|
/**
|
|
@@ -79,11 +81,6 @@ export interface ConnectionManagerInit {
|
|
|
79
81
|
*/
|
|
80
82
|
movingAverageInterval?: number
|
|
81
83
|
|
|
82
|
-
/**
|
|
83
|
-
* The value of the peer
|
|
84
|
-
*/
|
|
85
|
-
defaultPeerValue?: number
|
|
86
|
-
|
|
87
84
|
/**
|
|
88
85
|
* If true, try to connect to all discovered peers up to the connection manager limit
|
|
89
86
|
*/
|
|
@@ -124,6 +121,12 @@ export interface ConnectionManagerInit {
|
|
|
124
121
|
* Multiaddr resolvers to use when dialing
|
|
125
122
|
*/
|
|
126
123
|
resolvers?: Record<string, Resolver>
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* On startup we try to dial any peer that has previously been
|
|
127
|
+
* tagged with KEEP_ALIVE up to this timeout in ms. (default: 60000)
|
|
128
|
+
*/
|
|
129
|
+
startupReconnectTimeout?: number
|
|
127
130
|
}
|
|
128
131
|
|
|
129
132
|
export interface ConnectionManagerEvents {
|
|
@@ -138,11 +141,12 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
138
141
|
public readonly dialer: Dialer
|
|
139
142
|
private components = new Components()
|
|
140
143
|
private readonly opts: Required<ConnectionManagerInit>
|
|
141
|
-
private readonly peerValues: Map<string, number>
|
|
142
144
|
private readonly connections: Map<string, Connection[]>
|
|
143
145
|
private started: boolean
|
|
144
146
|
private timer?: ReturnType<retimer>
|
|
145
147
|
private readonly latencyMonitor: LatencyMonitor
|
|
148
|
+
private readonly startupReconnectTimeout: number
|
|
149
|
+
private connectOnStartupController?: TimeoutController
|
|
146
150
|
|
|
147
151
|
constructor (init: ConnectionManagerInit) {
|
|
148
152
|
super()
|
|
@@ -155,17 +159,6 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
155
159
|
|
|
156
160
|
log('options: %o', this.opts)
|
|
157
161
|
|
|
158
|
-
/**
|
|
159
|
-
* Map of peer identifiers to their peer value for pruning connections.
|
|
160
|
-
*
|
|
161
|
-
* @type {Map<string, number>}
|
|
162
|
-
*/
|
|
163
|
-
this.peerValues = trackedMap({
|
|
164
|
-
component: METRICS_COMPONENT,
|
|
165
|
-
metric: METRICS_PEER_VALUES,
|
|
166
|
-
metrics: this.components.getMetrics()
|
|
167
|
-
})
|
|
168
|
-
|
|
169
162
|
/**
|
|
170
163
|
* Map of connections per peer
|
|
171
164
|
*/
|
|
@@ -192,6 +185,8 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
192
185
|
|
|
193
186
|
this.onConnect = this.onConnect.bind(this)
|
|
194
187
|
this.onDisconnect = this.onDisconnect.bind(this)
|
|
188
|
+
|
|
189
|
+
this.startupReconnectTimeout = init.startupReconnectTimeout ?? STARTUP_RECONNECT_TIMEOUT
|
|
195
190
|
}
|
|
196
191
|
|
|
197
192
|
init (components: Components): void {
|
|
@@ -226,9 +221,43 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
226
221
|
async afterStart () {
|
|
227
222
|
this.components.getUpgrader().addEventListener('connection', this.onConnect)
|
|
228
223
|
this.components.getUpgrader().addEventListener('connectionEnd', this.onDisconnect)
|
|
224
|
+
|
|
225
|
+
// re-connect to any peers with the KEEP_ALIVE tag
|
|
226
|
+
void Promise.resolve()
|
|
227
|
+
.then(async () => {
|
|
228
|
+
const keepAlivePeers: PeerId[] = []
|
|
229
|
+
|
|
230
|
+
for (const peer of await this.components.getPeerStore().all()) {
|
|
231
|
+
const tags = await this.components.getPeerStore().getTags(peer.id)
|
|
232
|
+
const hasKeepAlive = tags.filter(tag => tag.name === KEEP_ALIVE).length > 0
|
|
233
|
+
|
|
234
|
+
if (hasKeepAlive) {
|
|
235
|
+
keepAlivePeers.push(peer.id)
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
this.connectOnStartupController?.clear()
|
|
240
|
+
this.connectOnStartupController = new TimeoutController(this.startupReconnectTimeout)
|
|
241
|
+
|
|
242
|
+
await Promise.all(
|
|
243
|
+
keepAlivePeers.map(async peer => {
|
|
244
|
+
await this.openConnection(peer, {
|
|
245
|
+
signal: this.connectOnStartupController?.signal
|
|
246
|
+
})
|
|
247
|
+
.catch(err => {
|
|
248
|
+
log.error(err)
|
|
249
|
+
})
|
|
250
|
+
})
|
|
251
|
+
)
|
|
252
|
+
})
|
|
253
|
+
.finally(() => {
|
|
254
|
+
this.connectOnStartupController?.clear()
|
|
255
|
+
})
|
|
229
256
|
}
|
|
230
257
|
|
|
231
258
|
async beforeStop () {
|
|
259
|
+
// if we are still dialing KEEP_ALIVE peers, abort those dials
|
|
260
|
+
this.connectOnStartupController?.abort()
|
|
232
261
|
this.components.getUpgrader().removeEventListener('connection', this.onConnect)
|
|
233
262
|
this.components.getUpgrader().removeEventListener('connectionEnd', this.onDisconnect)
|
|
234
263
|
}
|
|
@@ -271,18 +300,6 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
271
300
|
this.connections.clear()
|
|
272
301
|
}
|
|
273
302
|
|
|
274
|
-
/**
|
|
275
|
-
* Sets the value of the given peer. Peers with lower values
|
|
276
|
-
* will be disconnected first.
|
|
277
|
-
*/
|
|
278
|
-
setPeerValue (peerId: PeerId, value: number) {
|
|
279
|
-
if (value < 0 || value > 1) {
|
|
280
|
-
throw new Error('value should be a number between 0 and 1')
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
this.peerValues.set(peerId.toString(), value)
|
|
284
|
-
}
|
|
285
|
-
|
|
286
303
|
/**
|
|
287
304
|
* Checks the libp2p metrics to determine if any values have exceeded
|
|
288
305
|
* the configured maximums.
|
|
@@ -340,11 +357,10 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
340
357
|
await this.components.getPeerStore().keyBook.set(peerId, peerId.publicKey)
|
|
341
358
|
}
|
|
342
359
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
360
|
+
const numConnections = this.getConnections().length
|
|
361
|
+
const toPrune = numConnections - this.opts.maxConnections
|
|
346
362
|
|
|
347
|
-
await this._checkMaxLimit('maxConnections',
|
|
363
|
+
await this._checkMaxLimit('maxConnections', numConnections, toPrune)
|
|
348
364
|
this.dispatchEvent(new CustomEvent<Connection>('peer:connect', { detail: connection }))
|
|
349
365
|
}
|
|
350
366
|
|
|
@@ -367,7 +383,6 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
367
383
|
this.connections.set(peerId, storedConn)
|
|
368
384
|
} else if (storedConn != null) {
|
|
369
385
|
this.connections.delete(peerId)
|
|
370
|
-
this.peerValues.delete(connection.remotePeer.toString())
|
|
371
386
|
this.dispatchEvent(new CustomEvent<Connection>('peer:disconnect', { detail: connection }))
|
|
372
387
|
|
|
373
388
|
this.components.getMetrics()?.onPeerDisconnected(connection.remotePeer)
|
|
@@ -459,7 +474,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
459
474
|
_onLatencyMeasure (evt: CustomEvent<SummaryObject>) {
|
|
460
475
|
const { detail: summary } = evt
|
|
461
476
|
|
|
462
|
-
this._checkMaxLimit('maxEventLoopDelay', summary.avgMs)
|
|
477
|
+
this._checkMaxLimit('maxEventLoopDelay', summary.avgMs, 1)
|
|
463
478
|
.catch(err => {
|
|
464
479
|
log.error(err)
|
|
465
480
|
})
|
|
@@ -468,46 +483,86 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
468
483
|
/**
|
|
469
484
|
* If the `value` of `name` has exceeded its limit, maybe close a connection
|
|
470
485
|
*/
|
|
471
|
-
async _checkMaxLimit (name: keyof ConnectionManagerInit, value: number) {
|
|
486
|
+
async _checkMaxLimit (name: keyof ConnectionManagerInit, value: number, toPrune: number = 1) {
|
|
472
487
|
const limit = this.opts[name]
|
|
473
488
|
log.trace('checking limit of %s. current value: %d of %d', name, value, limit)
|
|
474
489
|
if (value > limit) {
|
|
475
|
-
log('%s: limit exceeded: %p, %d', this.components.getPeerId(), name, value)
|
|
476
|
-
await this.
|
|
490
|
+
log('%s: limit exceeded: %p, %d/%d, pruning %d connection(s)', this.components.getPeerId(), name, value, limit, toPrune)
|
|
491
|
+
await this._maybePruneConnections(toPrune)
|
|
477
492
|
}
|
|
478
493
|
}
|
|
479
494
|
|
|
480
495
|
/**
|
|
481
|
-
* If we have more connections than our maximum,
|
|
482
|
-
* to
|
|
496
|
+
* If we have more connections than our maximum, select some excess connections
|
|
497
|
+
* to prune based on peer value
|
|
483
498
|
*/
|
|
484
|
-
async
|
|
485
|
-
|
|
486
|
-
const peerValues = Array.from(new Map([...this.peerValues.entries()].sort((a, b) => a[1] - b[1])))
|
|
499
|
+
async _maybePruneConnections (toPrune: number) {
|
|
500
|
+
const connections = this.getConnections()
|
|
487
501
|
|
|
488
|
-
|
|
489
|
-
|
|
502
|
+
if (connections.length <= this.opts.minConnections || toPrune < 1) {
|
|
503
|
+
return
|
|
504
|
+
}
|
|
490
505
|
|
|
491
|
-
|
|
492
|
-
const peerId = disconnectPeer[0]
|
|
493
|
-
log('%p: lowest value peer is %s', this.components.getPeerId(), peerId)
|
|
494
|
-
log('%p: closing a connection to %j', this.components.getPeerId(), peerId)
|
|
506
|
+
const peerValues = new PeerMap<number>()
|
|
495
507
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
.catch(err => {
|
|
500
|
-
log.error(err)
|
|
501
|
-
})
|
|
508
|
+
// work out peer values
|
|
509
|
+
for (const connection of connections) {
|
|
510
|
+
const remotePeer = connection.remotePeer
|
|
502
511
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
detail: connections[0]
|
|
506
|
-
}))
|
|
507
|
-
break
|
|
508
|
-
}
|
|
509
|
-
}
|
|
512
|
+
if (peerValues.has(remotePeer)) {
|
|
513
|
+
continue
|
|
510
514
|
}
|
|
515
|
+
|
|
516
|
+
const tags = await this.components.getPeerStore().getTags(remotePeer)
|
|
517
|
+
|
|
518
|
+
// sum all tag values
|
|
519
|
+
peerValues.set(remotePeer, tags.reduce((acc, curr) => {
|
|
520
|
+
return acc + curr.value
|
|
521
|
+
}, 0))
|
|
511
522
|
}
|
|
523
|
+
|
|
524
|
+
// sort by value, lowest to highest
|
|
525
|
+
const sortedConnections = connections.sort((a, b) => {
|
|
526
|
+
const peerAValue = peerValues.get(a.remotePeer) ?? 0
|
|
527
|
+
const peerBValue = peerValues.get(b.remotePeer) ?? 0
|
|
528
|
+
|
|
529
|
+
if (peerAValue > peerBValue) {
|
|
530
|
+
return 1
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
if (peerAValue < peerBValue) {
|
|
534
|
+
return -1
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
return 0
|
|
538
|
+
})
|
|
539
|
+
|
|
540
|
+
// close some connections
|
|
541
|
+
const toClose = []
|
|
542
|
+
|
|
543
|
+
for (const connection of sortedConnections) {
|
|
544
|
+
log('too many connections open - closing a connection to %p', connection.remotePeer)
|
|
545
|
+
toClose.push(connection)
|
|
546
|
+
|
|
547
|
+
if (toClose.length === toPrune) {
|
|
548
|
+
break
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// close connections
|
|
553
|
+
await Promise.all(
|
|
554
|
+
toClose.map(async connection => {
|
|
555
|
+
try {
|
|
556
|
+
await connection.close()
|
|
557
|
+
} catch (err) {
|
|
558
|
+
log.error(err)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// TODO: should not need to invoke this manually
|
|
562
|
+
this.onDisconnect(new CustomEvent<Connection>('connectionEnd', {
|
|
563
|
+
detail: connection
|
|
564
|
+
}))
|
|
565
|
+
})
|
|
566
|
+
)
|
|
512
567
|
}
|
|
513
568
|
}
|
|
@@ -8,11 +8,11 @@ import {
|
|
|
8
8
|
import drain from 'it-drain'
|
|
9
9
|
import merge from 'it-merge'
|
|
10
10
|
import { pipe } from 'it-pipe'
|
|
11
|
-
import type { ContentRouting } from '@libp2p/
|
|
11
|
+
import type { ContentRouting } from '@libp2p/interface-content-routing'
|
|
12
12
|
import type { AbortOptions } from '@libp2p/interfaces'
|
|
13
13
|
import type { Startable } from '@libp2p/interfaces/startable'
|
|
14
14
|
import type { CID } from 'multiformats/cid'
|
|
15
|
-
import type { Components } from '@libp2p/
|
|
15
|
+
import type { Components } from '@libp2p/components'
|
|
16
16
|
|
|
17
17
|
export interface CompoundContentRoutingInit {
|
|
18
18
|
routers: ContentRouting[]
|
|
@@ -2,8 +2,8 @@ import errCode from 'err-code'
|
|
|
2
2
|
import filter from 'it-filter'
|
|
3
3
|
import map from 'it-map'
|
|
4
4
|
import type { Source } from 'it-stream-types'
|
|
5
|
-
import type { PeerInfo } from '@libp2p/
|
|
6
|
-
import type { PeerStore } from '@libp2p/
|
|
5
|
+
import type { PeerInfo } from '@libp2p/interface-peer-info'
|
|
6
|
+
import type { PeerStore } from '@libp2p/interface-peer-store'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Store the multiaddrs from every peer in the passed peer store
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import drain from 'it-drain'
|
|
2
2
|
import errCode from 'err-code'
|
|
3
|
-
import type { DHT } from '@libp2p/
|
|
4
|
-
import type { ContentRouting } from '@libp2p/
|
|
3
|
+
import type { DHT } from '@libp2p/interface-dht'
|
|
4
|
+
import type { ContentRouting } from '@libp2p/interface-content-routing'
|
|
5
5
|
import type { CID } from 'multiformats/cid'
|
|
6
6
|
import type { AbortOptions } from '@libp2p/interfaces'
|
|
7
7
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import errCode from 'err-code'
|
|
2
2
|
import { messages, codes } from '../errors.js'
|
|
3
|
-
import type { PeerRouting } from '@libp2p/
|
|
4
|
-
import type { DHT } from '@libp2p/
|
|
5
|
-
import type { PeerId } from '@libp2p/
|
|
3
|
+
import type { PeerRouting } from '@libp2p/interface-peer-routing'
|
|
4
|
+
import type { DHT } from '@libp2p/interface-dht'
|
|
5
|
+
import type { PeerId } from '@libp2p/interface-peer-id'
|
|
6
6
|
import type { AbortOptions } from '@libp2p/interfaces'
|
|
7
7
|
|
|
8
8
|
/**
|
package/src/dht/dummy-dht.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { DualDHT, QueryEvent, SingleDHT } from '@libp2p/
|
|
2
|
-
import type { PeerDiscoveryEvents } from '@libp2p/
|
|
1
|
+
import type { DualDHT, QueryEvent, SingleDHT } from '@libp2p/interface-dht'
|
|
2
|
+
import type { PeerDiscoveryEvents } from '@libp2p/interface-peer-discovery'
|
|
3
3
|
import errCode from 'err-code'
|
|
4
4
|
import { messages, codes } from '../errors.js'
|
|
5
5
|
import { EventEmitter } from '@libp2p/interfaces/events'
|
|
6
|
-
import { symbol } from '@libp2p/
|
|
6
|
+
import { symbol } from '@libp2p/interface-peer-discovery'
|
|
7
7
|
|
|
8
8
|
export class DummyDHT extends EventEmitter<PeerDiscoveryEvents> implements DualDHT {
|
|
9
9
|
get [symbol] (): true {
|
package/src/errors.ts
CHANGED
|
@@ -70,5 +70,8 @@ export enum codes {
|
|
|
70
70
|
ERR_NOT_IMPLEMENTED = 'ERR_NOT_IMPLEMENTED',
|
|
71
71
|
ERR_WRONG_PING_ACK = 'ERR_WRONG_PING_ACK',
|
|
72
72
|
ERR_INVALID_RECORD = 'ERR_INVALID_RECORD',
|
|
73
|
-
ERR_ALREADY_SUCCEEDED = 'ERR_ALREADY_SUCCEEDED'
|
|
73
|
+
ERR_ALREADY_SUCCEEDED = 'ERR_ALREADY_SUCCEEDED',
|
|
74
|
+
ERR_NO_HANDLER_FOR_PROTOCOL = 'ERR_NO_HANDLER_FOR_PROTOCOL',
|
|
75
|
+
ERR_TOO_MANY_OUTBOUND_PROTOCOL_STREAMS = 'ERR_TOO_MANY_OUTBOUND_PROTOCOL_STREAMS',
|
|
76
|
+
ERR_TOO_MANY_INBOUND_PROTOCOL_STREAMS = 'ERR_TOO_MANY_INBOUND_PROTOCOL_STREAMS'
|
|
74
77
|
}
|
package/src/fetch/index.ts
CHANGED
|
@@ -3,21 +3,24 @@ import errCode from 'err-code'
|
|
|
3
3
|
import { codes } from '../errors.js'
|
|
4
4
|
import * as lp from 'it-length-prefixed'
|
|
5
5
|
import { FetchRequest, FetchResponse } from './pb/proto.js'
|
|
6
|
-
import { handshake } from 'it-handshake'
|
|
7
6
|
import { PROTOCOL_NAME, PROTOCOL_VERSION } from './constants.js'
|
|
8
|
-
import type { PeerId } from '@libp2p/
|
|
7
|
+
import type { PeerId } from '@libp2p/interface-peer-id'
|
|
9
8
|
import type { Startable } from '@libp2p/interfaces/startable'
|
|
10
|
-
import type { Stream } from '@libp2p/
|
|
11
|
-
import type { IncomingStreamData } from '@libp2p/
|
|
12
|
-
import type { Components } from '@libp2p/
|
|
9
|
+
import type { Stream } from '@libp2p/interface-connection'
|
|
10
|
+
import type { IncomingStreamData } from '@libp2p/interface-registrar'
|
|
11
|
+
import type { Components } from '@libp2p/components'
|
|
13
12
|
import type { AbortOptions } from '@libp2p/interfaces'
|
|
14
13
|
import type { Duplex } from 'it-stream-types'
|
|
15
14
|
import { abortableDuplex } from 'abortable-iterator'
|
|
15
|
+
import { pipe } from 'it-pipe'
|
|
16
|
+
import first from 'it-first'
|
|
16
17
|
|
|
17
18
|
const log = logger('libp2p:fetch')
|
|
18
19
|
|
|
19
20
|
export interface FetchServiceInit {
|
|
20
21
|
protocolPrefix: string
|
|
22
|
+
maxInboundStreams: number
|
|
23
|
+
maxOutboundStreams: number
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
export interface HandleMessageOptions {
|
|
@@ -40,6 +43,7 @@ export class FetchService implements Startable {
|
|
|
40
43
|
private readonly components: Components
|
|
41
44
|
private readonly lookupFunctions: Map<string, LookupFunction>
|
|
42
45
|
private started: boolean
|
|
46
|
+
private readonly init: FetchServiceInit
|
|
43
47
|
|
|
44
48
|
constructor (components: Components, init: FetchServiceInit) {
|
|
45
49
|
this.started = false
|
|
@@ -47,13 +51,21 @@ export class FetchService implements Startable {
|
|
|
47
51
|
this.protocol = `/${init.protocolPrefix ?? 'libp2p'}/${PROTOCOL_NAME}/${PROTOCOL_VERSION}`
|
|
48
52
|
this.lookupFunctions = new Map() // Maps key prefix to value lookup function
|
|
49
53
|
this.handleMessage = this.handleMessage.bind(this)
|
|
54
|
+
this.init = init
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
async start () {
|
|
53
58
|
await this.components.getRegistrar().handle(this.protocol, (data) => {
|
|
54
|
-
void this.handleMessage(data)
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
void this.handleMessage(data)
|
|
60
|
+
.catch(err => {
|
|
61
|
+
log.error(err)
|
|
62
|
+
})
|
|
63
|
+
.finally(() => {
|
|
64
|
+
data.stream.close()
|
|
65
|
+
})
|
|
66
|
+
}, {
|
|
67
|
+
maxInboundStreams: this.init.maxInboundStreams,
|
|
68
|
+
maxOutboundStreams: this.init.maxOutboundStreams
|
|
57
69
|
})
|
|
58
70
|
this.started = true
|
|
59
71
|
}
|
|
@@ -74,7 +86,7 @@ export class FetchService implements Startable {
|
|
|
74
86
|
log('dialing %s to %p', this.protocol, peer)
|
|
75
87
|
|
|
76
88
|
const connection = await this.components.getConnectionManager().openConnection(peer, options)
|
|
77
|
-
const
|
|
89
|
+
const stream = await connection.newStream([this.protocol], options)
|
|
78
90
|
let source: Duplex<Uint8Array> = stream
|
|
79
91
|
|
|
80
92
|
// make stream abortable if AbortSignal passed
|
|
@@ -82,28 +94,42 @@ export class FetchService implements Startable {
|
|
|
82
94
|
source = abortableDuplex(stream, options.signal)
|
|
83
95
|
}
|
|
84
96
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
97
|
+
try {
|
|
98
|
+
const result = await pipe(
|
|
99
|
+
[FetchRequest.encode({ identifier: key })],
|
|
100
|
+
lp.encode(),
|
|
101
|
+
source,
|
|
102
|
+
lp.decode(),
|
|
103
|
+
async function (source) {
|
|
104
|
+
const buf = await first(source)
|
|
105
|
+
|
|
106
|
+
if (buf == null) {
|
|
107
|
+
throw errCode(new Error('No data received'), codes.ERR_INVALID_MESSAGE)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const response = FetchResponse.decode(buf)
|
|
111
|
+
|
|
112
|
+
switch (response.status) {
|
|
113
|
+
case (FetchResponse.StatusCode.OK): {
|
|
114
|
+
return response.data
|
|
115
|
+
}
|
|
116
|
+
case (FetchResponse.StatusCode.NOT_FOUND): {
|
|
117
|
+
return null
|
|
118
|
+
}
|
|
119
|
+
case (FetchResponse.StatusCode.ERROR): {
|
|
120
|
+
const errmsg = (new TextDecoder()).decode(response.data)
|
|
121
|
+
throw errCode(new Error('Error in fetch protocol response: ' + errmsg), codes.ERR_INVALID_PARAMETERS)
|
|
122
|
+
}
|
|
123
|
+
default: {
|
|
124
|
+
throw errCode(new Error('Unknown response status'), codes.ERR_INVALID_MESSAGE)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
return result ?? null
|
|
131
|
+
} finally {
|
|
132
|
+
stream.close()
|
|
107
133
|
}
|
|
108
134
|
}
|
|
109
135
|
|
|
@@ -114,25 +140,40 @@ export class FetchService implements Startable {
|
|
|
114
140
|
*/
|
|
115
141
|
async handleMessage (data: IncomingStreamData) {
|
|
116
142
|
const { stream } = data
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
143
|
+
const self = this
|
|
144
|
+
|
|
145
|
+
await pipe(
|
|
146
|
+
stream,
|
|
147
|
+
lp.decode(),
|
|
148
|
+
async function * (source) {
|
|
149
|
+
const buf = await first(source)
|
|
150
|
+
|
|
151
|
+
if (buf == null) {
|
|
152
|
+
throw errCode(new Error('No data received'), codes.ERR_INVALID_MESSAGE)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// for await (const buf of source) {
|
|
156
|
+
const request = FetchRequest.decode(buf)
|
|
157
|
+
|
|
158
|
+
let response: FetchResponse
|
|
159
|
+
const lookup = self._getLookupFunction(request.identifier)
|
|
160
|
+
if (lookup != null) {
|
|
161
|
+
const data = await lookup(request.identifier)
|
|
162
|
+
if (data != null) {
|
|
163
|
+
response = { status: FetchResponse.StatusCode.OK, data }
|
|
164
|
+
} else {
|
|
165
|
+
response = { status: FetchResponse.StatusCode.NOT_FOUND, data: new Uint8Array(0) }
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
const errmsg = (new TextEncoder()).encode('No lookup function registered for key: ' + request.identifier)
|
|
169
|
+
response = { status: FetchResponse.StatusCode.ERROR, data: errmsg }
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
yield FetchResponse.encode(response)
|
|
173
|
+
},
|
|
174
|
+
lp.encode(),
|
|
175
|
+
stream
|
|
176
|
+
)
|
|
136
177
|
}
|
|
137
178
|
|
|
138
179
|
/**
|
package/src/get-peer.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { peerIdFromString } from '@libp2p/peer-id'
|
|
|
2
2
|
import { Multiaddr } from '@multiformats/multiaddr'
|
|
3
3
|
import errCode from 'err-code'
|
|
4
4
|
import { codes } from './errors.js'
|
|
5
|
-
import { isPeerId } from '@libp2p/
|
|
6
|
-
import type { PeerId } from '@libp2p/
|
|
7
|
-
import type { PeerInfo } from '@libp2p/
|
|
5
|
+
import { isPeerId } from '@libp2p/interface-peer-id'
|
|
6
|
+
import type { PeerId } from '@libp2p/interface-peer-id'
|
|
7
|
+
import type { PeerInfo } from '@libp2p/interface-peer-info'
|
|
8
8
|
|
|
9
9
|
function peerIdFromMultiaddr (ma: Multiaddr) {
|
|
10
10
|
const idStr = ma.getPeerId()
|