libp2p 0.44.0 → 0.45.0-752db6d6

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 (188) hide show
  1. package/dist/index.min.js +30 -30
  2. package/dist/src/address-manager/index.d.ts +8 -4
  3. package/dist/src/address-manager/index.d.ts.map +1 -1
  4. package/dist/src/address-manager/index.js +37 -6
  5. package/dist/src/address-manager/index.js.map +1 -1
  6. package/dist/src/address-manager/utils.d.ts +2 -0
  7. package/dist/src/address-manager/utils.d.ts.map +1 -0
  8. package/dist/src/address-manager/utils.js +12 -0
  9. package/dist/src/address-manager/utils.js.map +1 -0
  10. package/dist/src/autonat/constants.d.ts +16 -2
  11. package/dist/src/autonat/constants.d.ts.map +1 -1
  12. package/dist/src/autonat/constants.js +16 -2
  13. package/dist/src/autonat/constants.js.map +1 -1
  14. package/dist/src/autonat/index.d.ts +12 -33
  15. package/dist/src/autonat/index.d.ts.map +1 -1
  16. package/dist/src/autonat/index.js +36 -30
  17. package/dist/src/autonat/index.js.map +1 -1
  18. package/dist/src/circuit-relay/server/advert-service.d.ts.map +1 -1
  19. package/dist/src/circuit-relay/server/advert-service.js +2 -2
  20. package/dist/src/circuit-relay/server/advert-service.js.map +1 -1
  21. package/dist/src/circuit-relay/server/index.d.ts.map +1 -1
  22. package/dist/src/circuit-relay/server/index.js +10 -3
  23. package/dist/src/circuit-relay/server/index.js.map +1 -1
  24. package/dist/src/circuit-relay/transport/discovery.d.ts.map +1 -1
  25. package/dist/src/circuit-relay/transport/discovery.js +4 -2
  26. package/dist/src/circuit-relay/transport/discovery.js.map +1 -1
  27. package/dist/src/circuit-relay/transport/index.d.ts +3 -0
  28. package/dist/src/circuit-relay/transport/index.d.ts.map +1 -1
  29. package/dist/src/circuit-relay/transport/index.js +6 -4
  30. package/dist/src/circuit-relay/transport/index.js.map +1 -1
  31. package/dist/src/circuit-relay/transport/listener.d.ts.map +1 -1
  32. package/dist/src/circuit-relay/transport/listener.js +30 -26
  33. package/dist/src/circuit-relay/transport/listener.js.map +1 -1
  34. package/dist/src/circuit-relay/transport/reservation-store.d.ts +5 -4
  35. package/dist/src/circuit-relay/transport/reservation-store.d.ts.map +1 -1
  36. package/dist/src/circuit-relay/transport/reservation-store.js +37 -30
  37. package/dist/src/circuit-relay/transport/reservation-store.js.map +1 -1
  38. package/dist/src/components.d.ts +6 -63
  39. package/dist/src/components.d.ts.map +1 -1
  40. package/dist/src/components.js +60 -164
  41. package/dist/src/components.js.map +1 -1
  42. package/dist/src/config/connection-gater.browser.d.ts +8 -0
  43. package/dist/src/config/connection-gater.browser.d.ts.map +1 -0
  44. package/dist/src/config/connection-gater.browser.js +27 -0
  45. package/dist/src/config/connection-gater.browser.js.map +1 -0
  46. package/dist/src/config/connection-gater.d.ts +6 -0
  47. package/dist/src/config/connection-gater.d.ts.map +1 -0
  48. package/dist/src/config/connection-gater.js +18 -0
  49. package/dist/src/config/connection-gater.js.map +1 -0
  50. package/dist/src/config.d.ts +2 -1
  51. package/dist/src/config.d.ts.map +1 -1
  52. package/dist/src/config.js +0 -62
  53. package/dist/src/config.js.map +1 -1
  54. package/dist/src/connection-manager/auto-dial.d.ts +3 -0
  55. package/dist/src/connection-manager/auto-dial.d.ts.map +1 -1
  56. package/dist/src/connection-manager/auto-dial.js +36 -13
  57. package/dist/src/connection-manager/auto-dial.js.map +1 -1
  58. package/dist/src/connection-manager/connection-pruner.d.ts +4 -0
  59. package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -1
  60. package/dist/src/connection-manager/connection-pruner.js +23 -8
  61. package/dist/src/connection-manager/connection-pruner.js.map +1 -1
  62. package/dist/src/connection-manager/dial-queue.d.ts +2 -1
  63. package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
  64. package/dist/src/connection-manager/dial-queue.js +36 -14
  65. package/dist/src/connection-manager/dial-queue.js.map +1 -1
  66. package/dist/src/connection-manager/index.d.ts +8 -7
  67. package/dist/src/connection-manager/index.d.ts.map +1 -1
  68. package/dist/src/connection-manager/index.js +23 -34
  69. package/dist/src/connection-manager/index.js.map +1 -1
  70. package/dist/src/content-routing/index.d.ts +0 -10
  71. package/dist/src/content-routing/index.d.ts.map +1 -1
  72. package/dist/src/content-routing/index.js +7 -42
  73. package/dist/src/content-routing/index.js.map +1 -1
  74. package/dist/src/content-routing/utils.d.ts.map +1 -1
  75. package/dist/src/content-routing/utils.js +3 -1
  76. package/dist/src/content-routing/utils.js.map +1 -1
  77. package/dist/src/fetch/index.d.ts +13 -35
  78. package/dist/src/fetch/index.d.ts.map +1 -1
  79. package/dist/src/fetch/index.js +7 -9
  80. package/dist/src/fetch/index.js.map +1 -1
  81. package/dist/src/identify/identify.d.ts +53 -0
  82. package/dist/src/identify/identify.d.ts.map +1 -0
  83. package/dist/src/identify/identify.js +407 -0
  84. package/dist/src/identify/identify.js.map +1 -0
  85. package/dist/src/identify/index.d.ts +12 -58
  86. package/dist/src/identify/index.d.ts.map +1 -1
  87. package/dist/src/identify/index.js +5 -388
  88. package/dist/src/identify/index.js.map +1 -1
  89. package/dist/src/index.d.ts +13 -68
  90. package/dist/src/index.d.ts.map +1 -1
  91. package/dist/src/index.js +2 -1
  92. package/dist/src/index.js.map +1 -1
  93. package/dist/src/insecure/index.js.map +1 -1
  94. package/dist/src/libp2p.d.ts +11 -42
  95. package/dist/src/libp2p.d.ts.map +1 -1
  96. package/dist/src/libp2p.js +137 -196
  97. package/dist/src/libp2p.js.map +1 -1
  98. package/dist/src/peer-routing.d.ts +1 -38
  99. package/dist/src/peer-routing.d.ts.map +1 -1
  100. package/dist/src/peer-routing.js +0 -59
  101. package/dist/src/peer-routing.js.map +1 -1
  102. package/dist/src/ping/constants.d.ts +4 -0
  103. package/dist/src/ping/constants.d.ts.map +1 -1
  104. package/dist/src/ping/constants.js +10 -0
  105. package/dist/src/ping/constants.js.map +1 -1
  106. package/dist/src/ping/index.d.ts +10 -27
  107. package/dist/src/ping/index.d.ts.map +1 -1
  108. package/dist/src/ping/index.js +18 -21
  109. package/dist/src/ping/index.js.map +1 -1
  110. package/dist/src/registrar.d.ts +5 -2
  111. package/dist/src/registrar.d.ts.map +1 -1
  112. package/dist/src/registrar.js +27 -25
  113. package/dist/src/registrar.js.map +1 -1
  114. package/dist/src/transport-manager.d.ts +11 -4
  115. package/dist/src/transport-manager.d.ts.map +1 -1
  116. package/dist/src/transport-manager.js +19 -10
  117. package/dist/src/transport-manager.js.map +1 -1
  118. package/dist/src/upgrader.d.ts +15 -10
  119. package/dist/src/upgrader.d.ts.map +1 -1
  120. package/dist/src/upgrader.js +39 -48
  121. package/dist/src/upgrader.js.map +1 -1
  122. package/dist/src/upnp-nat/index.d.ts +42 -0
  123. package/dist/src/upnp-nat/index.d.ts.map +1 -0
  124. package/dist/src/{nat-manager.js → upnp-nat/index.js} +11 -7
  125. package/dist/src/upnp-nat/index.js.map +1 -0
  126. package/dist/src/version.d.ts +1 -1
  127. package/dist/src/version.d.ts.map +1 -1
  128. package/dist/src/version.js +1 -1
  129. package/dist/src/version.js.map +1 -1
  130. package/package.json +61 -45
  131. package/src/address-manager/index.ts +50 -8
  132. package/src/address-manager/utils.ts +14 -0
  133. package/src/autonat/constants.ts +17 -2
  134. package/src/autonat/index.ts +53 -45
  135. package/src/circuit-relay/server/advert-service.ts +2 -2
  136. package/src/circuit-relay/server/index.ts +11 -3
  137. package/src/circuit-relay/transport/discovery.ts +5 -3
  138. package/src/circuit-relay/transport/index.ts +9 -4
  139. package/src/circuit-relay/transport/listener.ts +38 -28
  140. package/src/circuit-relay/transport/reservation-store.ts +34 -20
  141. package/src/components.ts +71 -234
  142. package/src/config/connection-gater.browser.ts +31 -0
  143. package/src/config/connection-gater.ts +19 -0
  144. package/src/config.ts +3 -64
  145. package/src/connection-manager/auto-dial.ts +44 -15
  146. package/src/connection-manager/connection-pruner.ts +28 -8
  147. package/src/connection-manager/dial-queue.ts +41 -21
  148. package/src/connection-manager/index.ts +31 -43
  149. package/src/content-routing/index.ts +7 -55
  150. package/src/content-routing/utils.ts +3 -1
  151. package/src/fetch/index.ts +51 -14
  152. package/src/identify/identify.ts +519 -0
  153. package/src/identify/index.ts +17 -507
  154. package/src/index.ts +14 -77
  155. package/src/insecure/index.ts +4 -4
  156. package/src/libp2p.ts +139 -260
  157. package/src/peer-routing.ts +1 -101
  158. package/src/ping/constants.ts +11 -0
  159. package/src/ping/index.ts +32 -28
  160. package/src/registrar.ts +31 -27
  161. package/src/transport-manager.ts +27 -13
  162. package/src/upgrader.ts +62 -58
  163. package/src/{nat-manager.ts → upnp-nat/index.ts} +16 -17
  164. package/src/version.ts +1 -1
  165. package/dist/src/dht/dht-content-routing.d.ts +0 -17
  166. package/dist/src/dht/dht-content-routing.d.ts.map +0 -1
  167. package/dist/src/dht/dht-content-routing.js +0 -32
  168. package/dist/src/dht/dht-content-routing.js.map +0 -1
  169. package/dist/src/dht/dht-peer-routing.d.ts +0 -15
  170. package/dist/src/dht/dht-peer-routing.d.ts.map +0 -1
  171. package/dist/src/dht/dht-peer-routing.js +0 -26
  172. package/dist/src/dht/dht-peer-routing.js.map +0 -1
  173. package/dist/src/dht/dummy-dht.d.ts +0 -20
  174. package/dist/src/dht/dummy-dht.d.ts.map +0 -1
  175. package/dist/src/dht/dummy-dht.js +0 -46
  176. package/dist/src/dht/dummy-dht.js.map +0 -1
  177. package/dist/src/nat-manager.d.ts +0 -74
  178. package/dist/src/nat-manager.d.ts.map +0 -1
  179. package/dist/src/nat-manager.js.map +0 -1
  180. package/dist/src/peer-record-updater.d.ts +0 -24
  181. package/dist/src/peer-record-updater.d.ts.map +0 -1
  182. package/dist/src/peer-record-updater.js +0 -44
  183. package/dist/src/peer-record-updater.js.map +0 -1
  184. package/dist/typedoc-urls.json +0 -41
  185. package/src/dht/dht-content-routing.ts +0 -44
  186. package/src/dht/dht-peer-routing.ts +0 -36
  187. package/src/dht/dummy-dht.ts +0 -60
  188. package/src/peer-record-updater.ts +0 -65
