libp2p 0.37.3-676cee2 → 0.37.3-6eaab2e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +1 -0
  2. package/dist/src/config.d.ts.map +1 -1
  3. package/dist/src/config.js +7 -3
  4. package/dist/src/config.js.map +1 -1
  5. package/dist/src/connection-manager/dialer/index.d.ts +4 -4
  6. package/dist/src/connection-manager/dialer/index.d.ts.map +1 -1
  7. package/dist/src/connection-manager/dialer/index.js +10 -10
  8. package/dist/src/connection-manager/dialer/index.js.map +1 -1
  9. package/dist/src/connection-manager/index.d.ts +15 -11
  10. package/dist/src/connection-manager/index.d.ts.map +1 -1
  11. package/dist/src/connection-manager/index.js +169 -62
  12. package/dist/src/connection-manager/index.js.map +1 -1
  13. package/dist/src/constants.d.ts +4 -0
  14. package/dist/src/constants.d.ts.map +1 -1
  15. package/dist/src/constants.js +4 -0
  16. package/dist/src/constants.js.map +1 -1
  17. package/dist/src/fetch/index.d.ts +4 -0
  18. package/dist/src/fetch/index.d.ts.map +1 -1
  19. package/dist/src/fetch/index.js +15 -5
  20. package/dist/src/fetch/index.js.map +1 -1
  21. package/dist/src/identify/index.d.ts +1 -1
  22. package/dist/src/identify/index.d.ts.map +1 -1
  23. package/dist/src/identify/index.js +9 -10
  24. package/dist/src/identify/index.js.map +1 -1
  25. package/dist/src/libp2p.d.ts.map +1 -1
  26. package/dist/src/libp2p.js +2 -12
  27. package/dist/src/libp2p.js.map +1 -1
  28. package/dist/src/metrics/index.d.ts +2 -2
  29. package/dist/src/metrics/index.d.ts.map +1 -1
  30. package/dist/src/metrics/index.js +6 -2
  31. package/dist/src/metrics/index.js.map +1 -1
  32. package/dist/src/ping/index.d.ts +4 -0
  33. package/dist/src/ping/index.d.ts.map +1 -1
  34. package/dist/src/ping/index.js +16 -6
  35. package/dist/src/ping/index.js.map +1 -1
  36. package/dist/src/upgrader.d.ts +6 -0
  37. package/dist/src/upgrader.d.ts.map +1 -1
  38. package/dist/src/upgrader.js +83 -59
  39. package/dist/src/upgrader.js.map +1 -1
  40. package/package.json +14 -13
  41. package/src/config.ts +7 -3
  42. package/src/connection-manager/dialer/index.ts +10 -10
  43. package/src/connection-manager/index.ts +220 -76
  44. package/src/constants.ts +5 -0
  45. package/src/fetch/index.ts +23 -6
  46. package/src/identify/index.ts +11 -12
  47. package/src/libp2p.ts +2 -13
  48. package/src/metrics/index.ts +8 -4
  49. package/src/ping/index.ts +24 -8
  50. package/src/upgrader.ts +95 -61
@@ -7,7 +7,6 @@ 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
11
  import { isPeerId, PeerId } from '@libp2p/interface-peer-id'
13
12
  import { setMaxListeners } from 'events'
@@ -18,6 +17,9 @@ import * as STATUS from '@libp2p/interface-connection/status'
18
17
  import { Dialer } from './dialer/index.js'
19
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: 0.5
35
+ movingAverageInterval: 60000
35
36
  }
36
37
 
38
+ const METRICS_SYSTEM = 'libp2p'
37
39
  const METRICS_COMPONENT = 'connection-manager'
38
- const METRICS_PEER_CONNECTIONS = 'peer-connections'
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 = trackedMap({
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,10 +449,6 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
340
449
  await this.components.getPeerStore().keyBook.set(peerId, peerId.publicKey)
341
450
  }
342
451
 
343
- if (!this.peerValues.has(peerIdStr)) {
344
- this.peerValues.set(peerIdStr, this.opts.defaultPeerValue)
345
- }
346
-
347
452
  const numConnections = this.getConnections().length
348
453
  const toPrune = numConnections - this.opts.maxConnections
349
454
 
@@ -370,7 +475,6 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
370
475
  this.connections.set(peerId, storedConn)
371
476
  } else if (storedConn != null) {
372
477
  this.connections.delete(peerId)
373
- this.peerValues.delete(connection.remotePeer.toString())
374
478
  this.dispatchEvent(new CustomEvent<Connection>('peer:disconnect', { detail: connection }))
375
479
 
376
480
  this.components.getMetrics()?.onPeerDisconnected(connection.remotePeer)
@@ -391,7 +495,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
391
495
  return conns
392
496
  }
