libp2p 1.9.3 → 1.9.4-2bbaf4361

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 (100) hide show
  1. package/dist/index.min.js +17 -18
  2. package/dist/src/components.d.ts.map +1 -1
  3. package/dist/src/components.js +4 -3
  4. package/dist/src/components.js.map +1 -1
  5. package/dist/src/config.d.ts +1 -1
  6. package/dist/src/config.d.ts.map +1 -1
  7. package/dist/src/config.js +2 -7
  8. package/dist/src/config.js.map +1 -1
  9. package/dist/src/connection/index.d.ts +3 -3
  10. package/dist/src/connection/index.d.ts.map +1 -1
  11. package/dist/src/connection/index.js +7 -7
  12. package/dist/src/connection/index.js.map +1 -1
  13. package/dist/src/connection-manager/connection-pruner.js +1 -1
  14. package/dist/src/connection-manager/constants.browser.d.ts +0 -8
  15. package/dist/src/connection-manager/constants.browser.d.ts.map +1 -1
  16. package/dist/src/connection-manager/constants.browser.js +0 -8
  17. package/dist/src/connection-manager/constants.browser.js.map +1 -1
  18. package/dist/src/connection-manager/constants.d.ts +0 -8
  19. package/dist/src/connection-manager/constants.d.ts.map +1 -1
  20. package/dist/src/connection-manager/constants.defaults.d.ts +12 -22
  21. package/dist/src/connection-manager/constants.defaults.d.ts.map +1 -1
  22. package/dist/src/connection-manager/constants.defaults.js +12 -22
  23. package/dist/src/connection-manager/constants.defaults.js.map +1 -1
  24. package/dist/src/connection-manager/constants.js +0 -8
  25. package/dist/src/connection-manager/constants.js.map +1 -1
  26. package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
  27. package/dist/src/connection-manager/dial-queue.js +29 -15
  28. package/dist/src/connection-manager/dial-queue.js.map +1 -1
  29. package/dist/src/connection-manager/index.d.ts +47 -50
  30. package/dist/src/connection-manager/index.d.ts.map +1 -1
  31. package/dist/src/connection-manager/index.js +23 -57
  32. package/dist/src/connection-manager/index.js.map +1 -1
  33. package/dist/src/connection-manager/reconnect-queue.d.ts +35 -0
  34. package/dist/src/connection-manager/reconnect-queue.d.ts.map +1 -0
  35. package/dist/src/connection-manager/reconnect-queue.js +104 -0
  36. package/dist/src/connection-manager/reconnect-queue.js.map +1 -0
  37. package/dist/src/connection-monitor.d.ts +1 -0
  38. package/dist/src/connection-monitor.d.ts.map +1 -1
  39. package/dist/src/connection-monitor.js +15 -5
  40. package/dist/src/connection-monitor.js.map +1 -1
  41. package/dist/src/content-routing.js +6 -6
  42. package/dist/src/content-routing.js.map +1 -1
  43. package/dist/src/errors.d.ts +41 -61
  44. package/dist/src/errors.d.ts.map +1 -1
  45. package/dist/src/errors.js +84 -63
  46. package/dist/src/errors.js.map +1 -1
  47. package/dist/src/get-peer.d.ts.map +1 -1
  48. package/dist/src/get-peer.js +4 -5
  49. package/dist/src/get-peer.js.map +1 -1
  50. package/dist/src/index.d.ts +27 -9
  51. package/dist/src/index.d.ts.map +1 -1
  52. package/dist/src/index.js +10 -3
  53. package/dist/src/index.js.map +1 -1
  54. package/dist/src/libp2p.d.ts +11 -10
  55. package/dist/src/libp2p.d.ts.map +1 -1
  56. package/dist/src/libp2p.js +13 -31
  57. package/dist/src/libp2p.js.map +1 -1
  58. package/dist/src/peer-routing.js +8 -8
  59. package/dist/src/peer-routing.js.map +1 -1
  60. package/dist/src/registrar.js +7 -7
  61. package/dist/src/registrar.js.map +1 -1
  62. package/dist/src/transport-manager.d.ts.map +1 -1
  63. package/dist/src/transport-manager.js +15 -23
  64. package/dist/src/transport-manager.js.map +1 -1
  65. package/dist/src/upgrader.d.ts +8 -8
  66. package/dist/src/upgrader.d.ts.map +1 -1
  67. package/dist/src/upgrader.js +51 -51
  68. package/dist/src/upgrader.js.map +1 -1
  69. package/dist/src/version.d.ts +1 -1
  70. package/dist/src/version.d.ts.map +1 -1
  71. package/dist/src/version.js +1 -1
  72. package/dist/src/version.js.map +1 -1
  73. package/package.json +20 -20
  74. package/src/components.ts +4 -3
  75. package/src/config.ts +4 -10
  76. package/src/connection/index.ts +9 -9
  77. package/src/connection-manager/connection-pruner.ts +1 -1
  78. package/src/connection-manager/constants.browser.ts +0 -10
  79. package/src/connection-manager/constants.defaults.ts +14 -27
  80. package/src/connection-manager/constants.ts +0 -10
  81. package/src/connection-manager/dial-queue.ts +30 -15
  82. package/src/connection-manager/index.ts +80 -118
  83. package/src/connection-manager/reconnect-queue.ts +134 -0
  84. package/src/connection-monitor.ts +15 -6
  85. package/src/content-routing.ts +6 -6
  86. package/src/errors.ts +96 -61
  87. package/src/get-peer.ts +4 -5
  88. package/src/index.ts +42 -12
  89. package/src/libp2p.ts +22 -36
  90. package/src/peer-routing.ts +8 -8
  91. package/src/registrar.ts +7 -7
  92. package/src/transport-manager.ts +15 -23
  93. package/src/upgrader.ts +55 -56
  94. package/src/version.ts +1 -1
  95. package/dist/src/connection-manager/auto-dial.d.ts +0 -47
  96. package/dist/src/connection-manager/auto-dial.d.ts.map +0 -1
  97. package/dist/src/connection-manager/auto-dial.js +0 -223
  98. package/dist/src/connection-manager/auto-dial.js.map +0 -1
  99. package/dist/typedoc-urls.json +0 -14
  100. package/src/connection-manager/auto-dial.ts +0 -285