@@ -0,0 +1,31 @@
1
+ import type { ConnectionGater } from '@libp2p/interface-connection-gater'
2
+ import type { Multiaddr } from '@multiformats/multiaddr'
3
+ import isPrivate from 'private-ip'
4
+
5
+ /**
6
+ * Returns a connection gater that disallows dialling private addresses by
7
+ * default. Browsers are severely limited in their resource usage so don't
8
+ * waste time trying to dial undiallable addresses.
9
+ */
10
+ export function connectionGater (gater: ConnectionGater = {}): ConnectionGater {
11
+ return {
12
+ denyDialPeer: async () => false,
13
+ denyDialMultiaddr: async (multiaddr: Multiaddr) => {
14
+ const tuples = multiaddr.stringTuples()
15
+
16
+ if (tuples[0][0] === 4 || tuples[0][0] === 41) {
17
+ return Boolean(isPrivate(`${tuples[0][1]}`))
18
+ }
19
+
20
+ return false
21
+ },
22
+ denyInboundConnection: async () => false,
23
+ denyOutboundConnection: async () => false,
24
+ denyInboundEncryptedConnection: async () => false,
25
+ denyOutboundEncryptedConnection: async () => false,
26
+ denyInboundUpgradedConnection: async () => false,
27
+ denyOutboundUpgradedConnection: async () => false,
28
+ filterMultiaddrForPeer: async () => true,
29
+ ...gater
30
+ }
31
+ }
@@ -0,0 +1,19 @@
1
+ import type { ConnectionGater } from '@libp2p/interface-connection-gater'
2
+
3
+ /**
4
+ * Returns a default connection gater implementation that allows everything
5
+ */
6
+ export function connectionGater (gater: ConnectionGater = {}): ConnectionGater {
7
+ return {
8
+ denyDialPeer: async () => false,
9
+ denyDialMultiaddr: async () => false,
10
+ denyInboundConnection: async () => false,
11
+ denyOutboundConnection: async () => false,
12
+ denyInboundEncryptedConnection: async () => false,
13
+ denyOutboundEncryptedConnection: async () => false,
14
+ denyInboundUpgradedConnection: async () => false,
15
+ denyOutboundUpgradedConnection: async () => false,
16
+ filterMultiaddrForPeer: async () => true,
17
+ ...gater
18
+ }
19
+ }
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 { AGENT_VERSION } from './identify/consts.js'
4
3
  import { publicAddressesFirst } from '@libp2p/utils/address-sort'