393
497
 
394
- async openConnection (peerId: PeerId, options?: AbortOptions): Promise<Connection> {
498
+ async openConnection (peerId: PeerId, options: AbortOptions = {}): Promise<Connection> {
395
499
  log('dial to %p', peerId)
396
500
  const existingConnections = this.getConnections(peerId)
397
501
 
@@ -401,30 +505,43 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
401
505
  return existingConnections[0]
402
506
  }
403
507
 
404
- const connection = await this.dialer.dial(peerId, options)
405
- let peerConnections = this.connections.get(peerId.toString())
508
+ let timeoutController: TimeoutController | undefined
406
509
 
407
- if (peerConnections == null) {
408
- peerConnections = []
409
- this.connections.set(peerId.toString(), peerConnections)
510
+ if (options?.signal == null) {
511
+ timeoutController = new TimeoutController(this.dialTimeout)
512
+ options.signal = timeoutController.signal
410
513
  }
411
514
 
412
- // we get notified of connections via the Upgrader emitting "connection"
413
- // events, double check we aren't already tracking this connection before
414
- // storing it
415
- let trackedConnection = false
515
+ try {
516
+ const connection = await this.dialer.dial(peerId, options)
517
+ let peerConnections = this.connections.get(peerId.toString())
416
518
 
417
- for (const conn of peerConnections) {
418
- if (conn.id === connection.id) {
419
- trackedConnection = true
519
+ if (peerConnections == null) {
520
+ peerConnections = []
521
+ this.connections.set(peerId.toString(), peerConnections)
420
522
  }
421
- }
422
523
 
423
- if (!trackedConnection) {
424
- peerConnections.push(connection)
425
- }
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
426
528
 
427
- return connection
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
+ }
428
545
  }
429
546
 
430
547
  async closeConnections (peerId: PeerId): Promise<void> {
@@ -475,7 +592,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
475
592
  const limit = this.opts[name]
476
593
  log.trace('checking limit of %s. current value: %d of %d', name, value, limit)
477
594
  if (value > limit) {
478
- log('%s: limit exceeded: %p, %d, pruning %d connection(s)', this.components.getPeerId(), name, value, toPrune)
595
+ log('%s: limit exceeded: %p, %d/%d, pruning %d connection(s)', this.components.getPeerId(), name, value, limit, toPrune)
479
596
  await this._maybePruneConnections(toPrune)
480
597
  }
481
598
  }
@@ -491,22 +608,49 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
491
608
  return
492
609
  }
493
610
 
494
- const peerValues = Array.from(new Map([...this.peerValues.entries()].sort((a, b) => a[1] - b[1])))
495
- log.trace('sorted peer values: %j', peerValues)
611
+ const peerValues = new PeerMap<number>()
496
612
 
497
- const toClose = []
613
+ // work out peer values
614
+ for (const connection of connections) {
615
+ const remotePeer = connection.remotePeer
498
616
 
499
- for (const [peerId] of peerValues) {
500
- log('too many connections open - closing a connection to %p', peerId)
617
+ if (peerValues.has(remotePeer)) {
618
+ continue
619
+ }
501
620
 
502
- for (const connection of connections) {
503
- if (connection.remotePeer.toString() === peerId) {
504
- toClose.push(connection)
505
- }
621
+ const tags = await this.components.getPeerStore().getTags(remotePeer)
506
622
 
507
- if (toClose.length === toPrune) {
508
- break
509
- }
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
  }
512
656
 
package/src/constants.ts CHANGED
@@ -4,6 +4,11 @@
4
4
  */
5
5
  export const DIAL_TIMEOUT = 30e3
6
6
 
7
+ /**
8
+ * How long in ms an inbound connection upgrade is allowed to take
9
+ */
10
+ export const INBOUND_UPGRADE_TIMEOUT = 30e3
11
+
7
12
  /**
8
13
  * Maximum allowed concurrent dials
9
14
  */
@@ -10,10 +10,10 @@ import type { Stream } from '@libp2p/interface-connection'
10
10
  import type { IncomingStreamData } from '@libp2p/interface-registrar'
11
11
  import type { Components } from '@libp2p/components'
12
12
  import type { AbortOptions } from '@libp2p/interfaces'
13
- import type { Duplex } from 'it-stream-types'
14
13
  import { abortableDuplex } from 'abortable-iterator'
15
14
  import { pipe } from 'it-pipe'
16
15
  import first from 'it-first'
16
+ import { TimeoutController } from 'timeout-abort-controller'
17
17
 
18
18
  const log = logger('libp2p:fetch')
19
19
 
@@ -21,6 +21,11 @@ export interface FetchServiceInit {
21
21
  protocolPrefix: string
22
22
  maxInboundStreams: number
23
23
  maxOutboundStreams: number
24
+
25
+ /**
26
+ * How long we should wait for a remote peer to send any data
27
+ */
28
+ timeout: number
24
29
  }
25
30
 
26
31
  export interface HandleMessageOptions {
@@ -86,14 +91,22 @@ export class FetchService implements Startable {
86
91
  log('dialing %s to %p', this.protocol, peer)
87
92
 
88
93
  const connection = await this.components.getConnectionManager().openConnection(peer, options)
89
- const stream = await connection.newStream([this.protocol], options)
90
- let source: Duplex<Uint8Array> = stream
94
+ let timeoutController
95
+ let signal = options.signal
91
96
 
92
- // make stream abortable if AbortSignal passed
93
- if (options.signal != null) {
94
- source = abortableDuplex(stream, options.signal)
97
+ // create a timeout if no abort signal passed
98
+ if (signal == null) {
99
+ timeoutController = new TimeoutController(this.init.timeout)
100
+ signal = timeoutController.signal
95
101
  }
96
102
 
103
+ const stream = await connection.newStream([this.protocol], {
104
+ signal
105
+ })
106
+
107
+ // make stream abortable
108
+ const source = abortableDuplex(stream, signal)
109
+
97
110
  try {
98
111
  const result = await pipe(
99
112
  [FetchRequest.encode({ identifier: key })],
@@ -129,6 +142,10 @@ export class FetchService implements Startable {
129
142
 
130
143
  return result ?? null
131
144
  } finally {
145
+ if (timeoutController != null) {
146
+ timeoutController.clear()
147
+ }
148
+
132
149
  stream.close()
133
150
  }
134
151
  }
@@ -30,9 +30,6 @@ import type { Duplex } from 'it-stream-types'
30
30
 
31
31
  const log = logger('libp2p:identify')
32
32
 
33
- // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L48
34
- const IDENTIFY_TIMEOUT = 60000
35
-
36
33
  // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L52
37
34
  const MAX_IDENTIFY_MESSAGE_SIZE = 1024 * 8
38
35
 
@@ -54,7 +51,7 @@ export interface IdentifyServiceInit {
54
51
  /**
55
52
  * How long we should wait for a remote peer to send their identify response
56
53
  */
57
- timeout?: number
54
+ timeout: number
58
55
 
59
56
  /**
60
57
  * Identify responses larger than this in bytes will be rejected (default: 8192)
@@ -167,7 +164,7 @@ export class IdentifyService implements Startable {
167
164
  const protocols = await this.components.getPeerStore().protoBook.get(this.components.getPeerId())
168
165
 
169
166
  const pushes = connections.map(async connection => {
170
- const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
167
+ const timeoutController = new TimeoutController(this.init.timeout)
171
168
  let stream: Stream | undefined
172
169
 
173
170
  try {
@@ -229,19 +226,21 @@ export class IdentifyService implements Startable {
229
226
  }
230
227
 
231
228
  async _identify (connection: Connection, options: AbortOptions = {}): Promise<Identify> {
232
- const stream = await connection.newStream([this.identifyProtocolStr], options)
233
- let source: Duplex<Uint8Array> = stream
234
229
  let timeoutController
235
230
  let signal = options.signal
236
231
 
237
232
  // create a timeout if no abort signal passed
238
233
  if (signal == null) {
239
- timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
234
+ timeoutController = new TimeoutController(this.init.timeout)
240
235
  signal = timeoutController.signal
241
236
  }
242
237
 
243
- // make stream abortable if AbortSignal passed
244
- source = abortableDuplex(stream, signal)
238
+ const stream = await connection.newStream([this.identifyProtocolStr], {
239
+ signal
240
+ })
241
+
242
+ // make stream abortable
243
+ const source = abortableDuplex(stream, signal)
245
244
 
246
245
  try {
247
246
  const data = await pipe(
@@ -370,7 +369,7 @@ export class IdentifyService implements Startable {
370
369
  */
371
370
  async _handleIdentify (data: IncomingStreamData) {
372
371
  const { connection, stream } = data
373
- const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
372
+ const timeoutController = new TimeoutController(this.init.timeout)
374
373
 
375
374
  try {
376
375
  const publicKey = this.components.getPeerId().publicKey ?? new Uint8Array(0)
@@ -421,7 +420,7 @@ export class IdentifyService implements Startable {
421
420
  */
422
421
  async _handlePush (data: IncomingStreamData) {
423
422
  const { connection, stream } = data
424
- const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
423
+ const timeoutController = new TimeoutController(this.init.timeout)
425
424
 
426
425
  let message: Identify | undefined
427
426
  try {
package/src/libp2p.ts CHANGED
@@ -124,7 +124,8 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
124
124
  // Set up the Upgrader
125
125
  this.components.setUpgrader(new DefaultUpgrader(this.components, {
126
126
  connectionEncryption: (init.connectionEncryption ?? []).map(component => this.configureComponent(component)),
127
- muxers: (init.streamMuxers ?? []).map(component => this.configureComponent(component))
127
+ muxers: (init.streamMuxers ?? []).map(component => this.configureComponent(component)),
128
+ inboundUpgradeTimeout: init.connectionManager.inboundUpgradeTimeout
128
129
  }))
129
130
 
130
131
  // Create the Connection Manager
@@ -309,18 +310,6 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
309
310
  )
310
311
 
311
312
  log('libp2p has started')
312
-
313
- // Once we start, emit any peers we may have already discovered
314
- // TODO: this should be removed, as we already discovered these peers in the past
315
- await this.components.getPeerStore().forEach(peer => {
316
- this.dispatchEvent(new CustomEvent<PeerInfo>('peer:discovery', {
317
- detail: {
318
- id: peer.id,
319
- multiaddrs: peer.addresses.map(addr => addr.multiaddr),
320
- protocols: peer.protocols
321
- }
322
- }))
323
- })
324
313
  } catch (err: any) {
325
314
  log.error('An error occurred starting libp2p', err)
326
315
  await this.stop()
@@ -3,7 +3,7 @@ import each from 'it-foreach'
3
3
  import LRU from 'hashlru'
4
4
  import { METRICS as defaultOptions } from '../constants.js'
5
5
  import { DefaultStats, StatsInit } from './stats.js'
6
- import type { ComponentMetricsUpdate, Metrics, Stats, TrackStreamOptions } from '@libp2p/interface-metrics'
6
+ import type { ComponentMetricsUpdate, Metrics, Stats, TrackedMetric, TrackStreamOptions } from '@libp2p/interface-metrics'
7
7
  import type { PeerId } from '@libp2p/interface-peer-id'
8
8
  import type { Startable } from '@libp2p/interfaces/startable'
9
9
  import type { Duplex } from 'it-stream-types'
@@ -41,7 +41,7 @@ export class DefaultMetrics implements Metrics, Startable {
41
41
  private readonly protocolStats: Map<string, DefaultStats>
42
42
  private readonly oldPeers: ReturnType<typeof LRU>
43
43
  private running: boolean
44
- private readonly systems: Map<string, Map<string, Map<string, number>>>
44
+ private readonly systems: Map<string, Map<string, Map<string, TrackedMetric>>>
45
45
  private readonly statsInit: StatsInit
46
46
 
47
47
  constructor (init: MetricsInit) {
@@ -115,7 +115,7 @@ export class DefaultMetrics implements Metrics, Startable {
115
115
  }
116
116
 
117
117
  updateComponentMetric (update: ComponentMetricsUpdate) {
118
- const { system = 'libp2p', component, metric, value } = update
118
+ const { system = 'libp2p', component, metric, value, label, help } = update
119
119
 
120
120
  if (!this.systems.has(system)) {
121
121
  this.systems.set(system, new Map())
@@ -137,7 +137,11 @@ export class DefaultMetrics implements Metrics, Startable {
137
137
  throw new Error('Unknown metric component')
138
138
  }
139
139
 
140
- componentMetrics.set(metric, value)
140
+ componentMetrics.set(metric, {
141
+ label,
142
+ help,
143
+ calculate: typeof value !== 'function' ? () => value : value
144
+ })
141
145
  }
142
146
 
143
147
  /**