libp2p 0.43.4 → 0.44.0

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 (105) hide show
  1. package/dist/index.min.js +30 -30
  2. package/dist/src/autonat/index.d.ts +1 -2
  3. package/dist/src/autonat/index.d.ts.map +1 -1
  4. package/dist/src/autonat/index.js +4 -6
  5. package/dist/src/autonat/index.js.map +1 -1
  6. package/dist/src/circuit-relay/transport/reservation-store.d.ts +1 -1
  7. package/dist/src/circuit-relay/transport/reservation-store.d.ts.map +1 -1
  8. package/dist/src/circuit-relay/utils.d.ts.map +1 -1
  9. package/dist/src/circuit-relay/utils.js +3 -1
  10. package/dist/src/circuit-relay/utils.js.map +1 -1
  11. package/dist/src/components.d.ts +1 -6
  12. package/dist/src/components.d.ts.map +1 -1
  13. package/dist/src/components.js +0 -10
  14. package/dist/src/components.js.map +1 -1
  15. package/dist/src/config.d.ts.map +1 -1
  16. package/dist/src/config.js +0 -9
  17. package/dist/src/config.js.map +1 -1
  18. package/dist/src/connection-manager/auto-dial.d.ts +36 -0
  19. package/dist/src/connection-manager/auto-dial.d.ts.map +1 -0
  20. package/dist/src/connection-manager/auto-dial.js +122 -0
  21. package/dist/src/connection-manager/auto-dial.js.map +1 -0
  22. package/dist/src/connection-manager/connection-pruner.d.ts +28 -0
  23. package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -0
  24. package/dist/src/connection-manager/connection-pruner.js +96 -0
  25. package/dist/src/connection-manager/connection-pruner.js.map +1 -0
  26. package/dist/src/connection-manager/constants.d.ts +49 -0
  27. package/dist/src/connection-manager/constants.d.ts.map +1 -0
  28. package/dist/src/connection-manager/constants.js +49 -0
  29. package/dist/src/connection-manager/constants.js.map +1 -0
  30. package/dist/src/connection-manager/dial-queue.d.ts +77 -0
  31. package/dist/src/connection-manager/dial-queue.d.ts.map +1 -0
  32. package/dist/src/connection-manager/dial-queue.js +366 -0
  33. package/dist/src/connection-manager/dial-queue.js.map +1 -0
  34. package/dist/src/connection-manager/index.d.ts +65 -69
  35. package/dist/src/connection-manager/index.d.ts.map +1 -1
  36. package/dist/src/connection-manager/index.js +116 -234
  37. package/dist/src/connection-manager/index.js.map +1 -1
  38. package/dist/src/connection-manager/utils.d.ts +9 -0
  39. package/dist/src/connection-manager/utils.d.ts.map +1 -0
  40. package/dist/src/connection-manager/utils.js +66 -0
  41. package/dist/src/connection-manager/utils.js.map +1 -0
  42. package/dist/src/fetch/index.js +3 -3
  43. package/dist/src/fetch/index.js.map +1 -1
  44. package/dist/src/identify/index.js +5 -5
  45. package/dist/src/identify/index.js.map +1 -1
  46. package/dist/src/insecure/index.d.ts.map +1 -1
  47. package/dist/src/insecure/index.js +3 -1
  48. package/dist/src/insecure/index.js.map +1 -1
  49. package/dist/src/libp2p.d.ts +10 -2
  50. package/dist/src/libp2p.d.ts.map +1 -1
  51. package/dist/src/libp2p.js +7 -13
  52. package/dist/src/libp2p.js.map +1 -1
  53. package/dist/src/upgrader.d.ts +1 -1
  54. package/dist/src/upgrader.d.ts.map +1 -1
  55. package/dist/src/upgrader.js +2 -1
  56. package/dist/src/upgrader.js.map +1 -1
  57. package/dist/typedoc-urls.json +1 -1
  58. package/package.json +18 -18
  59. package/src/autonat/index.ts +6 -9
  60. package/src/circuit-relay/transport/reservation-store.ts +1 -1
  61. package/src/circuit-relay/utils.ts +3 -1
  62. package/src/components.ts +1 -17
  63. package/src/config.ts +0 -9
  64. package/src/connection-manager/auto-dial.ts +171 -0
  65. package/src/connection-manager/connection-pruner.ts +137 -0
  66. package/src/connection-manager/constants.ts +60 -0
  67. package/src/connection-manager/dial-queue.ts +504 -0
  68. package/src/connection-manager/index.ts +190 -323
  69. package/src/connection-manager/utils.ts +76 -0
  70. package/src/fetch/index.ts +4 -4
  71. package/src/identify/index.ts +5 -5
  72. package/src/insecure/index.ts +5 -1
  73. package/src/libp2p.ts +17 -15
  74. package/src/upgrader.ts +3 -2
  75. package/src/version.ts +1 -1
  76. package/dist/src/connection-manager/auto-dialler.d.ts +0 -42
  77. package/dist/src/connection-manager/auto-dialler.d.ts.map +0 -1
  78. package/dist/src/connection-manager/auto-dialler.js +0 -105
  79. package/dist/src/connection-manager/auto-dialler.js.map +0 -1
  80. package/dist/src/connection-manager/dialer/dial-request.d.ts +0 -27
  81. package/dist/src/connection-manager/dialer/dial-request.d.ts.map +0 -1
  82. package/dist/src/connection-manager/dialer/dial-request.js +0 -114
  83. package/dist/src/connection-manager/dialer/dial-request.js.map +0 -1
  84. package/dist/src/connection-manager/dialer/index.d.ts +0 -121
  85. package/dist/src/connection-manager/dialer/index.d.ts.map +0 -1
  86. package/dist/src/connection-manager/dialer/index.js +0 -324
  87. package/dist/src/connection-manager/dialer/index.js.map +0 -1
  88. package/dist/src/connection-manager/latency-monitor.d.ts +0 -120
  89. package/dist/src/connection-manager/latency-monitor.d.ts.map +0 -1
  90. package/dist/src/connection-manager/latency-monitor.js +0 -220
  91. package/dist/src/connection-manager/latency-monitor.js.map +0 -1
  92. package/dist/src/connection-manager/visibility-change-emitter.d.ts +0 -66
  93. package/dist/src/connection-manager/visibility-change-emitter.d.ts.map +0 -1
  94. package/dist/src/connection-manager/visibility-change-emitter.js +0 -118
  95. package/dist/src/connection-manager/visibility-change-emitter.js.map +0 -1
  96. package/dist/src/constants.d.ts +0 -27
  97. package/dist/src/constants.d.ts.map +0 -1
  98. package/dist/src/constants.js +0 -31
  99. package/dist/src/constants.js.map +0 -1
  100. package/src/connection-manager/auto-dialler.ts +0 -158
  101. package/src/connection-manager/dialer/dial-request.ts +0 -144
  102. package/src/connection-manager/dialer/index.ts +0 -461
  103. package/src/connection-manager/latency-monitor.ts +0 -319
  104. package/src/connection-manager/visibility-change-emitter.ts +0 -135
  105. package/src/constants.ts +0 -36
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libp2p",
3
- "version": "0.43.4",
3
+ "version": "0.44.0",
4
4
  "description": "JavaScript implementation of libp2p, a modular peer to peer network stack",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "homepage": "https://github.com/libp2p/js-libp2p#readme",