package/src/upgrader.ts CHANGED
@@ -1,12 +1,12 @@
1
- import { CodeError, ERR_TIMEOUT, setMaxListeners } from '@libp2p/interface'
1
+ import { InvalidMultiaddrError, InvalidPeerIdError, TooManyInboundProtocolStreamsError, TooManyOutboundProtocolStreamsError, LimitedConnectionError, TimeoutError, setMaxListeners } from '@libp2p/interface'
2
2
  import * as mss from '@libp2p/multistream-select'
3
3
  import { peerIdFromString } from '@libp2p/peer-id'
4
4
  import { CustomProgressEvent } from 'progress-events'
5
5
  import { createConnection } from './connection/index.js'
6
6
  import { INBOUND_UPGRADE_TIMEOUT } from './connection-manager/constants.js'
7
- import { codes } from './errors.js'
7
+ import { ConnectionDeniedError, ConnectionInterceptedError, EncryptionFailedError, MuxerUnavailableError } from './errors.js'
8
8
  import { DEFAULT_MAX_INBOUND_STREAMS, DEFAULT_MAX_OUTBOUND_STREAMS } from './registrar.js'
9
- import type { Libp2pEvents, AbortOptions, ComponentLogger, MultiaddrConnection, Connection, Stream, ConnectionProtector, NewStreamOptions, ConnectionEncrypter, SecuredConnection, ConnectionGater, TypedEventTarget, Metrics, PeerId, PeerStore, StreamMuxer, StreamMuxerFactory, Upgrader, UpgraderOptions } from '@libp2p/interface'
9
+ import type { Libp2pEvents, AbortOptions, ComponentLogger, MultiaddrConnection, Connection, Stream, ConnectionProtector, NewStreamOptions, ConnectionEncrypter, SecuredConnection, ConnectionGater, TypedEventTarget, Metrics, PeerId, PeerStore, StreamMuxer, StreamMuxerFactory, Upgrader, UpgraderOptions, ConnectionLimits, SecureConnectionOptions } from '@libp2p/interface'
10
10
  import type { ConnectionManager, Registrar } from '@libp2p/interface-internal'
11
11
 
12
12
  const DEFAULT_PROTOCOL_SELECT_TIMEOUT = 30000
@@ -18,7 +18,7 @@ interface CreateConnectionOptions {
18
18
  upgradedConn: MultiaddrConnection
19
19
  remotePeer: PeerId
20
20
  muxerFactory?: StreamMuxerFactory
21
- transient?: boolean
21
+ limits?: ConnectionLimits
22
22
  }
23
23
 
