libp2p 0.37.2 → 0.37.3-3c0fb13
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 -2
- 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 +5 -4
- package/dist/src/circuit/circuit/hop.d.ts.map +1 -1
- package/dist/src/circuit/circuit/hop.js +8 -4
- package/dist/src/circuit/circuit/hop.js.map +1 -1
- package/dist/src/circuit/circuit/stop.d.ts +3 -2
- package/dist/src/circuit/circuit/stop.d.ts.map +1 -1
- package/dist/src/circuit/circuit/stop.js +4 -2
- 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 +4 -12
- package/dist/src/circuit/index.d.ts.map +1 -1
- package/dist/src/circuit/index.js.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 +8 -5
- package/dist/src/circuit/transport.d.ts.map +1 -1
- package/dist/src/circuit/transport.js +81 -59
- package/dist/src/circuit/transport.js.map +1 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +27 -4
- 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/auto-dialer.js +6 -0
- package/dist/src/connection-manager/dialer/auto-dialer.js.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 +209 -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 +82 -41
- 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 +48 -33
- package/dist/src/identify/index.js.map +1 -1
- package/dist/src/index.d.ts +18 -17
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.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 +17 -17
- 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 +31 -8
- 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 +164 -65
- 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 +15 -8
- package/src/circuit/circuit/stop.ts +8 -4
- package/src/circuit/circuit/stream-handler.ts +1 -1
- package/src/circuit/index.ts +4 -13
- package/src/circuit/listener.ts +3 -3
- package/src/circuit/transport.ts +90 -63
- package/src/config.ts +27 -4
- package/src/connection-manager/auto-dialler.ts +1 -1
- package/src/connection-manager/dialer/auto-dialer.ts +8 -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 +267 -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 +120 -53
- package/src/get-peer.ts +3 -3
- package/src/identify/index.ts +60 -42
- package/src/index.ts +18 -17
- package/src/insecure/index.ts +3 -3
- package/src/keychain/index.ts +2 -2
- package/src/libp2p.ts +34 -29
- 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 +47 -14
- 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 +204 -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,48 @@ 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
|
+
try {
|
|
335
|
+
// fails on node < 15.4
|
|
336
|
+
setMaxListeners?.(Infinity, this.connectOnStartupController.signal)
|
|
337
|
+
} catch {}
|
|
338
|
+
|
|
339
|
+
await Promise.all(
|
|
340
|
+
keepAlivePeers.map(async peer => {
|
|
341
|
+
await this.openConnection(peer, {
|
|
342
|
+
signal: this.connectOnStartupController?.signal
|
|
343
|
+
})
|
|
344
|
+
.catch(err => {
|
|
345
|
+
log.error(err)
|
|
346
|
+
})
|
|
347
|
+
})
|
|
348
|
+
)
|
|
349
|
+
})
|
|
350
|
+
.finally(() => {
|
|
351
|
+
this.connectOnStartupController?.clear()
|
|
352
|
+
})
|
|
229
353
|
}
|
|
230
354
|
|
|
231
355
|
async beforeStop () {
|
|
356
|
+
// if we are still dialing KEEP_ALIVE peers, abort those dials
|
|
357
|
+
this.connectOnStartupController?.abort()
|
|
232
358
|
this.components.getUpgrader().removeEventListener('connection', this.onConnect)
|
|
233
359
|
this.components.getUpgrader().removeEventListener('connectionEnd', this.onDisconnect)
|
|
234
360
|
}
|
|
@@ -271,18 +397,6 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
271
397
|
this.connections.clear()
|
|
272
398
|
}
|
|
273
399
|
|
|
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
400
|
/**
|
|
287
401
|
* Checks the libp2p metrics to determine if any values have exceeded
|
|
288
402
|
* the configured maximums.
|
|
@@ -340,11 +454,10 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
340
454
|
await this.components.getPeerStore().keyBook.set(peerId, peerId.publicKey)
|
|
341
455
|
}
|
|
342
456
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
457
|
+
const numConnections = this.getConnections().length
|
|
458
|
+
const toPrune = numConnections - this.opts.maxConnections
|
|
346
459
|
|
|
347
|
-
await this._checkMaxLimit('maxConnections',
|
|
460
|
+
await this._checkMaxLimit('maxConnections', numConnections, toPrune)
|
|
348
461
|
this.dispatchEvent(new CustomEvent<Connection>('peer:connect', { detail: connection }))
|
|
349
462
|
}
|
|
350
463
|
|
|
@@ -367,7 +480,6 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
367
480
|
this.connections.set(peerId, storedConn)
|
|
368
481
|
} else if (storedConn != null) {
|
|
369
482
|
this.connections.delete(peerId)
|
|
370
|
-
this.peerValues.delete(connection.remotePeer.toString())
|
|
371
483
|
this.dispatchEvent(new CustomEvent<Connection>('peer:disconnect', { detail: connection }))
|
|
372
484
|
|
|
373
485
|
this.components.getMetrics()?.onPeerDisconnected(connection.remotePeer)
|
|
@@ -388,7 +500,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
388
500
|
return conns
|
|
389
501
|
}
|
|
390
502
|
|
|
391
|
-
async openConnection (peerId: PeerId, options
|
|
503
|
+
async openConnection (peerId: PeerId, options: AbortOptions = {}): Promise<Connection> {
|
|
392
504
|
log('dial to %p', peerId)
|
|
393
505
|
const existingConnections = this.getConnections(peerId)
|
|
394
506
|
|
|
@@ -398,30 +510,48 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
398
510
|
return existingConnections[0]
|
|
399
511
|
}
|
|
400
512
|
|
|
401
|
-
|
|
402
|
-
let peerConnections = this.connections.get(peerId.toString())
|
|
513
|
+
let timeoutController: TimeoutController | undefined
|
|
403
514
|
|
|
404
|
-
if (
|
|
405
|
-
|
|
406
|
-
|
|
515
|
+
if (options?.signal == null) {
|
|
516
|
+
timeoutController = new TimeoutController(this.dialTimeout)
|
|
517
|
+
options.signal = timeoutController.signal
|
|
518
|
+
|
|
519
|
+
try {
|
|
520
|
+
// fails on node < 15.4
|
|
521
|
+
setMaxListeners?.(Infinity, timeoutController.signal)
|
|
522
|
+
} catch {}
|
|
407
523
|
}
|
|
408
524
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
let trackedConnection = false
|
|
525
|
+
try {
|
|
526
|
+
const connection = await this.dialer.dial(peerId, options)
|
|
527
|
+
let peerConnections = this.connections.get(peerId.toString())
|
|
413
528
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
529
|
+
if (peerConnections == null) {
|
|
530
|
+
peerConnections = []
|
|
531
|
+
this.connections.set(peerId.toString(), peerConnections)
|
|
417
532
|
}
|
|
418
|
-
}
|
|
419
533
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
534
|
+
// we get notified of connections via the Upgrader emitting "connection"
|
|
535
|
+
// events, double check we aren't already tracking this connection before
|
|
536
|
+
// storing it
|
|
537
|
+
let trackedConnection = false
|
|
423
538
|
|
|
424
|
-
|
|
539
|
+
for (const conn of peerConnections) {
|
|
540
|
+
if (conn.id === connection.id) {
|
|
541
|
+
trackedConnection = true
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
if (!trackedConnection) {
|
|
546
|
+
peerConnections.push(connection)
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
return connection
|
|
550
|
+
} finally {
|
|
551
|
+
if (timeoutController != null) {
|
|
552
|
+
timeoutController.clear()
|
|
553
|
+
}
|
|
554
|
+
}
|
|
425
555
|
}
|
|
426
556
|
|
|
427
557
|
async closeConnections (peerId: PeerId): Promise<void> {
|
|
@@ -459,7 +589,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
459
589
|
_onLatencyMeasure (evt: CustomEvent<SummaryObject>) {
|
|
460
590
|
const { detail: summary } = evt
|
|
461
591
|
|
|
462
|
-
this._checkMaxLimit('maxEventLoopDelay', summary.avgMs)
|
|
592
|
+
this._checkMaxLimit('maxEventLoopDelay', summary.avgMs, 1)
|
|
463
593
|
.catch(err => {
|
|
464
594
|
log.error(err)
|
|
465
595
|
})
|
|
@@ -468,46 +598,86 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
|
|
|
468
598
|
/**
|
|
469
599
|
* If the `value` of `name` has exceeded its limit, maybe close a connection
|
|
470
600
|
*/
|
|
471
|
-
async _checkMaxLimit (name: keyof ConnectionManagerInit, value: number) {
|
|
601
|
+
async _checkMaxLimit (name: keyof ConnectionManagerInit, value: number, toPrune: number = 1) {
|
|
472
602
|
const limit = this.opts[name]
|
|
473
603
|
log.trace('checking limit of %s. current value: %d of %d', name, value, limit)
|
|
474
604
|
if (value > limit) {
|
|
475
|
-
log('%s: limit exceeded: %p, %d', this.components.getPeerId(), name, value)
|
|
476
|
-
await this.
|
|
605
|
+
log('%s: limit exceeded: %p, %d/%d, pruning %d connection(s)', this.components.getPeerId(), name, value, limit, toPrune)
|
|
606
|
+
await this._maybePruneConnections(toPrune)
|
|
477
607
|
}
|
|
478
608
|
}
|
|
479
609
|
|
|
480
610
|
/**
|
|
481
|
-
* If we have more connections than our maximum,
|
|
482
|
-
* to
|
|
611
|
+
* If we have more connections than our maximum, select some excess connections
|
|
612
|
+
* to prune based on peer value
|
|
483
613
|
*/
|
|
484
|
-
async
|
|
485
|
-
|
|
486
|
-
const peerValues = Array.from(new Map([...this.peerValues.entries()].sort((a, b) => a[1] - b[1])))
|
|
614
|
+
async _maybePruneConnections (toPrune: number) {
|
|
615
|
+
const connections = this.getConnections()
|
|
487
616
|
|
|
488
|
-
|
|
489
|
-
|
|
617
|
+
if (connections.length <= this.opts.minConnections || toPrune < 1) {
|
|
618
|
+
return
|
|
619
|
+
}
|
|
490
620
|
|
|
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)
|
|
621
|
+
const peerValues = new PeerMap<number>()
|
|
495
622
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
.catch(err => {
|
|
500
|
-
log.error(err)
|
|
501
|
-
})
|
|
623
|
+
// work out peer values
|
|
624
|
+
for (const connection of connections) {
|
|
625
|
+
const remotePeer = connection.remotePeer
|
|
502
626
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
627
|
+
if (peerValues.has(remotePeer)) {
|
|
628
|
+
continue
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
const tags = await this.components.getPeerStore().getTags(remotePeer)
|
|
632
|
+
|
|
633
|
+
// sum all tag values
|
|
634
|
+
peerValues.set(remotePeer, tags.reduce((acc, curr) => {
|
|
635
|
+
return acc + curr.value
|
|
636
|
+
}, 0))
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// sort by value, lowest to highest
|
|
640
|
+
const sortedConnections = connections.sort((a, b) => {
|
|
641
|
+
const peerAValue = peerValues.get(a.remotePeer) ?? 0
|
|
642
|
+
const peerBValue = peerValues.get(b.remotePeer) ?? 0
|
|
643
|
+
|
|
644
|
+
if (peerAValue > peerBValue) {
|
|
645
|
+
return 1
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
if (peerAValue < peerBValue) {
|
|
649
|
+
return -1
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
return 0
|
|
653
|
+
})
|
|
654
|
+
|
|
655
|
+
// close some connections
|
|
656
|
+
const toClose = []
|
|
657
|
+
|
|
658
|
+
for (const connection of sortedConnections) {
|
|
659
|
+
log('too many connections open - closing a connection to %p', connection.remotePeer)
|
|
660
|
+
toClose.push(connection)
|
|
661
|
+
|
|
662
|
+
if (toClose.length === toPrune) {
|
|
663
|
+
break
|
|
510
664
|
}
|
|
511
665
|
}
|
|
666
|
+
|
|
667
|
+
// close connections
|
|
668
|
+
await Promise.all(
|
|
669
|
+
toClose.map(async connection => {
|
|
670
|
+
try {
|
|
671
|
+
await connection.close()
|
|
672
|
+
} catch (err) {
|
|
673
|
+
log.error(err)
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// TODO: should not need to invoke this manually
|
|
677
|
+
this.onDisconnect(new CustomEvent<Connection>('connectionEnd', {
|
|
678
|
+
detail: connection
|
|
679
|
+
}))
|
|
680
|
+
})
|
|
681
|
+
)
|
|
512
682
|
}
|
|
513
683
|
}
|
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
|
}
|