5
4
  import { FaultTolerance } from '@libp2p/interface-transport'
6
5
  import type { Multiaddr } from '@multiformats/multiaddr'
@@ -8,7 +7,7 @@ import type { Libp2pInit } from './index.js'
8
7
  import { codes, messages } from './errors.js'
9
8
  import { CodeError } from '@libp2p/interfaces/errors'
10
9
  import type { RecursivePartial } from '@libp2p/interfaces'
11
- import { isNode, isBrowser, isWebWorker, isElectronMain, isElectronRenderer, isReactNative } from 'wherearewe'
10
+ import type { ServiceMap } from '@libp2p/interface-libp2p'
12
11
 
13
12
  const DefaultConfig: Partial<Libp2pInit> = {
14
13
  addresses: {
@@ -25,62 +24,11 @@ const DefaultConfig: Partial<Libp2pInit> = {
25
24
  },
26
25
  transportManager: {
27
26
  faultTolerance: FaultTolerance.FATAL_ALL
28
- },
29
- peerRouting: {
30
- refreshManager: {
31
- enabled: true,
32
- interval: 6e5,
33
- bootDelay: 10e3
34
- }
35
- },
36
- nat: {
37
- enabled: true,
38
- ttl: 7200,
39
- keepAlive: true
40
- },
41
- identify: {
42
- protocolPrefix: 'ipfs',
43
- host: {
44
- agentVersion: AGENT_VERSION
45
- },
46
- // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L48
47
- timeout: 60000,
48
- maxInboundStreams: 1,
49
- maxOutboundStreams: 1,
50
- maxPushIncomingStreams: 1,
51
- maxPushOutgoingStreams: 1,
52
- maxObservedAddresses: 10
53
- },
54
- ping: {
55
- protocolPrefix: 'ipfs',
56
- // See https://github.com/libp2p/specs/blob/d4b5fb0152a6bb86cfd9ea/ping/ping.md?plain=1#L38-L43
57
- // The dialing peer MUST NOT keep more than one outbound stream for the ping protocol per peer.
58
- // The listening peer SHOULD accept at most two streams per peer since cross-stream behavior is
59
- // non-linear and stream writes occur asynchronously. The listening peer may perceive the
60
- // dialing peer closing and opening the wrong streams (for instance, closing stream B and
61
- // opening stream A even though the dialing peer is opening stream B and closing stream A).
62
- maxInboundStreams: 2,
63
- maxOutboundStreams: 1,
64
- timeout: 10000
65
- },
66
- fetch: {
67
- protocolPrefix: 'libp2p',
68
- maxInboundStreams: 1,
69
- maxOutboundStreams: 1,
70
- timeout: 10000
71
- },
72
- autonat: {
73
- protocolPrefix: 'libp2p',
74
- maxInboundStreams: 1,
75
- maxOutboundStreams: 1,
76
- timeout: 30000,
77
- startupDelay: 5000,
78
- refreshInterval: 60000
79
27
  }
80
28
  }
81
29
 
82
- export function validateConfig (opts: RecursivePartial<Libp2pInit>): Libp2pInit {
83
- const resultingOptions: Libp2pInit = mergeOptions(DefaultConfig, opts)
30
+ export function validateConfig <T extends ServiceMap = {}> (opts: RecursivePartial<Libp2pInit<T>>): Libp2pInit<T> {
31
+ const resultingOptions: Libp2pInit<T> = mergeOptions(DefaultConfig, opts)
84
32
 
85
33
  if (resultingOptions.transports == null || resultingOptions.transports.length < 1) {
86
34
  throw new CodeError(messages.ERR_TRANSPORTS_REQUIRED, codes.ERR_TRANSPORTS_REQUIRED)
@@ -94,14 +42,5 @@ export function validateConfig (opts: RecursivePartial<Libp2pInit>): Libp2pInit
94
42
  throw new CodeError(messages.ERR_PROTECTOR_REQUIRED, codes.ERR_PROTECTOR_REQUIRED)
95
43
  }
96
44
 
97
- // Append user agent version to default AGENT_VERSION depending on the environment
98
- if (resultingOptions.identify.host.agentVersion === AGENT_VERSION) {
99
- if (isNode || isElectronMain) {
100
- resultingOptions.identify.host.agentVersion += ` UserAgent=${globalThis.process.version}`
101
- } else if (isBrowser || isWebWorker || isElectronRenderer || isReactNative) {
102
- resultingOptions.identify.host.agentVersion += ` UserAgent=${globalThis.navigator.userAgent}`
103
- }
104
- }
105
-
106
45
  return resultingOptions
107
46
  }
@@ -1,10 +1,12 @@
1
1
  import { logger } from '@libp2p/logger'
2
2
  import type { PeerStore } from '@libp2p/interface-peer-store'
3
3
  import type { ConnectionManager } from '@libp2p/interface-connection-manager'
4
- import { PeerMap } from '@libp2p/peer-collections'
4
+ import { PeerMap, PeerSet } from '@libp2p/peer-collections'
5
5
  import PQueue from 'p-queue'
6
6
  import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_INTERVAL, AUTO_DIAL_PRIORITY, MIN_CONNECTIONS } from './constants.js'
7
7
  import type { Startable } from '@libp2p/interfaces/startable'
8
+ import type { EventEmitter } from '@libp2p/interfaces/events'
9
+ import type { Libp2pEvents } from '@libp2p/interface-libp2p'
8
10
 
9
11
  const log = logger('libp2p:connection-manager:auto-dial')
10
12
 
@@ -18,6 +20,7 @@ interface AutoDialInit {
18
20
  interface AutoDialComponents {
19
21
  connectionManager: ConnectionManager
20
22
  peerStore: PeerStore
23
+ events: EventEmitter<Libp2pEvents>
21
24
  }
22
25
 
23
26
  const defaultOptions = {
@@ -55,6 +58,14 @@ export class AutoDial implements Startable {
55
58
  this.queue.addListener('error', (err) => {
56
59
  log.error('error during auto-dial', err)
57
60
  })
61
+
62
+ // check the min connection limit whenever a peer disconnects
63
+ components.events.addEventListener('connection:close', () => {
64
+ this.autoDial()
65
+ .catch(err => {
66
+ log.error(err)
67
+ })
68
+ })
58
69
  }
59
70
 
60
71
  isStarted (): boolean {
@@ -86,7 +97,18 @@ export class AutoDial implements Startable {
86
97
  }
87
98
 
88
99
  async autoDial (): Promise<void> {
89
- const numConnections = this.connectionManager.getConnections().length
100
+ if (!this.started) {
101
+ return
102
+ }
103
+
104
+ const connections = this.connectionManager.getConnectionsMap()
105
+ const numConnections = connections.size
106
+ const dialQueue = new PeerSet(
107
+ // @ts-expect-error boolean filter removes falsy peer IDs
108
+ this.connectionManager.getDialQueue()
109
+ .map(queue => queue.peerId)
110
+ .filter(Boolean)
111
+ )
90
112
 
91
113
  // Already has enough connections
92
114
  if (numConnections >= this.minConnections) {
@@ -97,40 +119,47 @@ export class AutoDial implements Startable {
97
119
  log('not enough connections %d/%d - will dial peers to increase the number of connections', numConnections, this.minConnections)
98
120
 
99
121
  // 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)
122
+ const peers = await this.peerStore.all()
103
123
 
104
124
  // Remove some peers
105
- peers = peers.filter((peer) => {
125
+ const filteredPeers = peers.filter((peer) => {
106
126
  // Remove peers without addresses
107
127
  if (peer.addresses.length === 0) {
108
128
  return false
109
129
  }
110
130
 
131
+ // remove peers we are already connected to
132
+ if (connections.has(peer.id)) {
133
+ return false
134
+ }
135
+
136
+ // remove peers we are already dialling
137
+ if (dialQueue.has(peer.id)) {
138
+ return false
139
+ }
140
+
111
141
  return true
112
142
  })
113
143
 
114
- // shuffle the peers
115
- peers = peers.sort(() => Math.random() > 0.5 ? 1 : -1)
144
+ // shuffle the peers - this is so peers with the same tag values will be
145
+ // dialled in a different order each time
146
+ const shuffledPeers = filteredPeers.sort(() => Math.random() > 0.5 ? 1 : -1)
116
147
 
117
148
  // Sort shuffled peers by tag value
118
149
  const peerValues = new PeerMap<number>()
119
- for (const peer of peers) {
150
+ for (const peer of shuffledPeers) {
120
151
  if (peerValues.has(peer.id)) {
121
152
  continue
122
153
  }
123
154
 
124
- const tags = await this.peerStore.getTags(peer.id)
125
-
126
155
  // sum all tag values
127
- peerValues.set(peer.id, (tags ?? []).reduce((acc, curr) => {
156
+ peerValues.set(peer.id, [...peer.tags.values()].reduce((acc, curr) => {
128
157
  return acc + curr.value
129
158
  }, 0))
130
159
  }
131
160
 
132
161
  // sort by value, highest to lowest
133
- const sortedPeers = peers.sort((a, b) => {
162
+ const sortedPeers = shuffledPeers.sort((a, b) => {
134
163
  const peerAValue = peerValues.get(a.id) ?? 0
135
164
  const peerBValue = peerValues.get(b.id) ?? 0
136
165
 
@@ -145,11 +174,11 @@ export class AutoDial implements Startable {
145
174
  return 0
146
175
  })
147
176
 
148
- log('selected %d peers to dial', sortedPeers.length)
177
+ log('selected %d/%d peers to dial', sortedPeers.length, peers.length)
149
178
 
150
179
  for (const peer of sortedPeers) {
151
180
  this.queue.add(async () => {
152
- const numConnections = this.connectionManager.getConnections().length
181
+ const numConnections = this.connectionManager.getConnectionsMap().size
153
182
 
154
183
  // Check to see if we still need to auto dial
155
184
  if (numConnections >= this.minConnections) {
@@ -4,7 +4,8 @@ import type { PeerStore } from '@libp2p/interface-peer-store'
4
4
  import { PeerMap } from '@libp2p/peer-collections'
5
5
  import type { Multiaddr } from '@multiformats/multiaddr'
6
6
  import { MAX_CONNECTIONS } from './constants.js'
7
- import { CustomEvent } from '@libp2p/interfaces/events'
7
+ import type { EventEmitter } from '@libp2p/interfaces/events'
8
+ import type { Libp2pEvents } from '@libp2p/interface-libp2p'
8
9
 
9
10
  const log = logger('libp2p:connection-manager:connection-pruner')
10
11
 
@@ -16,6 +17,7 @@ interface ConnectionPrunerInit {
16
17
  interface ConnectionPrunerComponents {
17
18
  connectionManager: ConnectionManager
18
19
  peerStore: PeerStore
20
+ events: EventEmitter<Libp2pEvents>
19
21
  }
20
22
 
21
23
  const defaultOptions = {
@@ -31,12 +33,22 @@ export class ConnectionPruner {
31
33
  private readonly connectionManager: ConnectionManager
32
34
  private readonly peerStore: PeerStore
33
35
  private readonly allow: Multiaddr[]
36
+ private readonly events: EventEmitter<Libp2pEvents>
34
37
 
35
38
  constructor (components: ConnectionPrunerComponents, init: ConnectionPrunerInit = {}) {
36
39
  this.maxConnections = init.maxConnections ?? defaultOptions.maxConnections
37
40
  this.allow = init.allow ?? defaultOptions.allow
38
41
  this.connectionManager = components.connectionManager
39
42
  this.peerStore = components.peerStore
43
+ this.events = components.events
44
+
45
+ // check the max connection limit whenever a peer connects
46
+ components.events.addEventListener('connection:open', () => {
47
+ this.maybePruneConnections()
48
+ .catch(err => {
49
+ log.error(err)
50
+ })
51
+ })
40
52
  }
41
53
 
42
54
  /**
@@ -48,7 +60,7 @@ export class ConnectionPruner {
48
60
  const numConnections = connections.length
49
61
  const toPrune = Math.max(numConnections - this.maxConnections, 0)
50
62
 
51
- log.trace('checking max connections limit %d/%d', numConnections, this.maxConnections)
63
+ log('checking max connections limit %d/%d', numConnections, this.maxConnections)
52
64
  if (numConnections <= this.maxConnections) {
53
65
  return
54
66
  }
@@ -64,12 +76,20 @@ export class ConnectionPruner {
64
76
  continue
65
77
  }
66
78
 
67
- const tags = await this.peerStore.getTags(remotePeer)
79
+ peerValues.set(remotePeer, 0)
68
80
 
69
- // sum all tag values
70
- peerValues.set(remotePeer, tags.reduce((acc, curr) => {
71
- return acc + curr.value
72
- }, 0))
81
+ try {
82
+ const peer = await this.peerStore.get(remotePeer)
83
+
84
+ // sum all tag values
85
+ peerValues.set(remotePeer, [...peer.tags.values()].reduce((acc, curr) => {
86
+ return acc + curr.value
87
+ }, 0))
88
+ } catch (err: any) {
89
+ if (err.code !== 'ERR_NOT_FOUND') {
90
+ log.error('error loading peer tags', err)
91
+ }
92
+ }
73
93
  }
74
94
 
75
95
  // sort by value, lowest to highest
@@ -132,6 +152,6 @@ export class ConnectionPruner {
132
152
  )
133
153
 
134
154
  // despatch prune event
135
- this.connectionManager.dispatchEvent(new CustomEvent('peer:prune', { detail: toClose.map(conn => conn.remotePeer) }))
155
+ this.events.safeDispatchEvent('connection:prune', { detail: toClose })
136
156
  }
137
157
  }
@@ -1,7 +1,6 @@
1
1
  import { logger } from '@libp2p/logger'
2
2
  import { AbortError, CodeError } from '@libp2p/interfaces/errors'
3
3
  import { Multiaddr, Resolver, resolvers } from '@multiformats/multiaddr'
4
- import { TimeoutController } from 'timeout-abort-controller'
5
4
  import { publicAddressesFirst } from '@libp2p/utils/address-sort'
6
5
  import { codes } from '../errors.js'
7
6
  import {
@@ -14,7 +13,7 @@ import type { Connection } from '@libp2p/interface-connection'
14
13
  import type { AbortOptions } from '@libp2p/interfaces'
15
14
  import type { PeerId } from '@libp2p/interface-peer-id'
16
15
  import { getPeerAddress } from '../get-peer.js'
17
- import type { Address, AddressSorter, PeerStore } from '@libp2p/interface-peer-store'
16
+ import type { Address, PeerStore } from '@libp2p/interface-peer-store'
18
17
  import type { Metric, Metrics } from '@libp2p/interface-metrics'
19
18
  import type { TransportManager } from '@libp2p/interface-transport'
20
19
  import type { ConnectionGater } from '@libp2p/interface-connection-gater'
@@ -22,7 +21,9 @@ import PQueue from 'p-queue'
22
21
  import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers'
23
22
  import { combineSignals, resolveMultiaddrs } from './utils.js'
24
23
  import pDefer from 'p-defer'
25
- import type { ClearableSignal } from 'any-signal'
24
+ import { ClearableSignal, anySignal } from 'any-signal'
25
+ import type { AddressSorter } from '@libp2p/interface-libp2p'
26
+ import { setMaxListeners } from 'events'
26
27
 
27
28
  const log = logger('libp2p:connection-manager:dial-queue')
28
29
 
@@ -100,6 +101,11 @@ export class DialQueue {
100
101
  this.transportManager = components.transportManager
101
102
  this.shutDownController = new AbortController()
102
103
 
104
+ try {
105
+ // This emitter gets listened to a lot
106
+ setMaxListeners?.(Infinity, this.shutDownController.signal)
107
+ } catch {}
108
+
103
109
  this.pendingDialCount = components.metrics?.registerMetric('libp2p_dialler_pending_dials')
104
110
  this.inProgressDialCount = components.metrics?.registerMetric('libp2p_dialler_in_progress_dials')
105
111
  this.pendingDials = []
@@ -175,7 +181,7 @@ export class DialQueue {
175
181
 
176
182
  // create abort conditions - need to do this before `calculateMultiaddrs` as we may be about to
177
183
  // resolve a dns addr which can time out
178
- const { timeoutController, signal } = this.createDialAbortControllers(options.signal)
184
+ const signal = this.createDialAbortControllers(options.signal)
179
185
  let addrsToDial: Address[]
180
186
 
181
187
  try {
@@ -186,7 +192,6 @@ export class DialQueue {
186
192
  })
187
193
  } catch (err) {
188
194
  signal.clear()
189
- timeoutController.clear()
190
195
  throw err
191
196
  }
192
197
 
@@ -209,7 +214,6 @@ export class DialQueue {
209
214
  if (existingDial != null) {
210
215
  log('joining existing dial target for %p', peerId)
211
216
  signal.clear()
212
- timeoutController.clear()
213
217
  return await existingDial.promise
214
218
  }
215
219
 
@@ -232,13 +236,12 @@ export class DialQueue {
232
236
 
233
237
  // clean up abort signals/controllers
234
238
  signal.clear()
235
- timeoutController.clear()
236
239
  })
237
240
  .catch(err => {
238
- log.error('dial failed to %s', addrsToDial.map(({ multiaddr }) => multiaddr.toString()).join(', '), err)
241
+ log.error('dial failed to %s', pendingDial.multiaddrs.map(ma => ma.toString()).join(', '), err)
239
242
 
240
243
  // Error is a timeout
241
- if (timeoutController.signal.aborted) {
244
+ if (signal.aborted) {
242
245
  const error = new CodeError(err.message, codes.ERR_TIMEOUT)
243
246
  throw error
244
247
  }
@@ -252,18 +255,21 @@ export class DialQueue {
252
255
  return await pendingDial.promise
253
256
  }
254
257
 
255
- private createDialAbortControllers (userSignal?: AbortSignal): { timeoutController: TimeoutController, signal: ClearableSignal } {
256
- // ensure we throw if the dial takes longer than the dial timeout
257
- const timeoutController = new TimeoutController(this.dialTimeout)
258
-
258
+ private createDialAbortControllers (userSignal?: AbortSignal): ClearableSignal {
259
259
  // let any signal abort the dial
260
- const signal = combineSignals(
261
- timeoutController.signal,
262
- this.shutDownController.signal,
263
- userSignal
260
+ const signal = anySignal(
261
+ [AbortSignal.timeout(this.dialTimeout),
262
+ this.shutDownController.signal,
263
+ userSignal
264
+ ]
264
265
  )
265
266
 
266
- return { timeoutController, signal }
267
+ try {
268
+ // This emitter gets listened to a lot
269
+ setMaxListeners?.(Infinity, signal)
270
+ } catch {}
271
+
272
+ return signal
267
273
  }
268
274
 
269
275
  private async calculateMultiaddrs (peerId?: PeerId, addrs: Address[] = [], options: DialOptions = {}): Promise<Address[]> {
@@ -280,8 +286,15 @@ export class DialQueue {
280
286
  // if just a peer id was passed, load available multiaddrs for this peer from the address book
281
287
  if (addrs.length === 0) {
282
288
  log('loading multiaddrs for %p', peerId)
283
- addrs.push(...(await this.peerStore.addressBook.get(peerId)))
284
- log('loaded multiaddrs for %p', peerId, addrs.map(({ multiaddr }) => multiaddr.toString()))
289
+ try {
290
+ const peer = await this.peerStore.get(peerId)
291
+ addrs.push(...peer.addresses)
292
+ log('loaded multiaddrs for %p', peerId, addrs.map(({ multiaddr }) => multiaddr.toString()))
293
+ } catch (err: any) {
294
+ if (err.code !== codes.ERR_NOT_FOUND) {
295
+ throw err
296
+ }
297
+ }
285
298
  }
286
299
  }
287
300
 
@@ -371,7 +384,14 @@ export class DialQueue {
371
384
  gatedAdrs.push(addr)
372
385
  }
373
386
 
374
- return gatedAdrs.sort(this.addressSorter)
387
+ const sortedGatedAddrs = gatedAdrs.sort(this.addressSorter)
388
+
389
+ // make sure we actually have some addresses to dial
390
+ if (sortedGatedAddrs.length === 0) {
391
+ throw new CodeError('The connection gater denied all addresses in the dial request', codes.ERR_NO_VALID_ADDRESSES)
392
+ }
393
+
394
+ return sortedGatedAddrs
375
395
  }
376
396
 
377
397
  private async performDial (pendingDial: PendingDial, options: DialOptions = {}): Promise<Connection> {