@@ -102,10 +102,10 @@
102
102
  "@achingbrain/nat-port-mapper": "^1.0.3",
103
103
  "@libp2p/crypto": "^1.0.4",
104
104
  "@libp2p/interface-address-manager": "^2.0.0",
105
- "@libp2p/interface-connection": "^3.0.2",
105
+ "@libp2p/interface-connection": "^4.0.0",
106
106
  "@libp2p/interface-connection-encrypter": "^3.0.1",
107
- "@libp2p/interface-connection-gater": "^1.0.0",
108
- "@libp2p/interface-connection-manager": "^1.1.1",
107
+ "@libp2p/interface-connection-gater": "^2.0.1",
108
+ "@libp2p/interface-connection-manager": "^2.1.0",
109
109
  "@libp2p/interface-content-routing": "^2.0.0",
110
110
  "@libp2p/interface-dht": "^2.0.0",
111
111
  "@libp2p/interface-keychain": "^2.0.4",
@@ -136,21 +136,21 @@
136
136
  "@multiformats/mafmt": "^12.0.0",
137
137
  "@multiformats/multiaddr": "^12.0.0",
138
138
  "abortable-iterator": "^4.0.2",
139
- "any-signal": "^3.0.0",
139
+ "any-signal": "^4.1.1",
140
140
  "datastore-core": "^9.0.0",
