libp2p 0.37.2 → 0.37.3-0bb1b80
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 +25 -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 +9 -9
- package/dist/src/connection-manager/dialer/index.d.ts.map +1 -1
- package/dist/src/connection-manager/dialer/index.js +11 -11
- package/dist/src/connection-manager/dialer/index.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +24 -20
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +199 -82
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/constants.d.ts +4 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +4 -0
- package/dist/src/constants.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 +11 -4
- package/dist/src/fetch/index.d.ts.map +1 -1
- package/dist/src/fetch/index.js +74 -42
- 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 +8 -8
- package/dist/src/identify/index.d.ts.map +1 -1
- package/dist/src/identify/index.js +23 -32
- 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 +16 -16
- package/dist/src/libp2p.js.map +1 -1
- package/dist/src/metrics/index.d.ts +3 -3
- package/dist/src/metrics/index.d.ts.map +1 -1
- package/dist/src/metrics/index.js +6 -2
- package/dist/src/metrics/index.js.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 +10 -3
- package/dist/src/ping/index.d.ts.map +1 -1
- package/dist/src/ping/index.js +21 -7
- 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 +12 -6
- package/dist/src/upgrader.d.ts.map +1 -1
- package/dist/src/upgrader.js +151 -66
- package/dist/src/upgrader.js.map +1 -1
- package/dist/src/version.d.ts.map +1 -1
- package/dist/src/version.js.map +1 -1
- package/package.json +56 -32
- 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 +25 -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 +15 -15
- package/src/connection-manager/index.ts +257 -97
- package/src/constants.ts +5 -0
- 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 +111 -53
- package/src/get-peer.ts +3 -3
- package/src/identify/index.ts +34 -40
- package/src/index.ts +17 -17
- package/src/insecure/index.ts +3 -3
- package/src/keychain/index.ts +2 -2
- package/src/libp2p.ts +33 -28
- package/src/metrics/index.ts +9 -5
- 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 +35 -12
- 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 +188 -76
- package/src/version.ts +1 -2
|
@@ -7,17 +7,19 @@ import retimer from 'retimer'
|
|
|
7
7
|
import type { AbortOptions } from '@libp2p/interfaces'
|
|
8
8
|
import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events'
|
|
9
9
|
import type { Startable } from '@libp2p/interfaces/startable'
|
|
10
|
-
import { trackedMap } from '@libp2p/tracked-map'
|
|
11
10
|
import { codes } from '../errors.js'
|
|
12
|
-
import { isPeerId, PeerId } from '@libp2p/
|
|
11
|
+
import { isPeerId, PeerId } from '@libp2p/interface-peer-id'
|
|
13
12
|
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/
|
|
13
|
+
import type { Connection } from '@libp2p/interface-connection'
|
|
14
|
+
import type { ConnectionManager } from '@libp2p/interface-connection-manager'
|
|
15
|
+
import { Components, Initializable } from '@libp2p/components'
|
|
16
|
+
import * as STATUS from '@libp2p/interface-connection/status'
|
|
18
17
|
import { Dialer } from './dialer/index.js'
|
|
19
|
-
import type { AddressSorter } from '@libp2p/
|
|
18
|
+
import type { AddressSorter } from '@libp2p/interface-peer-store'
|
|
20
19
|
import type { Resolver } from '@multiformats/multiaddr'
|
|
20
|
+
import { PeerMap } from '@libp2p/peer-collections'
|
|
21
|
+
import { TimeoutController } from 'timeout-abort-controller'
|
|
22
|
+
import { KEEP_ALIVE } from '@libp2p/interface-peer-store/tags'
|
|
21
23
|
|
|
22
24
|
const log = logger('libp2p:connection-manager')
|
|
23
25
|
|
|
@@ -30,13 +32,12 @@ const defaultOptions: Partial<ConnectionManagerInit> = {
|
|
|
30
32
|
maxEventLoopDelay: Infinity,
|
|
31
33
|
pollInterval: 2000,
|
|
32
34
|
autoDialInterval: 10000,
|
|
33
|
-
movingAverageInterval: 60000
|
|
34
|
-
defaultPeerValue: 1
|
|
35
|
+
movingAverageInterval: 60000
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
const METRICS_SYSTEM = 'libp2p'
|
|
37
39
|
const METRICS_COMPONENT = 'connection-manager'
|
|
38
|
-
const
|
|
39
|
-
const METRICS_PEER_VALUES = 'peer-values'
|
|
40
|
+
const STARTUP_RECONNECT_TIMEOUT = 60000
|
|
40
41
|
|
|
41
42
|
export interface ConnectionManagerInit {
|
|
42
43
|
/**
|
|
@@ -79,11 +80,6 @@ export interface ConnectionManagerInit {
|
|
|
79
80
|
*/
|
|
80
81
|
movingAverageInterval?: number
|
|
81
82
|
|
|
82
|
-
/**
|
|
83
|
-
* The value of the peer
|
|
84
|
-
*/
|
|
85
|
-
defaultPeerValue?: number
|
|
86
|
-
|
|
87
83
|
/**
|
|
88
84
|
* If true, try to connect to all discovered peers up to the connection manager limit
|
|
89
85
|
*/
|
|
@@ -111,10 +107,17 @@ export interface ConnectionManagerInit {
|
|
|
111
107
|
maxAddrsToDial?: number
|
|
112
108
|
|
|
113
109
|
/**
|
|
114
|
-
* How long a dial attempt is allowed to take
|
|
110
|
+
* How long a dial attempt is allowed to take, including DNS resolution
|
|
111
|
+
* of the multiaddr, opening a socket and upgrading it to a Connection.
|
|
115
112
|
*/
|
|
116
113
|
dialTimeout?: number
|
|
117
114
|
|
|
115
|
+
/**
|
|
116
|
+
* When a new inbound connection is opened, the upgrade process (e.g. protect,
|
|
117
|
+
* encrypt, multiplex etc) must complete within this number of ms.
|
|
118
|
+
*/
|
|
119
|
+
inboundUpgradeTimeout: number
|
|
120
|
+
|
|
118
121
|
/**
|
|
119
122
|
* Number of max concurrent dials per peer
|
|
120
123
|
*/
|
|
@@ -124,6 +127,12 @@ export interface ConnectionManagerInit {
|
|
|
124
127
|
* Multiaddr resolvers to use when dialing
|
|
125
128
|
*/
|
|
126
129
|
resolvers?: Record<string, Resolver>
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* On startup we try to dial any peer that has previously been
|
|
133
|
+
* tagged with KEEP_ALIVE up to this timeout in ms. (default: 60000)
|
|
134
|
+
*/
|
|
135
|
+
startupReconnectTimeout?: number
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
export interface ConnectionManagerEvents {
|
|
@@ -138,11 +147,13 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
138
147
|
public readonly dialer: Dialer
|
|
139
148
|
private components = new Components()
|
|
140
149
|
private readonly opts: Required<ConnectionManagerInit>
|
|
141
|
-
private readonly peerValues: Map<string, number>
|
|
142
150
|
private readonly connections: Map<string, Connection[]>
|
|
143
151
|
private started: boolean
|
|
144
152
|
private timer?: ReturnType<retimer>
|
|
145
153
|
private readonly latencyMonitor: LatencyMonitor
|
|
154
|
+
private readonly startupReconnectTimeout: number
|
|
155
|
+
private connectOnStartupController?: TimeoutController
|
|
156
|
+
private readonly dialTimeout: number
|
|
146
157
|
|
|
147
158
|
constructor (init: ConnectionManagerInit) {
|
|
148
159
|
super()
|
|
@@ -155,25 +166,10 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
155
166
|
|
|
156
167
|
log('options: %o', this.opts)
|
|
157
168
|
|
|
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
169
|
/**
|
|
170
170
|
* Map of connections per peer
|
|
171
171
|
*/
|
|
172
|
-
this.connections =
|
|
173
|
-
component: METRICS_COMPONENT,
|
|
174
|
-
metric: METRICS_PEER_CONNECTIONS,
|
|
175
|
-
metrics: this.components.getMetrics()
|
|
176
|
-
})
|
|
172
|
+
this.connections = new Map()
|
|
177
173
|
|
|
178
174
|
this.started = false
|
|
179
175
|
this._checkMetrics = this._checkMetrics.bind(this)
|
|
@@ -192,12 +188,103 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
192
188
|
|
|
193
189
|
this.onConnect = this.onConnect.bind(this)
|
|
194
190
|
this.onDisconnect = this.onDisconnect.bind(this)
|
|
191
|
+
|
|
192
|
+
this.startupReconnectTimeout = init.startupReconnectTimeout ?? STARTUP_RECONNECT_TIMEOUT
|
|
193
|
+
this.dialTimeout = init.dialTimeout ?? 30000
|
|
195
194
|
}
|
|
196
195
|
|
|
197
196
|
init (components: Components): void {
|
|
198
197
|
this.components = components
|
|
199
198
|
|
|
200
199
|
this.dialer.init(components)
|
|
200
|
+
|
|
201
|
+
// track inbound/outbound connections
|
|
202
|
+
this.components.getMetrics()?.updateComponentMetric({
|
|
203
|
+
system: METRICS_SYSTEM,
|
|
204
|
+
component: METRICS_COMPONENT,
|
|
205
|
+
metric: 'connections',
|
|
206
|
+
label: 'direction',
|
|
207
|
+
value: () => {
|
|
208
|
+
const metric = {
|
|
209
|
+
inbound: 0,
|
|
210
|
+
outbound: 0
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
for (const conns of this.connections.values()) {
|
|
214
|
+
for (const conn of conns) {
|
|
215
|
+
if (conn.stat.direction === 'inbound') {
|
|
216
|
+
metric.inbound++
|
|
217
|
+
} else {
|
|
218
|
+
metric.outbound++
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return metric
|
|
224
|
+
}
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
// track total number of streams per protocol
|
|
228
|
+
this.components.getMetrics()?.updateComponentMetric({
|
|
229
|
+
system: METRICS_SYSTEM,
|
|
230
|
+
component: METRICS_COMPONENT,
|
|
231
|
+
metric: 'protocol-streams-total',
|
|
232
|
+
label: 'protocol',
|
|
233
|
+
value: () => {
|
|
234
|
+
const metric: Record<string, number> = {}
|
|
235
|
+
|
|
236
|
+
for (const conns of this.connections.values()) {
|
|
237
|
+
for (const conn of conns) {
|
|
238
|
+
for (const stream of conn.streams) {
|
|
239
|
+
const key = `${stream.stat.direction} ${stream.stat.protocol ?? 'unnegotiated'}`
|
|
240
|
+
|
|
241
|
+
metric[key] = (metric[key] ?? 0) + 1
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return metric
|
|
247
|
+
}
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
// track 90th percentile of streams per protocol
|
|
251
|
+
this.components.getMetrics()?.updateComponentMetric({
|
|
252
|
+
system: METRICS_SYSTEM,
|
|
253
|
+
component: METRICS_COMPONENT,
|
|
254
|
+
metric: 'protocol-streams-per-connection-90th-percentile',
|
|
255
|
+
label: 'protocol',
|
|
256
|
+
value: () => {
|
|
257
|
+
const allStreams: Record<string, number[]> = {}
|
|
258
|
+
|
|
259
|
+
for (const conns of this.connections.values()) {
|
|
260
|
+
for (const conn of conns) {
|
|
261
|
+
const streams: Record<string, number> = {}
|
|
262
|
+
|
|
263
|
+
for (const stream of conn.streams) {
|
|
264
|
+
const key = `${stream.stat.direction} ${stream.stat.protocol ?? 'unnegotiated'}`
|
|
265
|
+
|
|
266
|
+
streams[key] = (streams[key] ?? 0) + 1
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
for (const [protocol, count] of Object.entries(streams)) {
|
|
270
|
+
allStreams[protocol] = allStreams[protocol] ?? []
|
|
271
|
+
allStreams[protocol].push(count)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const metric: Record<string, number> = {}
|
|
277
|
+
|
|
278
|
+
for (let [protocol, counts] of Object.entries(allStreams)) {
|
|
279
|
+
counts = counts.sort((a, b) => a - b)
|
|
280
|
+
|
|
281
|
+
const index = Math.floor(counts.length * 0.9)
|
|
282
|
+
metric[protocol] = counts[index]
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return metric
|
|
286
|
+
}
|
|
287
|
+
})
|
|
201
288
|
}
|
|
202
289
|
|
|
203
290
|
isStarted () {
|
|
@@ -226,9 +313,43 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
226
313
|
async afterStart () {
|
|
227
314
|
this.components.getUpgrader().addEventListener('connection', this.onConnect)
|
|
228
315
|
this.components.getUpgrader().addEventListener('connectionEnd', this.onDisconnect)
|
|
316
|
+
|
|
317
|
+
// re-connect to any peers with the KEEP_ALIVE tag
|
|
318
|
+
void Promise.resolve()
|
|
319
|
+
.then(async () => {
|
|
320
|
+
const keepAlivePeers: PeerId[] = []
|
|
321
|
+
|
|
322
|
+
for (const peer of await this.components.getPeerStore().all()) {
|
|
323
|
+
const tags = await this.components.getPeerStore().getTags(peer.id)
|
|
324
|
+
const hasKeepAlive = tags.filter(tag => tag.name === KEEP_ALIVE).length > 0
|
|
325
|
+
|
|
326
|
+
if (hasKeepAlive) {
|
|
327
|
+
keepAlivePeers.push(peer.id)
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
this.connectOnStartupController?.clear()
|
|
332
|
+
this.connectOnStartupController = new TimeoutController(this.startupReconnectTimeout)
|
|
333
|
+
|
|
334
|
+
await Promise.all(
|
|
335
|
+
keepAlivePeers.map(async peer => {
|
|
336
|
+
await this.openConnection(peer, {
|
|
337
|
+
signal: this.connectOnStartupController?.signal
|
|
338
|
+
})
|
|
339
|
+
.catch(err => {
|
|
340
|
+
log.error(err)
|
|
341
|
+
})
|
|
342
|
+
})
|
|
343
|
+
)
|
|
344
|
+
})
|
|
345
|
+
.finally(() => {
|
|
346
|
+
this.connectOnStartupController?.clear()
|
|
347
|
+
})
|
|
229
348
|
}
|
|
230
349
|
|
|
231
350
|
async beforeStop () {
|
|
351
|
+
// if we are still dialing KEEP_ALIVE peers, abort those dials
|
|
352
|
+
this.connectOnStartupController?.abort()
|
|
232
353
|
this.components.getUpgrader().removeEventListener('connection', this.onConnect)
|
|
233
354
|
this.components.getUpgrader().removeEventListener('connectionEnd', this.onDisconnect)
|
|
234
355
|
}
|
|
@@ -271,18 +392,6 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
271
392
|
this.connections.clear()
|
|
272
393
|
}
|
|
273
394
|
|
|
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
395
|
/**
|
|
287
396
|
* Checks the libp2p metrics to determine if any values have exceeded
|
|
288
397
|
* the configured maximums.
|
|
@@ -340,11 +449,10 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
340
449
|
await this.components.getPeerStore().keyBook.set(peerId, peerId.publicKey)
|
|
341
450
|
}
|
|
342
451
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
452
|
+
const numConnections = this.getConnections().length
|
|
453
|
+
const toPrune = numConnections - this.opts.maxConnections
|
|
346
454
|
|
|
347
|
-
await this._checkMaxLimit('maxConnections',
|
|
455
|
+
await this._checkMaxLimit('maxConnections', numConnections, toPrune)
|
|
348
456
|
this.dispatchEvent(new CustomEvent<Connection>('peer:connect', { detail: connection }))
|
|
349
457
|
}
|
|
350
458
|
|
|
@@ -367,7 +475,6 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
367
475
|
this.connections.set(peerId, storedConn)
|
|
368
476
|
} else if (storedConn != null) {
|
|
369
477
|
this.connections.delete(peerId)
|
|
370
|
-
this.peerValues.delete(connection.remotePeer.toString())
|
|
371
478
|
this.dispatchEvent(new CustomEvent<Connection>('peer:disconnect', { detail: connection }))
|
|
372
479
|
|
|
373
480
|
this.components.getMetrics()?.onPeerDisconnected(connection.remotePeer)
|
|
@@ -388,7 +495,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
388
495
|
return conns
|
|
389
496
|
}
|
|
390
497
|
|
|
391
|
-
async openConnection (peerId: PeerId, options
|
|
498
|
+
async openConnection (peerId: PeerId, options: AbortOptions = {}): Promise<Connection> {
|
|
392
499
|
log('dial to %p', peerId)
|
|
393
500
|
const existingConnections = this.getConnections(peerId)
|
|
394
501
|
|
|
@@ -398,30 +505,43 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
398
505
|
return existingConnections[0]
|
|
399
506
|
}
|
|
400
507
|
|
|
401
|
-
|
|
402
|
-
let peerConnections = this.connections.get(peerId.toString())
|
|
508
|
+
let timeoutController: TimeoutController | undefined
|
|
403
509
|
|
|
404
|
-
if (
|
|
405
|
-
|
|
406
|
-
|
|
510
|
+
if (options?.signal == null) {
|
|
511
|
+
timeoutController = new TimeoutController(this.dialTimeout)
|
|
512
|
+
options.signal = timeoutController.signal
|
|
407
513
|
}
|
|
408
514
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
let trackedConnection = false
|
|
515
|
+
try {
|
|
516
|
+
const connection = await this.dialer.dial(peerId, options)
|
|
517
|
+
let peerConnections = this.connections.get(peerId.toString())
|
|
413
518
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
519
|
+
if (peerConnections == null) {
|
|
520
|
+
peerConnections = []
|
|
521
|
+
this.connections.set(peerId.toString(), peerConnections)
|
|
417
522
|
}
|
|
418
|
-
}
|
|
419
523
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
524
|
+
// we get notified of connections via the Upgrader emitting "connection"
|
|
525
|
+
// events, double check we aren't already tracking this connection before
|
|
526
|
+
// storing it
|
|
527
|
+
let trackedConnection = false
|
|
423
528
|
|
|
424
|
-
|
|
529
|
+
for (const conn of peerConnections) {
|
|
530
|
+
if (conn.id === connection.id) {
|
|
531
|
+
trackedConnection = true
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if (!trackedConnection) {
|
|
536
|
+
peerConnections.push(connection)
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
return connection
|
|
540
|
+
} finally {
|
|
541
|
+
if (timeoutController != null) {
|
|
542
|
+
timeoutController.clear()
|
|
543
|
+
}
|
|
544
|
+
}
|
|
425
545
|
}
|
|
426
546
|
|
|
427
547
|
async closeConnections (peerId: PeerId): Promise<void> {
|
|
@@ -459,7 +579,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
459
579
|
_onLatencyMeasure (evt: CustomEvent<SummaryObject>) {
|
|
460
580
|
const { detail: summary } = evt
|
|
461
581
|
|
|
462
|
-
this._checkMaxLimit('maxEventLoopDelay', summary.avgMs)
|
|
582
|
+
this._checkMaxLimit('maxEventLoopDelay', summary.avgMs, 1)
|
|
463
583
|
.catch(err => {
|
|
464
584
|
log.error(err)
|
|
465
585
|
})
|
|
@@ -468,46 +588,86 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
468
588
|
/**
|
|
469
589
|
* If the `value` of `name` has exceeded its limit, maybe close a connection
|
|
470
590
|
*/
|
|
471
|
-
async _checkMaxLimit (name: keyof ConnectionManagerInit, value: number) {
|
|
591
|
+
async _checkMaxLimit (name: keyof ConnectionManagerInit, value: number, toPrune: number = 1) {
|
|
472
592
|
const limit = this.opts[name]
|
|
473
593
|
log.trace('checking limit of %s. current value: %d of %d', name, value, limit)
|
|
474
594
|
if (value > limit) {
|
|
475
|
-
log('%s: limit exceeded: %p, %d', this.components.getPeerId(), name, value)
|
|
476
|
-
await this.
|
|
595
|
+
log('%s: limit exceeded: %p, %d/%d, pruning %d connection(s)', this.components.getPeerId(), name, value, limit, toPrune)
|
|
596
|
+
await this._maybePruneConnections(toPrune)
|
|
477
597
|
}
|
|
478
598
|
}
|
|
479
599
|
|
|
480
600
|
/**
|
|
481
|
-
* If we have more connections than our maximum,
|
|
482
|
-
* to
|
|
601
|
+
* If we have more connections than our maximum, select some excess connections
|
|
602
|
+
* to prune based on peer value
|
|
483
603
|
*/
|
|
484
|
-
async
|
|
485
|
-
|
|
486
|
-
|
|
604
|
+
async _maybePruneConnections (toPrune: number) {
|
|
605
|
+
const connections = this.getConnections()
|
|
606
|
+
|
|
607
|
+
if (connections.length <= this.opts.minConnections || toPrune < 1) {
|
|
608
|
+
return
|
|
609
|
+
}
|
|
487
610
|
|
|
488
|
-
|
|
489
|
-
const disconnectPeer = peerValues[0]
|
|
611
|
+
const peerValues = new PeerMap<number>()
|
|
490
612
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
log('%p: closing a connection to %j', this.components.getPeerId(), peerId)
|
|
613
|
+
// work out peer values
|
|
614
|
+
for (const connection of connections) {
|
|
615
|
+
const remotePeer = connection.remotePeer
|
|
495
616
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
.catch(err => {
|
|
500
|
-
log.error(err)
|
|
501
|
-
})
|
|
617
|
+
if (peerValues.has(remotePeer)) {
|
|
618
|
+
continue
|
|
619
|
+
}
|
|
502
620
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
621
|
+
const tags = await this.components.getPeerStore().getTags(remotePeer)
|
|
622
|
+
|
|
623
|
+
// sum all tag values
|
|
624
|
+
peerValues.set(remotePeer, tags.reduce((acc, curr) => {
|
|
625
|
+
return acc + curr.value
|
|
626
|
+
}, 0))
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// sort by value, lowest to highest
|
|
630
|
+
const sortedConnections = connections.sort((a, b) => {
|
|
631
|
+
const peerAValue = peerValues.get(a.remotePeer) ?? 0
|
|
632
|
+
const peerBValue = peerValues.get(b.remotePeer) ?? 0
|
|
633
|
+
|
|
634
|
+
if (peerAValue > peerBValue) {
|
|
635
|
+
return 1
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
if (peerAValue < peerBValue) {
|
|
639
|
+
return -1
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
return 0
|
|
643
|
+
})
|
|
644
|
+
|
|
645
|
+
// close some connections
|
|
646
|
+
const toClose = []
|
|
647
|
+
|
|
648
|
+
for (const connection of sortedConnections) {
|
|
649
|
+
log('too many connections open - closing a connection to %p', connection.remotePeer)
|
|
650
|
+
toClose.push(connection)
|
|
651
|
+
|
|
652
|
+
if (toClose.length === toPrune) {
|
|
653
|
+
break
|
|
510
654
|
}
|
|
511
655
|
}
|
|
656
|
+
|
|
657
|
+
// close connections
|
|
658
|
+
await Promise.all(
|
|
659
|
+
toClose.map(async connection => {
|
|
660
|
+
try {
|
|
661
|
+
await connection.close()
|
|
662
|
+
} catch (err) {
|
|
663
|
+
log.error(err)
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// TODO: should not need to invoke this manually
|
|
667
|
+
this.onDisconnect(new CustomEvent<Connection>('connectionEnd', {
|
|
668
|
+
detail: connection
|
|
669
|
+
}))
|
|
670
|
+
})
|
|
671
|
+
)
|
|
512
672
|
}
|
|
513
673
|
}
|
package/src/constants.ts
CHANGED
|
@@ -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
|
}
|