24
24
  interface OnStreamOptions {
@@ -32,8 +32,8 @@ export interface CryptoResult extends SecuredConnection<MultiaddrConnection> {
32
32
  }
33
33
 
34
34
  export interface UpgraderInit {
35
- connectionEncryption: ConnectionEncrypter[]
36
- muxers: StreamMuxerFactory[]
35
+ connectionEncrypters: ConnectionEncrypter[]
36
+ streamMuxers: StreamMuxerFactory[]
37
37
 
38
38
  /**
39
39
  * An amount of ms by which an inbound connection upgrade
@@ -48,7 +48,7 @@ function findIncomingStreamLimit (protocol: string, registrar: Registrar): numbe
48
48
 
49
49
  return options.maxInboundStreams
50
50
  } catch (err: any) {
51
- if (err.code !== codes.ERR_NO_HANDLER_FOR_PROTOCOL) {
51
+ if (err.name !== 'UnhandledProtocolError') {
52
52
  throw err
53
53
  }
54
54
  }
@@ -64,7 +64,7 @@ function findOutgoingStreamLimit (protocol: string, registrar: Registrar, option
64
64
  return options.maxOutboundStreams
65
65
  }
66
66
  } catch (err: any) {
67
- if (err.code !== codes.ERR_NO_HANDLER_FOR_PROTOCOL) {
67
+ if (err.name !== 'UnhandledProtocolError') {
68
68
  throw err
69
69
  }
70
70
  }
@@ -100,23 +100,23 @@ type ConnectionDeniedType = keyof Pick<ConnectionGater, 'denyOutboundConnection'
100
100
 
101
101
  export class DefaultUpgrader implements Upgrader {
102
102
  private readonly components: DefaultUpgraderComponents
103
- private readonly connectionEncryption: Map<string, ConnectionEncrypter>
104
- private readonly muxers: Map<string, StreamMuxerFactory>
103
+ private readonly connectionEncrypters: Map<string, ConnectionEncrypter>
104
+ private readonly streamMuxers: Map<string, StreamMuxerFactory>
105
105
  private readonly inboundUpgradeTimeout: number
106
106
  private readonly events: TypedEventTarget<Libp2pEvents>
107
107
 
108
108
  constructor (components: DefaultUpgraderComponents, init: UpgraderInit) {
109
109
  this.components = components
110
- this.connectionEncryption = new Map()
110
+ this.connectionEncrypters = new Map()
111
111
 
112
- init.connectionEncryption.forEach(encrypter => {
113
- this.connectionEncryption.set(encrypter.protocol, encrypter)
112
+ init.connectionEncrypters.forEach(encrypter => {
113
+ this.connectionEncrypters.set(encrypter.protocol, encrypter)
114
114
  })
115
115
 
116
- this.muxers = new Map()
116
+ this.streamMuxers = new Map()
117
117
 
118
- init.muxers.forEach(muxer => {
119
- this.muxers.set(muxer.protocol, muxer)
118
+ init.streamMuxers.forEach(muxer => {
119
+ this.streamMuxers.set(muxer.protocol, muxer)
120
120
  })
121
121
 
122
122
  this.inboundUpgradeTimeout = init.inboundUpgradeTimeout ?? INBOUND_UPGRADE_TIMEOUT
@@ -130,7 +130,7 @@ export class DefaultUpgrader implements Upgrader {
130
130
 
131
131
  if (connectionGater !== undefined) {
132
132
  if (await connectionGater(remotePeer, maConn)) {
133
- throw new CodeError(`The multiaddr connection is blocked by gater.${connectionType}`, codes.ERR_CONNECTION_INTERCEPTED)
133
+ throw new ConnectionInterceptedError(`The multiaddr connection is blocked by gater.${connectionType}`)
134
134
  }
135
135
  }
136
136
  }
@@ -142,7 +142,7 @@ export class DefaultUpgrader implements Upgrader {
142
142
  const accept = await this.components.connectionManager.acceptIncomingConnection(maConn)
143
143
 
144
144
  if (!accept) {
145
- throw new CodeError('connection denied', codes.ERR_CONNECTION_DENIED)
145
+ throw new ConnectionDeniedError('connection denied')
146
146
  }
147
147
 
148
148
  let encryptedConn: MultiaddrConnection
@@ -154,7 +154,7 @@ export class DefaultUpgrader implements Upgrader {
154
154
  const signal = AbortSignal.timeout(this.inboundUpgradeTimeout)
155
155
 
156
156
  const onAbort = (): void => {
157
- maConn.abort(new CodeError('inbound upgrade timeout', ERR_TIMEOUT))
157
+ maConn.abort(new TimeoutError('inbound upgrade timeout'))
158
158
  }
159
159
 
160
160
  signal.addEventListener('abort', onAbort, { once: true })
@@ -163,7 +163,7 @@ export class DefaultUpgrader implements Upgrader {
163
163
 
164
164
  try {
165
165
  if ((await this.components.connectionGater.denyInboundConnection?.(maConn)) === true) {
166
- throw new CodeError('The multiaddr connection is blocked by gater.acceptConnection', codes.ERR_CONNECTION_INTERCEPTED)
166
+ throw new ConnectionInterceptedError('The multiaddr connection is blocked by gater.acceptConnection')
167
167
  }
168
168
 
169
169
  this.components.metrics?.trackMultiaddrConnection(maConn)
@@ -204,7 +204,7 @@ export class DefaultUpgrader implements Upgrader {
204
204
  const idStr = maConn.remoteAddr.getPeerId()
205
205
 
206
206
  if (idStr == null) {
207
- throw new CodeError('inbound connection that skipped encryption must have a peer id', codes.ERR_INVALID_MULTIADDR)
207
+ throw new InvalidMultiaddrError('inbound connection that skipped encryption must have a peer id')
208
208
  }
209
209
 
210
210
  const remotePeerId = peerIdFromString(idStr)
@@ -216,14 +216,14 @@ export class DefaultUpgrader implements Upgrader {
216
216
  upgradedConn = encryptedConn
217
217
  if (opts?.muxerFactory != null) {
218
218
  muxerFactory = opts.muxerFactory
219
- } else if (this.muxers.size > 0) {
219
+ } else if (this.streamMuxers.size > 0) {
220
220
  opts?.onProgress?.(new CustomProgressEvent('upgrader:multiplex-inbound-connection'))
221
221
 
222
222
  // Multiplex the connection
223
223
  const multiplexed = await this._multiplexInbound({
224
224
  ...protectedConn,
225
225
  ...encryptedConn
226
- }, this.muxers)
226
+ }, this.streamMuxers)
227
227
  muxerFactory = multiplexed.muxerFactory
228
228
  upgradedConn = multiplexed.stream
229
229
  }
@@ -243,7 +243,7 @@ export class DefaultUpgrader implements Upgrader {
243
243
  upgradedConn,
244
244
  muxerFactory,
245
245
  remotePeer,
246
- transient: opts?.transient
246
+ limits: opts?.limits
247
247
  })
248
248
  } finally {
249
249
  signal.removeEventListener('abort', onAbort)
@@ -296,7 +296,10 @@ export class DefaultUpgrader implements Upgrader {
296
296
  conn: encryptedConn,
297
297
  remotePeer,
298
298
  protocol: cryptoProtocol
299
- } = await this._encryptOutbound(protectedConn, remotePeerId))
299
+ } = await this._encryptOutbound(protectedConn, {
300
+ ...opts,
301
+ remotePeer: remotePeerId
302
+ }))
300
303
 
301
304
  const maConn: MultiaddrConnection = {
302
305
  ...protectedConn,
@@ -306,7 +309,7 @@ export class DefaultUpgrader implements Upgrader {
306
309
  await this.shouldBlockConnection(remotePeer, maConn, 'denyOutboundEncryptedConnection')
307
310
  } else {
308
311
  if (remotePeerId == null) {
309
- throw new CodeError('Encryption was skipped but no peer id was passed', codes.ERR_INVALID_PEER)
312
+ throw new InvalidPeerIdError('Encryption was skipped but no peer id was passed')
310
313
  }
311
314
 
312
315
  cryptoProtocol = 'native'
@@ -316,12 +319,12 @@ export class DefaultUpgrader implements Upgrader {
316
319
  upgradedConn = encryptedConn
317
320
  if (opts?.muxerFactory != null) {
318
321
  muxerFactory = opts.muxerFactory
319
- } else if (this.muxers.size > 0) {
322
+ } else if (this.streamMuxers.size > 0) {
320
323
  // Multiplex the connection
321
324
  const multiplexed = await this._multiplexOutbound({
322
325
  ...protectedConn,
323
326
  ...encryptedConn
324
- }, this.muxers)
327
+ }, this.streamMuxers)
325
328
  muxerFactory = multiplexed.muxerFactory
326
329
  upgradedConn = multiplexed.stream
327
330
  }
@@ -342,7 +345,7 @@ export class DefaultUpgrader implements Upgrader {
342
345
  upgradedConn,
343
346
  muxerFactory,
344
347
  remotePeer,
345
- transient: opts?.transient
348
+ limits: opts?.limits
346
349
  })
347
350
  }
348
351
 
@@ -357,7 +360,7 @@ export class DefaultUpgrader implements Upgrader {
357
360
  upgradedConn,
358
361
  remotePeer,
359
362
  muxerFactory,
360
- transient
363
+ limits
361
364
  } = opts
362
365
 
363
366
  let muxer: StreamMuxer | undefined
@@ -392,7 +395,7 @@ export class DefaultUpgrader implements Upgrader {
392
395
  const streamCount = countStreams(protocol, 'inbound', connection)
393
396
 
394
397
  if (streamCount === incomingLimit) {
395
- const err = new CodeError(`Too many inbound protocol streams for protocol "${protocol}" - limit ${incomingLimit}`, codes.ERR_TOO_MANY_INBOUND_PROTOCOL_STREAMS)
398
+ const err = new TooManyInboundProtocolStreamsError(`Too many inbound protocol streams for protocol "${protocol}" - limit ${incomingLimit}`)
396
399
  muxedStream.abort(err)
397
400
 
398
401
  throw err
@@ -441,7 +444,7 @@ export class DefaultUpgrader implements Upgrader {
441
444
 
442
445
  newStream = async (protocols: string[], options: NewStreamOptions = {}): Promise<Stream> => {
443
446
  if (muxer == null) {
444
- throw new CodeError('Stream is not multiplexed', codes.ERR_MUXER_UNAVAILABLE)
447
+ throw new MuxerUnavailableError('Connection is not multiplexed')
445
448
  }
446
449
 
447
450
  connection.log('starting new stream for protocols %s', protocols)
@@ -478,7 +481,7 @@ export class DefaultUpgrader implements Upgrader {
478
481
  const streamCount = countStreams(protocol, 'outbound', connection)
479
482
 
480
483
  if (streamCount >= outgoingLimit) {
481
- const err = new CodeError(`Too many outbound protocol streams for protocol "${protocol}" - ${streamCount}/${outgoingLimit}`, codes.ERR_TOO_MANY_OUTBOUND_PROTOCOL_STREAMS)
484
+ const err = new TooManyOutboundProtocolStreamsError(`Too many outbound protocol streams for protocol "${protocol}" - ${streamCount}/${outgoingLimit}`)
482
485
  muxedStream.abort(err)
483
486
 
484
487
  throw err
@@ -521,11 +524,7 @@ export class DefaultUpgrader implements Upgrader {
521
524
  muxedStream.abort(err)
522
525
  }
523
526
 
524
- if (err.code != null) {
525
- throw err
526
- }
527
-
528
- throw new CodeError(String(err), codes.ERR_UNSUPPORTED_PROTOCOL)
527
+ throw err
529
528
  }
530
529
  }
531
530
 
@@ -566,7 +565,7 @@ export class DefaultUpgrader implements Upgrader {
566
565
  maConn.timeline.upgraded = Date.now()
567
566
 
568
567
  const errConnectionNotMultiplexed = (): any => {
569
- throw new CodeError('connection is not multiplexed', codes.ERR_CONNECTION_NOT_MULTIPLEXED)
568
+ throw new MuxerUnavailableError('Connection is not multiplexed')
570
569
  }
571
570
 
572
571
  // Create the connection
@@ -578,7 +577,7 @@ export class DefaultUpgrader implements Upgrader {
578
577
  timeline: maConn.timeline,
579
578
  multiplexer: muxer?.protocol,
580
579
  encryption: cryptoProtocol,
581
- transient,
580
+ limits,
582
581
  logger: this.components.logger,
583
582
  newStream: newStream ?? errConnectionNotMultiplexed,
584
583
  getStreams: () => { if (muxer != null) { return muxer.streams } else { return [] } },
@@ -617,8 +616,8 @@ export class DefaultUpgrader implements Upgrader {
617
616
  const { connection, stream, protocol } = opts
618
617
  const { handler, options } = this.components.registrar.getHandler(protocol)
619
618
 
620
- if (connection.transient && options.runOnTransientConnection !== true) {
621
- throw new CodeError('Cannot open protocol stream on transient connection', 'ERR_TRANSIENT_CONNECTION')
619
+ if (connection.limits != null && options.runOnLimitedConnection !== true) {
620
+ throw new LimitedConnectionError('Cannot open protocol stream on limited connection')
622
621
  }
623
622
 
624
623
  handler({ connection, stream })
@@ -627,15 +626,15 @@ export class DefaultUpgrader implements Upgrader {
627
626
  /**
628
627
  * Attempts to encrypt the incoming `connection` with the provided `cryptos`
629
628
  */
630
- async _encryptInbound (connection: MultiaddrConnection): Promise<CryptoResult> {
631
- const protocols = Array.from(this.connectionEncryption.keys())
629
+ async _encryptInbound (connection: MultiaddrConnection, options?: AbortOptions): Promise<CryptoResult> {
630
+ const protocols = Array.from(this.connectionEncrypters.keys())
632
631
  connection.log('handling inbound crypto protocol selection', protocols)
633
632
 
634
633
  try {
635
634
  const { stream, protocol } = await mss.handle(connection, protocols, {
636
635
  log: connection.log
637
636
  })
638
- const encrypter = this.connectionEncryption.get(protocol)
637
+ const encrypter = this.connectionEncrypters.get(protocol)
639
638
 
640
639
  if (encrypter == null) {
641
640
  throw new Error(`no crypto module found for ${protocol}`)
@@ -644,12 +643,12 @@ export class DefaultUpgrader implements Upgrader {
644
643
  connection.log('encrypting inbound connection using', protocol)
645
644
 
646
645
  return {
647
- ...await encrypter.secureInbound(this.components.peerId, stream),
646
+ ...await encrypter.secureInbound(stream, options),
648
647
  protocol
649
648
  }
650
649
  } catch (err: any) {
651
650
  connection.log.error('encrypting inbound connection failed', err)
652
- throw new CodeError(err.message, codes.ERR_ENCRYPTION_FAILED)
651
+ throw new EncryptionFailedError(err.message)
653
652
  }
654
653
  }
655
654
 
@@ -657,8 +656,8 @@ export class DefaultUpgrader implements Upgrader {
657
656
  * Attempts to encrypt the given `connection` with the provided connection encrypters.
658
657
  * The first `ConnectionEncrypter` module to succeed will be used
659
658
  */
660
- async _encryptOutbound (connection: MultiaddrConnection, remotePeerId?: PeerId): Promise<CryptoResult> {
661
- const protocols = Array.from(this.connectionEncryption.keys())
659
+ async _encryptOutbound (connection: MultiaddrConnection, options?: SecureConnectionOptions): Promise<CryptoResult> {
660
+ const protocols = Array.from(this.connectionEncrypters.keys())
662
661
  connection.log('selecting outbound crypto protocol', protocols)
663
662
 
664
663
  try {
@@ -672,21 +671,21 @@ export class DefaultUpgrader implements Upgrader {
672
671
  yieldBytes: true
673
672
  })
674
673
 
675
- const encrypter = this.connectionEncryption.get(protocol)
674
+ const encrypter = this.connectionEncrypters.get(protocol)
676
675
 
677
676
  if (encrypter == null) {
678
677
  throw new Error(`no crypto module found for ${protocol}`)
679
678
  }
680
679
 
681
- connection.log('encrypting outbound connection to %p using %s', remotePeerId, encrypter)
680
+ connection.log('encrypting outbound connection to %p using %s', options?.remotePeer, encrypter)
682
681
 
683
682
  return {
684
- ...await encrypter.secureOutbound(this.components.peerId, stream, remotePeerId),
683
+ ...await encrypter.secureOutbound(stream, options),
685
684
  protocol
686
685
  }
687
686
  } catch (err: any) {
688
- connection.log.error('encrypting outbound connection to %p failed', remotePeerId, err)
689
- throw new CodeError(err.message, codes.ERR_ENCRYPTION_FAILED)
687
+ connection.log.error('encrypting outbound connection to %p failed', options?.remotePeer, err)
688
+ throw new EncryptionFailedError(err.message)
690
689
  }
691
690
  }
692
691
 
@@ -714,7 +713,7 @@ export class DefaultUpgrader implements Upgrader {
714
713
  return { stream, muxerFactory }
715
714
  } catch (err: any) {
716
715
  connection.log.error('error multiplexing outbound connection', err)
717
- throw new CodeError(String(err), codes.ERR_MUXER_UNAVAILABLE)
716
+ throw new MuxerUnavailableError(String(err))
718
717
  }
719
718
  }
720
719
 
@@ -734,7 +733,7 @@ export class DefaultUpgrader implements Upgrader {
734
733
  return { stream, muxerFactory }
735
734
  } catch (err: any) {
736
735
  connection.log.error('error multiplexing inbound connection', err)
737
- throw new CodeError(String(err), codes.ERR_MUXER_UNAVAILABLE)
736
+ throw new MuxerUnavailableError(String(err))
738
737
  }
739
738
  }
740
739
  }
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
- export const version = '1.9.3'
1
+ export const version = '1.9.4-2bbaf4361'
2
2
  export const name = 'libp2p'
@@ -1,47 +0,0 @@
1
- import type { Libp2pEvents, ComponentLogger, TypedEventTarget, PeerStore, Startable, Metrics } from '@libp2p/interface';
2
- import type { ConnectionManager } from '@libp2p/interface-internal';
3
- interface AutoDialInit {
4
- minConnections?: number;
5
- maxQueueLength?: number;
6
- autoDialConcurrency?: number;
7
- autoDialPriority?: number;
8
- autoDialInterval?: number;
9
- autoDialPeerRetryThreshold?: number;
10
- autoDialDiscoveredPeersDebounce?: number;
11
- }
12
- interface AutoDialComponents {
13
- connectionManager: ConnectionManager;
14
- peerStore: PeerStore;
15
- events: TypedEventTarget<Libp2pEvents>;
16
- logger: ComponentLogger;
17
- metrics?: Metrics;
18
- }
19
- export declare class AutoDial implements Startable {
20
- private readonly connectionManager;
21
- private readonly peerStore;
22
- private readonly queue;
23
- private readonly minConnections;
24
- private readonly autoDialPriority;
25
- private readonly autoDialIntervalMs;
26
- private readonly autoDialMaxQueueLength;
27
- private readonly autoDialPeerRetryThresholdMs;
28
- private readonly autoDialDiscoveredPeersDebounce;
29
- private autoDialInterval?;
30
- private started;
31
- private running;
32
- private readonly log;
33
- /**
34
- * Proactively tries to connect to known peers stored in the PeerStore.
35
- * It will keep the number of connections below the upper limit and sort
36
- * the peers to connect based on whether we know their keys and protocols.
37
- */
38
- constructor(components: AutoDialComponents, init: AutoDialInit);
39
- isStarted(): boolean;
40
- start(): void;
41
- afterStart(): void;
42
- stop(): void;
43
- autoDial(): Promise<void>;
44
- private sheduleNextAutodial;
45
- }
46
- export {};
47
- //# sourceMappingURL=auto-dial.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auto-dial.d.ts","sourceRoot":"","sources":["../../../src/connection-manager/auto-dial.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAU,eAAe,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAC/H,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAEnE,UAAU,YAAY;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,0BAA0B,CAAC,EAAE,MAAM,CAAA;IACnC,+BAA+B,CAAC,EAAE,MAAM,CAAA;CACzC;AAED,UAAU,kBAAkB;IAC1B,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,SAAS,EAAE,SAAS,CAAA;IACpB,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAA;IACtC,MAAM,EAAE,eAAe,CAAA;IACvB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAYD,qBAAa,QAAS,YAAW,SAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAQ;IACzC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAQ;IAC3C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAQ;IAC/C,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAQ;IACrD,OAAO,CAAC,QAAQ,CAAC,+BAA+B,CAAQ;IACxD,OAAO,CAAC,gBAAgB,CAAC,CAAgC;IACzD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAE5B;;;;OAIG;gBACU,UAAU,EAAE,kBAAkB,EAAE,IAAI,EAAE,YAAY;IA8C/D,SAAS,IAAK,OAAO;IAIrB,KAAK,IAAK,IAAI;IAId,UAAU,IAAK,IAAI;IAOnB,IAAI,IAAK,IAAI;IAQP,QAAQ,IAAK,OAAO,CAAC,IAAI,CAAC;IAoJhC,OAAO,CAAC,mBAAmB;CAY5B"}
@@ -1,223 +0,0 @@
1
- import { PeerMap, PeerSet } from '@libp2p/peer-collections';
2
- import { PeerQueue } from '@libp2p/utils/peer-queue';
3
- import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
4
- import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_DISCOVERED_PEERS_DEBOUNCE, AUTO_DIAL_INTERVAL, AUTO_DIAL_MAX_QUEUE_LENGTH, AUTO_DIAL_PEER_RETRY_THRESHOLD, AUTO_DIAL_PRIORITY, LAST_DIAL_FAILURE_KEY, MIN_CONNECTIONS } from './constants.js';
5
- const defaultOptions = {
6
- minConnections: MIN_CONNECTIONS,
7
- maxQueueLength: AUTO_DIAL_MAX_QUEUE_LENGTH,
8
- autoDialConcurrency: AUTO_DIAL_CONCURRENCY,
9
- autoDialPriority: AUTO_DIAL_PRIORITY,
10
- autoDialInterval: AUTO_DIAL_INTERVAL,
11
- autoDialPeerRetryThreshold: AUTO_DIAL_PEER_RETRY_THRESHOLD,
12
- autoDialDiscoveredPeersDebounce: AUTO_DIAL_DISCOVERED_PEERS_DEBOUNCE
13
- };
14
- export class AutoDial {
15
- connectionManager;
16
- peerStore;
17
- queue;
18
- minConnections;
19
- autoDialPriority;
20
- autoDialIntervalMs;
21
- autoDialMaxQueueLength;
22
- autoDialPeerRetryThresholdMs;
23
- autoDialDiscoveredPeersDebounce;
24
- autoDialInterval;
25
- started;
26
- running;
27
- log;
28
- /**
29
- * Proactively tries to connect to known peers stored in the PeerStore.
30
- * It will keep the number of connections below the upper limit and sort
31
- * the peers to connect based on whether we know their keys and protocols.
32
- */
33
- constructor(components, init) {
34
- this.connectionManager = components.connectionManager;
35
- this.peerStore = components.peerStore;
36
- this.minConnections = init.minConnections ?? defaultOptions.minConnections;
37
- this.autoDialPriority = init.autoDialPriority ?? defaultOptions.autoDialPriority;
38
- this.autoDialIntervalMs = init.autoDialInterval ?? defaultOptions.autoDialInterval;
39
- this.autoDialMaxQueueLength = init.maxQueueLength ?? defaultOptions.maxQueueLength;
40
- this.autoDialPeerRetryThresholdMs = init.autoDialPeerRetryThreshold ?? defaultOptions.autoDialPeerRetryThreshold;
41
- this.autoDialDiscoveredPeersDebounce = init.autoDialDiscoveredPeersDebounce ?? defaultOptions.autoDialDiscoveredPeersDebounce;
42
- this.log = components.logger.forComponent('libp2p:connection-manager:auto-dial');
43
- this.started = false;
44
- this.running = false;
45
- this.queue = new PeerQueue({
46
- concurrency: init.autoDialConcurrency ?? defaultOptions.autoDialConcurrency,
47
- metricName: 'libp2p_autodial_queue',
48
- metrics: components.metrics
49
- });
50
- this.queue.addEventListener('error', (evt) => {
51
- this.log.error('error during auto-dial', evt.detail);
52
- });
53
- // check the min connection limit whenever a peer disconnects
54
- components.events.addEventListener('connection:close', () => {
55
- this.autoDial()
56
- .catch(err => {
57
- this.log.error(err);
58
- });
59
- });
60
- // sometimes peers are discovered in quick succession so add a small
61
- // debounce to ensure all eligible peers are autodialed
62
- let debounce;
63
- // when new peers are discovered, dial them if we don't have
64
- // enough connections
65
- components.events.addEventListener('peer:discovery', () => {
66
- clearTimeout(debounce);
67
- debounce = setTimeout(() => {
68
- this.autoDial()
69
- .catch(err => {
70
- this.log.error(err);
71
- });
72
- }, this.autoDialDiscoveredPeersDebounce);
73
- });
74
- }
75
- isStarted() {
76
- return this.started;
77
- }
78
- start() {
79
- this.started = true;
80
- }
81
- afterStart() {
82
- this.autoDial()
83
- .catch(err => {
84
- this.log.error('error while autodialing', err);
85
- });
86
- }
87
- stop() {
88
- // clear the queue
89
- this.queue.clear();
90
- clearTimeout(this.autoDialInterval);
91
- this.started = false;
92
- this.running = false;
93
- }
94
- async autoDial() {
95
- if (!this.started || this.running) {
96
- return;
97
- }
98
- const connections = this.connectionManager.getConnectionsMap();
99
- const numConnections = connections.size;
100
- // already have enough connections
101
- if (numConnections >= this.minConnections) {
102
- if (this.minConnections > 0) {
103
- this.log.trace('have enough connections %d/%d', numConnections, this.minConnections);
104
- }
105
- // no need to schedule next autodial as it will be run when on
106
- // connection:close event
107
- return;
108
- }
109
- if (this.queue.size > this.autoDialMaxQueueLength) {
110
- this.log('not enough connections %d/%d but auto dial queue is full', numConnections, this.minConnections);
111
- this.sheduleNextAutodial();
112
- return;
113
- }
114
- this.running = true;
115
- this.log('not enough connections %d/%d - will dial peers to increase the number of connections', numConnections, this.minConnections);
116
- const dialQueue = new PeerSet(
117
- // @ts-expect-error boolean filter removes falsy peer IDs
118
- this.connectionManager.getDialQueue()
119
- .map(queue => queue.peerId)
120
- .filter(Boolean));
121
- // sort peers on whether we know protocols or public keys for them
122
- const peers = await this.peerStore.all({
123
- filters: [
124
- // remove some peers
125
- (peer) => {
126
- // remove peers without addresses
127
- if (peer.addresses.length === 0) {
128
- this.log.trace('not autodialing %p because they have no addresses', peer.id);
129
- return false;
130
- }
131
- // remove peers we are already connected to
132
- if (connections.has(peer.id)) {
133
- this.log.trace('not autodialing %p because they are already connected', peer.id);
134
- return false;
135
- }
136
- // remove peers we are already dialling
137
- if (dialQueue.has(peer.id)) {
138
- this.log.trace('not autodialing %p because they are already being dialed', peer.id);
139
- return false;
140
- }
141
- // remove peers already in the autodial queue
142
- if (this.queue.has(peer.id)) {
143
- this.log.trace('not autodialing %p because they are already being autodialed', peer.id);
144
- return false;
145
- }
146
- return true;
147
- }
148
- ]
149
- });
150
- // shuffle the peers - this is so peers with the same tag values will be
151
- // dialled in a different order each time
152
- const shuffledPeers = peers.sort(() => Math.random() > 0.5 ? 1 : -1);
153
- // sort shuffled peers by tag value
154
- const peerValues = new PeerMap();
155
- for (const peer of shuffledPeers) {
156
- if (peerValues.has(peer.id)) {
157
- continue;
158
- }
159
- // sum all tag values
160
- peerValues.set(peer.id, [...peer.tags.values()].reduce((acc, curr) => {
161
- return acc + curr.value;
162
- }, 0));
163
- }
164
- // sort by value, highest to lowest
165
- const sortedPeers = shuffledPeers.sort((a, b) => {
166
- const peerAValue = peerValues.get(a.id) ?? 0;
167
- const peerBValue = peerValues.get(b.id) ?? 0;
168
- if (peerAValue > peerBValue) {
169
- return -1;
170
- }
171
- if (peerAValue < peerBValue) {
172
- return 1;
173
- }
174
- return 0;
175
- });
176
- const peersThatHaveNotFailed = sortedPeers.filter(peer => {
177
- const lastDialFailure = peer.metadata.get(LAST_DIAL_FAILURE_KEY);
178
- if (lastDialFailure == null) {
179
- return true;
180
- }
181
- const lastDialFailureTimestamp = parseInt(uint8ArrayToString(lastDialFailure));
182
- if (isNaN(lastDialFailureTimestamp)) {
183
- return true;
184
- }
185
- // only dial if the time since the last failure is above the retry threshold
186
- return Date.now() - lastDialFailureTimestamp > this.autoDialPeerRetryThresholdMs;
187
- });
188
- this.log('selected %d/%d peers to dial', peersThatHaveNotFailed.length, peers.length);
189
- for (const peer of peersThatHaveNotFailed) {
190
- this.queue.add(async () => {
191
- const numConnections = this.connectionManager.getConnectionsMap().size;
192
- // Check to see if we still need to auto dial
193
- if (numConnections >= this.minConnections) {
194
- this.log('got enough connections now %d/%d', numConnections, this.minConnections);
195
- this.queue.clear();
196
- return;
197
- }
198
- this.log('connecting to a peerStore stored peer %p', peer.id);
199
- await this.connectionManager.openConnection(peer.id, {
200
- priority: this.autoDialPriority
201
- });
202
- }, {
203
- peerId: peer.id
204
- }).catch(err => {
205
- this.log.error('could not connect to peerStore stored peer', err);
206
- });
207
- }
208
- this.running = false;
209
- this.sheduleNextAutodial();
210
- }
211
- sheduleNextAutodial() {
212
- if (!this.started) {
213
- return;
214
- }
215
- this.autoDialInterval = setTimeout(() => {
216
- this.autoDial()
217
- .catch(err => {
218
- this.log.error('error while autodialing', err);
219
- });
220
- }, this.autoDialIntervalMs);
221
- }
222
- }
223
- //# sourceMappingURL=auto-dial.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auto-dial.js","sourceRoot":"","sources":["../../../src/connection-manager/auto-dial.ts"],"names":[],"mappings":"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"}