141
141
  "interface-datastore": "^8.0.0",
142
- "it-all": "^2.0.0",
143
- "it-drain": "^2.0.0",
144
- "it-filter": "^2.0.0",
145
- "it-first": "^2.0.0",
146
- "it-parallel": "^3.0.0",
142
+ "it-all": "^3.0.1",
143
+ "it-drain": "^3.0.1",
144
+ "it-filter": "^3.0.1",
145
+ "it-first": "^3.0.1",
147
146
  "it-handshake": "^4.1.2",
148
- "it-length-prefixed": "^8.0.2",
149
- "it-map": "^2.0.0",
150
- "it-merge": "^2.0.0",
147
+ "it-length-prefixed": "^9.0.0",
148
+ "it-map": "^3.0.2",
149
+ "it-merge": "^3.0.0",
151
150
  "it-pair": "^2.0.2",
151
+ "it-parallel": "^3.0.0",
152
152
  "it-pb-stream": "^3.2.0",
153
- "it-pipe": "^2.0.3",
153
+ "it-pipe": "^3.0.1",
154
154
  "it-stream-types": "^1.0.4",
155
155
  "merge-options": "^3.0.4",
156
156
  "multiformats": "^11.0.0",
@@ -172,7 +172,7 @@
172
172
  "devDependencies": {
173
173
  "@chainsafe/libp2p-gossipsub": "^6.2.0",
174
174
  "@chainsafe/libp2p-noise": "^11.0.0",
175
- "@chainsafe/libp2p-yamux": "^3.0.3",
175
+ "@chainsafe/libp2p-yamux": "^3.0.8",
176
176
  "@libp2p/bootstrap": "^6.0.0",
177
177
  "@libp2p/daemon-client": "^5.0.0",
178
178
  "@libp2p/daemon-server": "^4.1.0",
@@ -182,9 +182,9 @@
182
182
  "@libp2p/interface-connection-encrypter-compliance-tests": "^4.0.0",
183
183
  "@libp2p/interface-mocks": "^9.0.0",
184
184
  "@libp2p/interop": "^7.0.0",
185
- "@libp2p/kad-dht": "^8.0.0",
185
+ "@libp2p/kad-dht": "^8.0.7",
186
186
  "@libp2p/mdns": "^7.0.0",
187
- "@libp2p/mplex": "^7.0.0",
187
+ "@libp2p/mplex": "^7.1.6",
188
188
  "@libp2p/pubsub": "^6.0.0",
189
189
  "@libp2p/tcp": "^6.0.0",
190
190
  "@libp2p/websockets": "^5.0.0",
@@ -197,7 +197,7 @@
197
197
  "execa": "^7.0.0",
198
198
  "go-libp2p": "^1.0.1",
199
199
  "it-pushable": "^3.0.0",
200
- "it-to-buffer": "^3.0.1",
200
+ "it-to-buffer": "^4.0.1",
201
201
  "npm-run-all": "^4.1.5",
202
202
  "p-event": "^5.0.1",
203
203
  "p-times": "^4.0.0",
@@ -1,6 +1,6 @@
1
1
  import type { AddressManager } from '@libp2p/interface-address-manager'
2
2
  import type { Connection } from '@libp2p/interface-connection'
3
- import type { ConnectionManager, Dialer } from '@libp2p/interface-connection-manager'
3
+ import type { ConnectionManager } from '@libp2p/interface-connection-manager'
4
4
  import type { PeerId } from '@libp2p/interface-peer-id'
5
5
  import type { PeerInfo } from '@libp2p/interface-peer-info'
6
6
  import type { PeerRouting } from '@libp2p/interface-peer-routing'
@@ -74,7 +74,6 @@ export interface DefaultAutonatComponents {
74
74
  registrar: Registrar
75
75
  addressManager: AddressManager
76
76
  transportManager: TransportManager
77
- dialer: Dialer
78
77
  peerId: PeerId
79
78
  connectionManager: ConnectionManager
80
79
  peerRouting: PeerRouting
@@ -151,7 +150,7 @@ export class AutonatService implements Startable {
151
150
 
152
151
  await pipe(
153
152
  source,
154
- lp.decode(),
153
+ (source) => lp.decode(source),
155
154
  async function * (stream) {
156
155
  const buf = await first(stream)
157
156
 
@@ -319,9 +318,7 @@ export class AutonatService implements Startable {
319
318
  lastMultiaddr = multiaddr
320
319
 
321
320
  try {
322
- // use the dialer so we can dial a specific multiaddr instead of every known
323
- // multiaddr for the peer
324
- connection = await self.components.dialer.dial(multiaddr, {
321
+ connection = await self.components.connectionManager.openConnection(multiaddr, {
325
322
  signal: controller.signal
326
323
  })
327
324
 
@@ -360,7 +357,7 @@ export class AutonatService implements Startable {
360
357
  }
361
358
  })
362
359
  },
363
- lp.encode(),
360
+ (source) => lp.encode(source),
364
361
  // pipe to the stream, not the abortable source other wise we
365
362
  // can't tell the remote when a dial timed out..
366
363
  data.stream
@@ -449,9 +446,9 @@ export class AutonatService implements Startable {
449
446
 
450
447
  const buf = await pipe(
451
448
  [request],
452
- lp.encode(),
449
+ (source) => lp.encode(source),
453
450
  source,
454
- lp.decode(),
451
+ (source) => lp.decode(source),
455
452
  async (stream) => await first(stream)
456
453
  )
457
454
  if (buf == null) {
@@ -10,7 +10,7 @@ import type { Reservation } from '../pb/index.js'
10
10
  import { HopMessage, Status } from '../pb/index.js'
11
11
  import { getExpirationMilliseconds } from '../utils.js'
12
12
  import type { TransportManager } from '@libp2p/interface-transport'
13
- import type { Startable } from '@libp2p/interfaces/dist/src/startable.js'
13
+ import type { Startable } from '@libp2p/interfaces/startable'
14
14
  import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events'
15
15
  import type { PeerStore } from '@libp2p/interface-peer-store'
16
16
  import { multiaddr } from '@multiformats/multiaddr'
@@ -7,7 +7,7 @@ import { logger } from '@libp2p/logger'
7
7
  import type { Stream } from '@libp2p/interface-connection'
8
8
  import { DEFAULT_DATA_LIMIT, DEFAULT_DURATION_LIMIT } from './constants.js'
9
9
  import { abortableSource } from 'abortable-iterator'
10
- import anySignal from 'any-signal'
10
+ import { anySignal } from 'any-signal'
11
11
 
12
12
  const log = logger('libp2p:circuit-relay:utils')
13
13
 
@@ -69,6 +69,7 @@ const doRelay = (src: Stream, dst: Stream, abortSignal: AbortSignal, limit: Requ
69
69
  srcDstFinished = true
70
70
 
71
71
  if (dstSrcFinished) {
72
+ signal.clear()
72
73
  clearTimeout(timeout)
73
74
  }
74
75
  })
@@ -86,6 +87,7 @@ const doRelay = (src: Stream, dst: Stream, abortSignal: AbortSignal, limit: Requ
86
87
  dstSrcFinished = true
87
88
 
88
89
  if (srcDstFinished) {
90
+ signal.clear()
89
91
  clearTimeout(timeout)
90
92
  }
91
93
  })
package/src/components.ts CHANGED
@@ -12,7 +12,7 @@ import type { TransportManager, Upgrader } from '@libp2p/interface-transport'
12
12
  import type { Datastore } from 'interface-datastore'
13
13
  import type { PubSub } from '@libp2p/interface-pubsub'
14
14
  import type { DualDHT } from '@libp2p/interface-dht'
15
- import type { ConnectionManager, Dialer } from '@libp2p/interface-connection-manager'
15
+ import type { ConnectionManager } from '@libp2p/interface-connection-manager'
16
16
  import type { ConnectionGater } from '@libp2p/interface-connection-gater'
17
17
 
18
18
  export interface Components {
@@ -28,7 +28,6 @@ export interface Components {
28
28
  peerRouting: PeerRouting
29
29
  datastore: Datastore
30
30
  connectionProtector?: ConnectionProtector
31
- dialer: Dialer
32
31
  metrics?: Metrics
33
32
  dht?: DualDHT
34
33
  pubsub?: PubSub
@@ -50,7 +49,6 @@ export interface ComponentsInit {
50
49
  connectionProtector?: ConnectionProtector
51
50
  dht?: DualDHT
52
51
  pubsub?: PubSub
53
- dialer?: Dialer
54
52
  }
55
53
 
56
54
  export class DefaultComponents implements Components, Startable {
@@ -69,7 +67,6 @@ export class DefaultComponents implements Components, Startable {
69
67
  private _connectionProtector?: ConnectionProtector
70
68
  private _dht?: DualDHT
71
69
  private _pubsub?: PubSub
72
- private _dialer?: Dialer
73
70
  private _started = false
74
71
 
75
72
  constructor (init: ComponentsInit = {}) {
@@ -88,7 +85,6 @@ export class DefaultComponents implements Components, Startable {
88
85
  this._connectionProtector = init.connectionProtector
89
86
  this._dht = init.dht
90
87
  this._pubsub = init.pubsub
91
- this._dialer = init.dialer
92
88
  }
93
89
 
94
90
  isStarted (): boolean {
@@ -295,18 +291,6 @@ export class DefaultComponents implements Components, Startable {
295
291
  this._connectionProtector = connectionProtector
296
292
  }
297
293
 
298
- get dialer (): Dialer {
299
- if (this._dialer == null) {
300
- throw new CodeError('dialer not set', 'ERR_SERVICE_MISSING')
301
- }
302
-
303
- return this._dialer
304
- }
305
-
306
- set dialer (dialer: Dialer) {
307
- this._dialer = dialer
308
- }
309
-
310
294
  get metrics (): Metrics | undefined {
311
295
  return this._metrics
312
296
  }
package/src/config.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import mergeOptions from 'merge-options'
2
2
  import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers'
3
- import * as Constants from './constants.js'
4
3
  import { AGENT_VERSION } from './identify/consts.js'
5
4
  import { publicAddressesFirst } from '@libp2p/utils/address-sort'
6
5
  import { FaultTolerance } from '@libp2p/interface-transport'
@@ -19,19 +18,11 @@ const DefaultConfig: Partial<Libp2pInit> = {
19
18
  announceFilter: (multiaddrs: Multiaddr[]) => multiaddrs
20
19
  },
21
20
  connectionManager: {
22
- maxConnections: 300,
23
- minConnections: 50,
24
- autoDialInterval: 10000,
25
- maxParallelDials: Constants.MAX_PARALLEL_DIALS,
26
- maxDialsPerPeer: Constants.MAX_PER_PEER_DIALS,
27
- dialTimeout: Constants.DIAL_TIMEOUT,
28
- inboundUpgradeTimeout: Constants.INBOUND_UPGRADE_TIMEOUT,
29
21
  resolvers: {
30
22
  dnsaddr: dnsaddrResolver
31
23
  },
32
24
  addressSorter: publicAddressesFirst
33
25
  },
34
- connectionGater: {},
35
26
  transportManager: {
36
27
  faultTolerance: FaultTolerance.FATAL_ALL
37
28
  },
@@ -0,0 +1,171 @@
1
+ import { logger } from '@libp2p/logger'
2
+ import type { PeerStore } from '@libp2p/interface-peer-store'
3
+ import type { ConnectionManager } from '@libp2p/interface-connection-manager'
4
+ import { PeerMap } from '@libp2p/peer-collections'
5
+ import PQueue from 'p-queue'
6
+ import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_INTERVAL, AUTO_DIAL_PRIORITY, MIN_CONNECTIONS } from './constants.js'
7
+ import type { Startable } from '@libp2p/interfaces/startable'
8
+
9
+ const log = logger('libp2p:connection-manager:auto-dial')
10
+
11
+ interface AutoDialInit {
12
+ minConnections?: number
13
+ autoDialConcurrency?: number
14
+ autoDialPriority?: number
15
+ autoDialInterval?: number
16
+ }
17
+
18
+ interface AutoDialComponents {
19
+ connectionManager: ConnectionManager
20
+ peerStore: PeerStore
21
+ }
22
+
23
+ const defaultOptions = {
24
+ minConnections: MIN_CONNECTIONS,
25
+ autoDialConcurrency: AUTO_DIAL_CONCURRENCY,
26
+ autoDialPriority: AUTO_DIAL_PRIORITY,
27
+ autoDialInterval: AUTO_DIAL_INTERVAL
28
+ }
29
+
30
+ export class AutoDial implements Startable {
31
+ private readonly connectionManager: ConnectionManager
32
+ private readonly peerStore: PeerStore
33
+ private readonly queue: PQueue
34
+ private readonly minConnections: number
35
+ private readonly autoDialPriority: number
36
+ private readonly autoDialIntervalMs: number
37
+ private autoDialInterval?: ReturnType<typeof setInterval>
38
+ private started: boolean
39
+
40
+ /**
41
+ * Proactively tries to connect to known peers stored in the PeerStore.
42
+ * It will keep the number of connections below the upper limit and sort
43
+ * the peers to connect based on whether we know their keys and protocols.
44
+ */
45
+ constructor (components: AutoDialComponents, init: AutoDialInit) {
46
+ this.connectionManager = components.connectionManager
47
+ this.peerStore = components.peerStore
48
+ this.minConnections = init.minConnections ?? defaultOptions.minConnections
49
+ this.autoDialPriority = init.autoDialPriority ?? defaultOptions.autoDialPriority
50
+ this.autoDialIntervalMs = init.autoDialInterval ?? defaultOptions.autoDialInterval
51
+ this.started = false
52
+ this.queue = new PQueue({
53
+ concurrency: init.autoDialConcurrency ?? defaultOptions.autoDialConcurrency
54
+ })
55
+ this.queue.addListener('error', (err) => {
56
+ log.error('error during auto-dial', err)
57
+ })
58
+ }
59
+
60
+ isStarted (): boolean {
61
+ return this.started
62
+ }
63
+
64
+ start (): void {
65
+ this.autoDialInterval = setInterval(() => {
66
+ this.autoDial()
67
+ .catch(err => {
68
+ log.error('error while autodialing', err)
69
+ })
70
+ }, this.autoDialIntervalMs)
71
+ this.started = true
72
+ }
73
+
74
+ afterStart (): void {
75
+ this.autoDial()
76
+ .catch(err => {
77
+ log.error('error while autodialing', err)
78
+ })
79
+ }
80
+
81
+ stop (): void {
82
+ // clear the queue
83
+ this.queue.clear()
84
+ clearInterval(this.autoDialInterval)
85
+ this.started = false
86
+ }
87
+
88
+ async autoDial (): Promise<void> {
89
+ const numConnections = this.connectionManager.getConnections().length
90
+
91
+ // Already has enough connections
92
+ if (numConnections >= this.minConnections) {
93
+ log('have enough connections %d/%d', numConnections, this.minConnections)
94
+ return
95
+ }
96
+
97
+ log('not enough connections %d/%d - will dial peers to increase the number of connections', numConnections, this.minConnections)
98
+
99
+ // Sort peers on whether we know protocols or public keys for them
100
+ let peers = await this.peerStore.all()
101
+
102
+ log('loaded %d peers from the peer store', peers.length)
103
+
104
+ // Remove some peers
105
+ peers = peers.filter((peer) => {
106
+ // Remove peers without addresses
107
+ if (peer.addresses.length === 0) {
108
+ return false
109
+ }
110
+
111
+ return true
112
+ })
113
+
114
+ // shuffle the peers
115
+ peers = peers.sort(() => Math.random() > 0.5 ? 1 : -1)
116
+
117
+ // Sort shuffled peers by tag value
118
+ const peerValues = new PeerMap<number>()
119
+ for (const peer of peers) {
120
+ if (peerValues.has(peer.id)) {
121
+ continue
122
+ }
123
+
124
+ const tags = await this.peerStore.getTags(peer.id)
125
+
126
+ // sum all tag values
127
+ peerValues.set(peer.id, (tags ?? []).reduce((acc, curr) => {
128
+ return acc + curr.value
129
+ }, 0))
130
+ }
131
+
132
+ // sort by value, highest to lowest
133
+ const sortedPeers = peers.sort((a, b) => {
134
+ const peerAValue = peerValues.get(a.id) ?? 0
135
+ const peerBValue = peerValues.get(b.id) ?? 0
136
+
137
+ if (peerAValue > peerBValue) {
138
+ return -1
139
+ }
140
+
141
+ if (peerAValue < peerBValue) {
142
+ return 1
143
+ }
144
+
145
+ return 0
146
+ })
147
+
148
+ log('selected %d peers to dial', sortedPeers.length)
149
+
150
+ for (const peer of sortedPeers) {
151
+ this.queue.add(async () => {
152
+ const numConnections = this.connectionManager.getConnections().length
153
+
154
+ // Check to see if we still need to auto dial
155
+ if (numConnections >= this.minConnections) {
156
+ log('got enough connections now %d/%d', numConnections, this.minConnections)
157
+ this.queue.clear()
158
+ return
159
+ }
160
+
161
+ log('connecting to a peerStore stored peer %p', peer.id)
162
+ await this.connectionManager.openConnection(peer.id, {
163
+ // @ts-expect-error needs adding to the ConnectionManager interface
164
+ priority: this.autoDialPriority
165
+ })
166
+ }).catch(err => {
167
+ log.error('could not connect to peerStore stored peer', err)
168
+ })
169
+ }
170
+ }
171
+ }
@@ -0,0 +1,137 @@
1
+ import { logger } from '@libp2p/logger'
2
+ import type { ConnectionManager } from '@libp2p/interface-connection-manager'
3
+ import type { PeerStore } from '@libp2p/interface-peer-store'
4
+ import { PeerMap } from '@libp2p/peer-collections'
5
+ import type { Multiaddr } from '@multiformats/multiaddr'
6
+ import { MAX_CONNECTIONS } from './constants.js'
7
+ import { CustomEvent } from '@libp2p/interfaces/events'
8
+
9
+ const log = logger('libp2p:connection-manager:connection-pruner')
10
+
11
+ interface ConnectionPrunerInit {
12
+ maxConnections?: number
13
+ allow?: Multiaddr[]
14
+ }
15
+
16
+ interface ConnectionPrunerComponents {
17
+ connectionManager: ConnectionManager
18
+ peerStore: PeerStore
19
+ }
20
+
21
+ const defaultOptions = {
22
+ maxConnections: MAX_CONNECTIONS,
23
+ allow: []
24
+ }
25
+
26
+ /**
27
+ * If we go over the max connections limit, choose some connections to close
28
+ */
29
+ export class ConnectionPruner {
30
+ private readonly maxConnections: number
31
+ private readonly connectionManager: ConnectionManager
32
+ private readonly peerStore: PeerStore
33
+ private readonly allow: Multiaddr[]
34
+
35
+ constructor (components: ConnectionPrunerComponents, init: ConnectionPrunerInit = {}) {
36
+ this.maxConnections = init.maxConnections ?? defaultOptions.maxConnections
37
+ this.allow = init.allow ?? defaultOptions.allow
38
+ this.connectionManager = components.connectionManager
39
+ this.peerStore = components.peerStore
40
+ }
41
+
42
+ /**
43
+ * If we have more connections than our maximum, select some excess connections
44
+ * to prune based on peer value
45
+ */
46
+ async maybePruneConnections (): Promise<void> {
47
+ const connections = this.connectionManager.getConnections()
48
+ const numConnections = connections.length
49
+ const toPrune = Math.max(numConnections - this.maxConnections, 0)
50
+
51
+ log.trace('checking max connections limit %d/%d', numConnections, this.maxConnections)
52
+ if (numConnections <= this.maxConnections) {
53
+ return
54
+ }
55
+
56
+ log('max connections limit exceeded %d/%d, pruning %d connection(s)', numConnections, this.maxConnections, toPrune)
57
+ const peerValues = new PeerMap<number>()
58
+
59
+ // work out peer values
60
+ for (const connection of connections) {
61
+ const remotePeer = connection.remotePeer
62
+
63
+ if (peerValues.has(remotePeer)) {
64
+ continue
65
+ }
66
+
67
+ const tags = await this.peerStore.getTags(remotePeer)
68
+
69
+ // sum all tag values
70
+ peerValues.set(remotePeer, tags.reduce((acc, curr) => {
71
+ return acc + curr.value
72
+ }, 0))
73
+ }
74
+
75
+ // sort by value, lowest to highest
76
+ const sortedConnections = connections.sort((a, b) => {
77
+ const peerAValue = peerValues.get(a.remotePeer) ?? 0
78
+ const peerBValue = peerValues.get(b.remotePeer) ?? 0
79
+
80
+ if (peerAValue > peerBValue) {
81
+ return 1
82
+ }
83
+
84
+ if (peerAValue < peerBValue) {
85
+ return -1
86
+ }
87
+
88
+ // if the peers have an equal tag value then we want to close short-lived connections first
89
+ const connectionALifespan = a.stat.timeline.open
90
+ const connectionBLifespan = b.stat.timeline.open
91
+
92
+ if (connectionALifespan < connectionBLifespan) {
93
+ return 1
94
+ }
95
+
96
+ if (connectionALifespan > connectionBLifespan) {
97
+ return -1
98
+ }
99
+
100
+ return 0
101
+ })
102
+
103
+ // close some connections
104
+ const toClose = []
105
+
106
+ for (const connection of sortedConnections) {
107
+ log('too many connections open - closing a connection to %p', connection.remotePeer)
108
+ // check allow list
109
+ const connectionInAllowList = this.allow.some((ma) => {
110
+ return connection.remoteAddr.toString().startsWith(ma.toString())
111
+ })
112
+
113
+ // Connections in the allow list should be excluded from pruning
114
+ if (!connectionInAllowList) {
115
+ toClose.push(connection)
116
+ }
117
+
118
+ if (toClose.length === toPrune) {
119
+ break
120
+ }
121
+ }
122
+
123
+ // close connections
124
+ await Promise.all(
125
+ toClose.map(async connection => {
126
+ try {
127
+ await connection.close()
128
+ } catch (err) {
129
+ log.error(err)
130
+ }
131
+ })
132
+ )
133
+
134
+ // despatch prune event
135
+ this.connectionManager.dispatchEvent(new CustomEvent('peer:prune', { detail: toClose.map(conn => conn.remotePeer) }))
136
+ }
137
+ }
@@ -0,0 +1,60 @@
1
+
2
+ /**
3
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#dialTimeout
4
+ */
5
+ export const DIAL_TIMEOUT = 30e3
6
+
7
+ /**
8
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#inboundUpgradeTimeout
9
+ */
10
+ export const INBOUND_UPGRADE_TIMEOUT = 30e3
11
+
12
+ /**
13
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#maxParallelDials
14
+ */
15
+ export const MAX_PARALLEL_DIALS = 100
16
+
17
+ /**
18
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#maxPeerAddrsToDial
19
+ */
20
+ export const MAX_PEER_ADDRS_TO_DIAL = 25
21
+
22
+ /**
23
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#maxParallelDialsPerPeer
24
+ */
25
+ export const MAX_PARALLEL_DIALS_PER_PEER = 10
26
+
27
+ /**
28
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#minConnections
29
+ */
30
+ export const MIN_CONNECTIONS = 50
31
+
32
+ /**
33
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#maxConnections
34
+ */
35
+ export const MAX_CONNECTIONS = 300
36
+
37
+ /**
38
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#autoDialInterval
39
+ */
40
+ export const AUTO_DIAL_INTERVAL = 5000
41
+
42
+ /**
43
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#autoDialConcurrency
44
+ */
45
+ export const AUTO_DIAL_CONCURRENCY = 25
46
+
47
+ /**
48
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#autoDialPriority
49
+ */
50
+ export const AUTO_DIAL_PRIORITY = 0
51
+
52
+ /**
53
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#inboundConnectionThreshold
54
+ */
55
+ export const INBOUND_CONNECTION_THRESHOLD = 5
56
+
57
+ /**
58
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#maxIncomingPendingConnections
59
+ */
60
+ export const MAX_INCOMING_PENDING_CONNECTIONS = 10