libp2p 0.37.3 → 0.38.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 (189) hide show
  1. package/README.md +1 -2
  2. package/dist/src/address-manager/index.d.ts +2 -2
  3. package/dist/src/address-manager/index.d.ts.map +1 -1
  4. package/dist/src/circuit/auto-relay.d.ts +4 -4
  5. package/dist/src/circuit/auto-relay.d.ts.map +1 -1
  6. package/dist/src/circuit/circuit/hop.d.ts +7 -5
  7. package/dist/src/circuit/circuit/hop.d.ts.map +1 -1
  8. package/dist/src/circuit/circuit/hop.js +8 -4
  9. package/dist/src/circuit/circuit/hop.js.map +1 -1
  10. package/dist/src/circuit/circuit/stop.d.ts +6 -4
  11. package/dist/src/circuit/circuit/stop.d.ts.map +1 -1
  12. package/dist/src/circuit/circuit/stop.js +4 -2
  13. package/dist/src/circuit/circuit/stop.js.map +1 -1
  14. package/dist/src/circuit/circuit/stream-handler.d.ts +3 -2
  15. package/dist/src/circuit/circuit/stream-handler.d.ts.map +1 -1
  16. package/dist/src/circuit/circuit/stream-handler.js +2 -2
  17. package/dist/src/circuit/circuit/stream-handler.js.map +1 -1
  18. package/dist/src/circuit/index.d.ts +4 -12
  19. package/dist/src/circuit/index.d.ts.map +1 -1
  20. package/dist/src/circuit/index.js.map +1 -1
  21. package/dist/src/circuit/listener.d.ts +3 -3
  22. package/dist/src/circuit/listener.d.ts.map +1 -1
  23. package/dist/src/circuit/pb/index.d.ts +5 -4
  24. package/dist/src/circuit/pb/index.d.ts.map +1 -1
  25. package/dist/src/circuit/pb/index.js +107 -11
  26. package/dist/src/circuit/pb/index.js.map +1 -1
  27. package/dist/src/circuit/transport.d.ts +8 -5
  28. package/dist/src/circuit/transport.d.ts.map +1 -1
  29. package/dist/src/circuit/transport.js +81 -59
  30. package/dist/src/circuit/transport.js.map +1 -1
  31. package/dist/src/config.d.ts.map +1 -1
  32. package/dist/src/config.js +27 -4
  33. package/dist/src/config.js.map +1 -1
  34. package/dist/src/connection-manager/auto-dialler.d.ts +1 -1
  35. package/dist/src/connection-manager/auto-dialler.d.ts.map +1 -1
  36. package/dist/src/connection-manager/dialer/auto-dialer.d.ts +2 -2
  37. package/dist/src/connection-manager/dialer/auto-dialer.d.ts.map +1 -1
  38. package/dist/src/connection-manager/dialer/auto-dialer.js +6 -0
  39. package/dist/src/connection-manager/dialer/auto-dialer.js.map +1 -1
  40. package/dist/src/connection-manager/dialer/dial-request.d.ts +1 -1
  41. package/dist/src/connection-manager/dialer/dial-request.d.ts.map +1 -1
  42. package/dist/src/connection-manager/dialer/index.d.ts +9 -9
  43. package/dist/src/connection-manager/dialer/index.d.ts.map +1 -1
  44. package/dist/src/connection-manager/dialer/index.js +11 -11
  45. package/dist/src/connection-manager/dialer/index.js.map +1 -1
  46. package/dist/src/connection-manager/index.d.ts +20 -16
  47. package/dist/src/connection-manager/index.d.ts.map +1 -1
  48. package/dist/src/connection-manager/index.js +185 -65
  49. package/dist/src/connection-manager/index.js.map +1 -1
  50. package/dist/src/constants.d.ts +4 -0
  51. package/dist/src/constants.d.ts.map +1 -1
  52. package/dist/src/constants.js +4 -0
  53. package/dist/src/constants.js.map +1 -1
  54. package/dist/src/content-routing/index.d.ts +4 -4
  55. package/dist/src/content-routing/index.d.ts.map +1 -1
  56. package/dist/src/content-routing/utils.d.ts +2 -2
  57. package/dist/src/content-routing/utils.d.ts.map +1 -1
  58. package/dist/src/dht/dht-content-routing.d.ts +3 -3
  59. package/dist/src/dht/dht-content-routing.d.ts.map +1 -1
  60. package/dist/src/dht/dht-peer-routing.d.ts +5 -5
  61. package/dist/src/dht/dht-peer-routing.d.ts.map +1 -1
  62. package/dist/src/dht/dummy-dht.d.ts +3 -3
  63. package/dist/src/dht/dummy-dht.d.ts.map +1 -1
  64. package/dist/src/dht/dummy-dht.js +1 -1
  65. package/dist/src/dht/dummy-dht.js.map +1 -1
  66. package/dist/src/errors.d.ts +4 -1
  67. package/dist/src/errors.d.ts.map +1 -1
  68. package/dist/src/errors.js +3 -0
  69. package/dist/src/errors.js.map +1 -1
  70. package/dist/src/fetch/index.d.ts +11 -4
  71. package/dist/src/fetch/index.d.ts.map +1 -1
  72. package/dist/src/fetch/index.js +82 -41
  73. package/dist/src/fetch/index.js.map +1 -1
  74. package/dist/src/fetch/pb/proto.d.ts +4 -3
  75. package/dist/src/fetch/pb/proto.d.ts.map +1 -1
  76. package/dist/src/fetch/pb/proto.js +88 -8
  77. package/dist/src/fetch/pb/proto.js.map +1 -1
  78. package/dist/src/get-peer.d.ts +2 -2
  79. package/dist/src/get-peer.d.ts.map +1 -1
  80. package/dist/src/get-peer.js +1 -1
  81. package/dist/src/get-peer.js.map +1 -1
  82. package/dist/src/identify/index.d.ts +8 -8
  83. package/dist/src/identify/index.d.ts.map +1 -1
  84. package/dist/src/identify/index.js +49 -34
  85. package/dist/src/identify/index.js.map +1 -1
  86. package/dist/src/identify/pb/message.d.ts +2 -1
  87. package/dist/src/identify/pb/message.d.ts.map +1 -1
  88. package/dist/src/identify/pb/message.js +94 -10
  89. package/dist/src/identify/pb/message.js.map +1 -1
  90. package/dist/src/index.d.ts +18 -17
  91. package/dist/src/index.d.ts.map +1 -1
  92. package/dist/src/index.js.map +1 -1
  93. package/dist/src/insecure/index.d.ts +2 -2
  94. package/dist/src/insecure/index.d.ts.map +1 -1
  95. package/dist/src/insecure/index.js +8 -4
  96. package/dist/src/insecure/index.js.map +1 -1
  97. package/dist/src/insecure/pb/proto.d.ts +4 -3
  98. package/dist/src/insecure/pb/proto.d.ts.map +1 -1
  99. package/dist/src/insecure/pb/proto.js +89 -9
  100. package/dist/src/insecure/pb/proto.js.map +1 -1
  101. package/dist/src/keychain/index.d.ts +2 -2
  102. package/dist/src/keychain/index.d.ts.map +1 -1
  103. package/dist/src/libp2p.d.ts +14 -14
  104. package/dist/src/libp2p.d.ts.map +1 -1
  105. package/dist/src/libp2p.js +17 -17
  106. package/dist/src/libp2p.js.map +1 -1
  107. package/dist/src/metrics/index.d.ts +4 -5
  108. package/dist/src/metrics/index.d.ts.map +1 -1
  109. package/dist/src/metrics/index.js +9 -6
  110. package/dist/src/metrics/index.js.map +1 -1
  111. package/dist/src/metrics/moving-average.d.ts +1 -1
  112. package/dist/src/metrics/moving-average.d.ts.map +1 -1
  113. package/dist/src/metrics/stats.d.ts +1 -1
  114. package/dist/src/metrics/stats.d.ts.map +1 -1
  115. package/dist/src/nat-manager.d.ts +1 -1
  116. package/dist/src/nat-manager.d.ts.map +1 -1
  117. package/dist/src/peer-record-updater.d.ts +1 -1
  118. package/dist/src/peer-record-updater.d.ts.map +1 -1
  119. package/dist/src/peer-routing.d.ts +4 -4
  120. package/dist/src/peer-routing.d.ts.map +1 -1
  121. package/dist/src/ping/index.d.ts +10 -3
  122. package/dist/src/ping/index.d.ts.map +1 -1
  123. package/dist/src/ping/index.js +32 -9
  124. package/dist/src/ping/index.js.map +1 -1
  125. package/dist/src/pnet/index.d.ts +1 -2
  126. package/dist/src/pnet/index.d.ts.map +1 -1
  127. package/dist/src/pnet/index.js +2 -1
  128. package/dist/src/pnet/index.js.map +1 -1
  129. package/dist/src/pubsub/dummy-pubsub.d.ts +2 -2
  130. package/dist/src/pubsub/dummy-pubsub.d.ts.map +1 -1
  131. package/dist/src/registrar.d.ts +10 -8
  132. package/dist/src/registrar.d.ts.map +1 -1
  133. package/dist/src/registrar.js +63 -44
  134. package/dist/src/registrar.js.map +1 -1
  135. package/dist/src/transport-manager.d.ts +3 -3
  136. package/dist/src/transport-manager.d.ts.map +1 -1
  137. package/dist/src/upgrader.d.ts +12 -6
  138. package/dist/src/upgrader.d.ts.map +1 -1
  139. package/dist/src/upgrader.js +183 -82
  140. package/dist/src/upgrader.js.map +1 -1
  141. package/dist/src/version.d.ts.map +1 -1
  142. package/dist/src/version.js.map +1 -1
  143. package/package.json +66 -42
  144. package/src/address-manager/index.ts +2 -2
  145. package/src/circuit/README.md +2 -2
  146. package/src/circuit/auto-relay.ts +4 -4
  147. package/src/circuit/circuit/hop.ts +20 -11
  148. package/src/circuit/circuit/stop.ts +10 -5
  149. package/src/circuit/circuit/stream-handler.ts +6 -5
  150. package/src/circuit/index.ts +4 -13
  151. package/src/circuit/listener.ts +3 -3
  152. package/src/circuit/pb/index.ts +133 -15
  153. package/src/circuit/transport.ts +92 -63
  154. package/src/config.ts +27 -4
  155. package/src/connection-manager/auto-dialler.ts +1 -1
  156. package/src/connection-manager/dialer/auto-dialer.ts +8 -2
  157. package/src/connection-manager/dialer/dial-request.ts +1 -1
  158. package/src/connection-manager/dialer/index.ts +15 -15
  159. package/src/connection-manager/index.ts +239 -82
  160. package/src/constants.ts +5 -0
  161. package/src/content-routing/index.ts +2 -2
  162. package/src/content-routing/utils.ts +2 -2
  163. package/src/dht/dht-content-routing.ts +2 -2
  164. package/src/dht/dht-peer-routing.ts +3 -3
  165. package/src/dht/dummy-dht.ts +3 -3
  166. package/src/errors.ts +4 -1
  167. package/src/fetch/index.ts +120 -53
  168. package/src/fetch/pb/proto.ts +109 -11
  169. package/src/get-peer.ts +3 -3
  170. package/src/identify/index.ts +64 -47
  171. package/src/identify/pb/message.ts +111 -11
  172. package/src/index.ts +18 -17
  173. package/src/insecure/index.ts +11 -6
  174. package/src/insecure/pb/proto.ts +111 -12
  175. package/src/keychain/index.ts +2 -2
  176. package/src/libp2p.ts +34 -29
  177. package/src/metrics/index.ts +13 -12
  178. package/src/metrics/moving-average.ts +1 -1
  179. package/src/metrics/stats.ts +1 -1
  180. package/src/nat-manager.ts +1 -1
  181. package/src/peer-record-updater.ts +1 -1
  182. package/src/peer-routing.ts +4 -4
  183. package/src/ping/index.ts +48 -15
  184. package/src/pnet/index.ts +3 -2
  185. package/src/pubsub/dummy-pubsub.ts +2 -2
  186. package/src/registrar.ts +79 -55
  187. package/src/transport-manager.ts +3 -3
  188. package/src/upgrader.ts +223 -93
  189. package/src/version.ts +1 -2
@@ -7,17 +7,19 @@ import retimer from 'retimer'
7
7
  import type { AbortOptions } from '@libp2p/interfaces'
8
8
  import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events'
9
9
  import type { Startable } from '@libp2p/interfaces/startable'
10
- import { trackedMap } from '@libp2p/tracked-map'
11
10
  import { codes } from '../errors.js'
12
- import { isPeerId, PeerId } from '@libp2p/interfaces/peer-id'
11
+ import { isPeerId, PeerId } from '@libp2p/interface-peer-id'
13
12
  import { setMaxListeners } from 'events'
14
- import type { Connection } from '@libp2p/interfaces/connection'
15
- import type { ConnectionManager } from '@libp2p/interfaces/connection-manager'
16
- import { Components, Initializable } from '@libp2p/interfaces/components'
17
- import * as STATUS from '@libp2p/interfaces/connection/status'
13
+ import type { Connection } from '@libp2p/interface-connection'
14
+ import type { ConnectionManager } from '@libp2p/interface-connection-manager'
15
+ import { Components, Initializable } from '@libp2p/components'
16
+ import * as STATUS from '@libp2p/interface-connection/status'
18
17
  import { Dialer } from './dialer/index.js'
19
- import type { AddressSorter } from '@libp2p/interfaces/peer-store'
18
+ import type { AddressSorter } from '@libp2p/interface-peer-store'
20
19
  import type { Resolver } from '@multiformats/multiaddr'
20
+ import { PeerMap } from '@libp2p/peer-collections'
21
+ import { TimeoutController } from 'timeout-abort-controller'
22
+ import { KEEP_ALIVE } from '@libp2p/interface-peer-store/tags'
21
23
 
22
24
  const log = logger('libp2p:connection-manager')
23
25
 
@@ -30,13 +32,12 @@ const defaultOptions: Partial<ConnectionManagerInit> = {
30
32
  maxEventLoopDelay: Infinity,
31
33
  pollInterval: 2000,
32
34
  autoDialInterval: 10000,
33
- movingAverageInterval: 60000,
34
- defaultPeerValue: 0.5
35
+ movingAverageInterval: 60000
35
36
  }
36
37
 
38
+ const METRICS_SYSTEM = 'libp2p'
37
39
  const METRICS_COMPONENT = 'connection-manager'
38
- const METRICS_PEER_CONNECTIONS = 'peer-connections'
39
- const METRICS_PEER_VALUES = 'peer-values'
40
+ const STARTUP_RECONNECT_TIMEOUT = 60000
40
41
 
41
42
  export interface ConnectionManagerInit {
42
43
  /**
@@ -79,11 +80,6 @@ export interface ConnectionManagerInit {
79
80
  */
80
81
  movingAverageInterval?: number
81
82
 
82
- /**
83
- * The value of the peer
84
- */
85
- defaultPeerValue?: number
86
-
87
83
  /**
88
84
  * If true, try to connect to all discovered peers up to the connection manager limit
89
85
  */
@@ -111,10 +107,17 @@ export interface ConnectionManagerInit {
111
107
  maxAddrsToDial?: number
112
108
 
113
109
  /**
114
- * How long a dial attempt is allowed to take
110
+ * How long a dial attempt is allowed to take, including DNS resolution
111
+ * of the multiaddr, opening a socket and upgrading it to a Connection.
115
112
  */
116
113
  dialTimeout?: number
117
114
 
115
+ /**
116
+ * When a new inbound connection is opened, the upgrade process (e.g. protect,
117
+ * encrypt, multiplex etc) must complete within this number of ms.
118
+ */
119
+ inboundUpgradeTimeout: number
120
+
118
121
  /**
119
122
  * Number of max concurrent dials per peer
120
123
  */
@@ -124,6 +127,12 @@ export interface ConnectionManagerInit {
124
127
  * Multiaddr resolvers to use when dialing
125
128
  */
126
129
  resolvers?: Record<string, Resolver>
130
+
131
+ /**
132
+ * On startup we try to dial any peer that has previously been
133
+ * tagged with KEEP_ALIVE up to this timeout in ms. (default: 60000)
134
+ */
135
+ startupReconnectTimeout?: number
127
136
  }
128
137
 
129
138
  export interface ConnectionManagerEvents {
@@ -138,11 +147,13 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
138
147
  public readonly dialer: Dialer
139
148
  private components = new Components()
140
149
  private readonly opts: Required<ConnectionManagerInit>
141
- private readonly peerValues: Map<string, number>
142
150
  private readonly connections: Map<string, Connection[]>
143
151
  private started: boolean
144
152
  private timer?: ReturnType<retimer>
145
153
  private readonly latencyMonitor: LatencyMonitor
154
+ private readonly startupReconnectTimeout: number
155
+ private connectOnStartupController?: TimeoutController
156
+ private readonly dialTimeout: number
146
157
 
147
158
  constructor (init: ConnectionManagerInit) {
148
159
  super()
@@ -155,25 +166,10 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
155
166
 
156
167
  log('options: %o', this.opts)
157
168
 
158
- /**
159
- * Map of peer identifiers to their peer value for pruning connections.
160
- *
161
- * @type {Map<string, number>}
162
- */
163
- this.peerValues = trackedMap({
164
- component: METRICS_COMPONENT,
165
- metric: METRICS_PEER_VALUES,
166
- metrics: this.components.getMetrics()
167
- })
168
-
169
169
  /**
170
170
  * Map of connections per peer
171
171
  */
172
- this.connections = trackedMap({
173
- component: METRICS_COMPONENT,
174
- metric: METRICS_PEER_CONNECTIONS,
175
- metrics: this.components.getMetrics()
176
- })
172
+ this.connections = new Map()
177
173
 
178
174
  this.started = false
179
175
  this._checkMetrics = this._checkMetrics.bind(this)
@@ -192,12 +188,103 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
192
188
 
193
189
  this.onConnect = this.onConnect.bind(this)
194
190
  this.onDisconnect = this.onDisconnect.bind(this)
191
+
192
+ this.startupReconnectTimeout = init.startupReconnectTimeout ?? STARTUP_RECONNECT_TIMEOUT
193
+ this.dialTimeout = init.dialTimeout ?? 30000
195
194
  }
196
195
 
197
196
  init (components: Components): void {
198
197
  this.components = components
199
198
 
200
199
  this.dialer.init(components)
200
+
201
+ // track inbound/outbound connections
202
+ this.components.getMetrics()?.updateComponentMetric({
203
+ system: METRICS_SYSTEM,
204
+ component: METRICS_COMPONENT,
205
+ metric: 'connections',
206
+ label: 'direction',
207
+ value: () => {
208
+ const metric = {
209
+ inbound: 0,
210
+ outbound: 0
211
+ }
212
+
213
+ for (const conns of this.connections.values()) {
214
+ for (const conn of conns) {
215
+ if (conn.stat.direction === 'inbound') {
216
+ metric.inbound++
217
+ } else {
218
+ metric.outbound++
219
+ }
220
+ }
221
+ }
222
+
223
+ return metric
224
+ }
225
+ })
226
+
227
+ // track total number of streams per protocol
228
+ this.components.getMetrics()?.updateComponentMetric({
229
+ system: METRICS_SYSTEM,
230
+ component: METRICS_COMPONENT,
231
+ metric: 'protocol-streams-total',
232
+ label: 'protocol',
233
+ value: () => {
234
+ const metric: Record<string, number> = {}
235
+
236
+ for (const conns of this.connections.values()) {
237
+ for (const conn of conns) {
238
+ for (const stream of conn.streams) {
239
+ const key = `${stream.stat.direction} ${stream.stat.protocol ?? 'unnegotiated'}`
240
+
241
+ metric[key] = (metric[key] ?? 0) + 1
242
+ }
243
+ }
244
+ }
245
+
246
+ return metric
247
+ }
248
+ })
249
+
250
+ // track 90th percentile of streams per protocol
251
+ this.components.getMetrics()?.updateComponentMetric({
252
+ system: METRICS_SYSTEM,
253
+ component: METRICS_COMPONENT,
254
+ metric: 'protocol-streams-per-connection-90th-percentile',
255
+ label: 'protocol',
256
+ value: () => {
257
+ const allStreams: Record<string, number[]> = {}
258
+
259
+ for (const conns of this.connections.values()) {
260
+ for (const conn of conns) {
261
+ const streams: Record<string, number> = {}
262
+
263
+ for (const stream of conn.streams) {
264
+ const key = `${stream.stat.direction} ${stream.stat.protocol ?? 'unnegotiated'}`
265
+
266
+ streams[key] = (streams[key] ?? 0) + 1
267
+ }
268
+
269
+ for (const [protocol, count] of Object.entries(streams)) {
270
+ allStreams[protocol] = allStreams[protocol] ?? []
271
+ allStreams[protocol].push(count)
272
+ }
273
+ }
274
+ }
275
+
276
+ const metric: Record<string, number> = {}
277
+
278
+ for (let [protocol, counts] of Object.entries(allStreams)) {
279
+ counts = counts.sort((a, b) => a - b)
280
+
281
+ const index = Math.floor(counts.length * 0.9)
282
+ metric[protocol] = counts[index]
283
+ }
284
+
285
+ return metric
286
+ }
287
+ })
201
288
  }
202
289
 
203
290
  isStarted () {
@@ -226,9 +313,51 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
226
313
  async afterStart () {
227
314
  this.components.getUpgrader().addEventListener('connection', this.onConnect)
228
315
  this.components.getUpgrader().addEventListener('connectionEnd', this.onDisconnect)
316
+
317
+ // re-connect to any peers with the KEEP_ALIVE tag
318
+ void Promise.resolve()
319
+ .then(async () => {
320
+ const keepAlivePeers: PeerId[] = []
321
+
322
+ for (const peer of await this.components.getPeerStore().all()) {
323
+ const tags = await this.components.getPeerStore().getTags(peer.id)
324
+ const hasKeepAlive = tags.filter(tag => tag.name === KEEP_ALIVE).length > 0
325
+
326
+ if (hasKeepAlive) {
327
+ keepAlivePeers.push(peer.id)
328
+ }
329
+ }
330
+
331
+ this.connectOnStartupController?.clear()
332
+ this.connectOnStartupController = new TimeoutController(this.startupReconnectTimeout)
333
+
334
+ try {
335
+ // fails on node < 15.4
336
+ setMaxListeners?.(Infinity, this.connectOnStartupController.signal)
337
+ } catch {}
338
+
339
+ await Promise.all(
340
+ keepAlivePeers.map(async peer => {
341
+ await this.openConnection(peer, {
342
+ signal: this.connectOnStartupController?.signal
343
+ })
344
+ .catch(err => {
345
+ log.error(err)
346
+ })
347
+ })
348
+ )
349
+ })
350
+ .catch(err => {
351
+ log.error(err)
352
+ })
353
+ .finally(() => {
354
+ this.connectOnStartupController?.clear()
355
+ })
229
356
  }
230
357
 
231
358
  async beforeStop () {
359
+ // if we are still dialing KEEP_ALIVE peers, abort those dials
360
+ this.connectOnStartupController?.abort()
232
361
  this.components.getUpgrader().removeEventListener('connection', this.onConnect)
233
362
  this.components.getUpgrader().removeEventListener('connectionEnd', this.onDisconnect)
234
363
  }
@@ -271,18 +400,6 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
271
400
  this.connections.clear()
272
401
  }
273
402
 
274
- /**
275
- * Sets the value of the given peer. Peers with lower values
276
- * will be disconnected first.
277
- */
278
- setPeerValue (peerId: PeerId, value: number) {
279
- if (value < 0 || value > 1) {
280
- throw new Error('value should be a number between 0 and 1')
281
- }
282
-
283
- this.peerValues.set(peerId.toString(), value)
284
- }
285
-
286
403
  /**
287
404
  * Checks the libp2p metrics to determine if any values have exceeded
288
405
  * the configured maximums.
@@ -340,10 +457,6 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
340
457
  await this.components.getPeerStore().keyBook.set(peerId, peerId.publicKey)
341
458
  }
342
459
 
343
- if (!this.peerValues.has(peerIdStr)) {
344
- this.peerValues.set(peerIdStr, this.opts.defaultPeerValue)
345
- }
346
-
347
460
  const numConnections = this.getConnections().length
348
461
  const toPrune = numConnections - this.opts.maxConnections
349
462
 
@@ -370,7 +483,6 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
370
483
  this.connections.set(peerId, storedConn)
371
484
  } else if (storedConn != null) {
372
485
  this.connections.delete(peerId)
373
- this.peerValues.delete(connection.remotePeer.toString())
374
486
  this.dispatchEvent(new CustomEvent<Connection>('peer:disconnect', { detail: connection }))
375
487
 
376
488
  this.components.getMetrics()?.onPeerDisconnected(connection.remotePeer)
@@ -391,7 +503,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
391
503
  return conns
392
504
  }
393
505
 
394
- async openConnection (peerId: PeerId, options?: AbortOptions): Promise<Connection> {
506
+ async openConnection (peerId: PeerId, options: AbortOptions = {}): Promise<Connection> {
395
507
  log('dial to %p', peerId)
396
508
  const existingConnections = this.getConnections(peerId)
397
509
 
@@ -401,30 +513,48 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
401
513
  return existingConnections[0]
402
514
  }
403
515
 
404
- const connection = await this.dialer.dial(peerId, options)
405
- let peerConnections = this.connections.get(peerId.toString())
516
+ let timeoutController: TimeoutController | undefined
517
+
518
+ if (options?.signal == null) {
519
+ timeoutController = new TimeoutController(this.dialTimeout)
520
+ options.signal = timeoutController.signal
406
521
 
407
- if (peerConnections == null) {
408
- peerConnections = []
409
- this.connections.set(peerId.toString(), peerConnections)
522
+ try {
523
+ // fails on node < 15.4
524
+ setMaxListeners?.(Infinity, timeoutController.signal)
525
+ } catch {}
410
526
  }
411
527
 
412
- // we get notified of connections via the Upgrader emitting "connection"
413
- // events, double check we aren't already tracking this connection before
414
- // storing it
415
- let trackedConnection = false
528
+ try {
529
+ const connection = await this.dialer.dial(peerId, options)
530
+ let peerConnections = this.connections.get(peerId.toString())
416
531
 
417
- for (const conn of peerConnections) {
418
- if (conn.id === connection.id) {
419
- trackedConnection = true
532
+ if (peerConnections == null) {
533
+ peerConnections = []
534
+ this.connections.set(peerId.toString(), peerConnections)
420
535
  }
421
- }
422
536
 
423
- if (!trackedConnection) {
424
- peerConnections.push(connection)
425
- }
537
+ // we get notified of connections via the Upgrader emitting "connection"
538
+ // events, double check we aren't already tracking this connection before
539
+ // storing it
540
+ let trackedConnection = false
541
+
542
+ for (const conn of peerConnections) {
543
+ if (conn.id === connection.id) {
544
+ trackedConnection = true
545
+ }
546
+ }
547
+
548
+ if (!trackedConnection) {
549
+ peerConnections.push(connection)
550
+ }
426
551
 
427
- return connection
552
+ return connection
553
+ } finally {
554
+ if (timeoutController != null) {
555
+ timeoutController.clear()
556
+ }
557
+ }
428
558
  }
429
559
 
430
560
  async closeConnections (peerId: PeerId): Promise<void> {
@@ -475,7 +605,7 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
475
605
  const limit = this.opts[name]
476
606
  log.trace('checking limit of %s. current value: %d of %d', name, value, limit)
477
607
  if (value > limit) {
478
- log('%s: limit exceeded: %p, %d, pruning %d connection(s)', this.components.getPeerId(), name, value, toPrune)
608
+ log('%s: limit exceeded: %p, %d/%d, pruning %d connection(s)', this.components.getPeerId(), name, value, limit, toPrune)
479
609
  await this._maybePruneConnections(toPrune)
480
610
  }
481
611
  }
@@ -491,22 +621,49 @@ export class DefaultConnectionManager extends EventEmitter<ConnectionManagerEven
491
621
  return
492
622
  }
493
623
 
494
- const peerValues = Array.from(new Map([...this.peerValues.entries()].sort((a, b) => a[1] - b[1])))
495
- log.trace('sorted peer values: %j', peerValues)
624
+ const peerValues = new PeerMap<number>()
496
625
 
497
- const toClose = []
626
+ // work out peer values
627
+ for (const connection of connections) {
628
+ const remotePeer = connection.remotePeer
498
629
 
499
- for (const [peerId] of peerValues) {
500
- log('too many connections open - closing a connection to %p', peerId)
630
+ if (peerValues.has(remotePeer)) {
631
+ continue
632
+ }
501
633
 
502
- for (const connection of connections) {
503
- if (connection.remotePeer.toString() === peerId) {
504
- toClose.push(connection)
505
- }
634
+ const tags = await this.components.getPeerStore().getTags(remotePeer)
506
635
 
507
- if (toClose.length === toPrune) {
508
- break
509
- }
636
+ // sum all tag values
637
+ peerValues.set(remotePeer, tags.reduce((acc, curr) => {
638
+ return acc + curr.value
639
+ }, 0))
640
+ }
641
+
642
+ // sort by value, lowest to highest
643
+ const sortedConnections = connections.sort((a, b) => {
644
+ const peerAValue = peerValues.get(a.remotePeer) ?? 0
645
+ const peerBValue = peerValues.get(b.remotePeer) ?? 0
646
+
647
+ if (peerAValue > peerBValue) {
648
+ return 1
649
+ }
650
+
651
+ if (peerAValue < peerBValue) {
652
+ return -1
653
+ }
654
+
655
+ return 0
656
+ })
657
+
658
+ // close some connections
659
+ const toClose = []
660
+
661
+ for (const connection of sortedConnections) {
662
+ log('too many connections open - closing a connection to %p', connection.remotePeer)
663
+ toClose.push(connection)
664
+
665
+ if (toClose.length === toPrune) {
666
+ break
510
667
  }
511
668
  }
512
669
 
package/src/constants.ts CHANGED
@@ -4,6 +4,11 @@
4
4
  */
5
5
  export const DIAL_TIMEOUT = 30e3
6
6
 
7
+ /**
8
+ * How long in ms an inbound connection upgrade is allowed to take
9
+ */
10
+ export const INBOUND_UPGRADE_TIMEOUT = 30e3
11
+
7
12
  /**
8
13
  * Maximum allowed concurrent dials
9
14
  */
@@ -8,11 +8,11 @@ import {
8
8
  import drain from 'it-drain'
9
9
  import merge from 'it-merge'
10
10
  import { pipe } from 'it-pipe'
11
- import type { ContentRouting } from '@libp2p/interfaces/content-routing'
11
+ import type { ContentRouting } from '@libp2p/interface-content-routing'
12
12
  import type { AbortOptions } from '@libp2p/interfaces'
13
13
  import type { Startable } from '@libp2p/interfaces/startable'
14
14
  import type { CID } from 'multiformats/cid'
15
- import type { Components } from '@libp2p/interfaces/components'
15
+ import type { Components } from '@libp2p/components'
16
16
 
17
17
  export interface CompoundContentRoutingInit {
18
18
  routers: ContentRouting[]
@@ -2,8 +2,8 @@ import errCode from 'err-code'
2
2
  import filter from 'it-filter'
3
3
  import map from 'it-map'
4
4
  import type { Source } from 'it-stream-types'
5
- import type { PeerInfo } from '@libp2p/interfaces/peer-info'
6
- import type { PeerStore } from '@libp2p/interfaces/peer-store'
5
+ import type { PeerInfo } from '@libp2p/interface-peer-info'
6
+ import type { PeerStore } from '@libp2p/interface-peer-store'
7
7
 
8
8
  /**
9
9
  * Store the multiaddrs from every peer in the passed peer store
@@ -1,7 +1,7 @@
1
1
  import drain from 'it-drain'
2
2
  import errCode from 'err-code'
3
- import type { DHT } from '@libp2p/interfaces/dht'
4
- import type { ContentRouting } from '@libp2p/interfaces/content-routing'
3
+ import type { DHT } from '@libp2p/interface-dht'
4
+ import type { ContentRouting } from '@libp2p/interface-content-routing'
5
5
  import type { CID } from 'multiformats/cid'
6
6
  import type { AbortOptions } from '@libp2p/interfaces'
7
7
 
@@ -1,8 +1,8 @@
1
1
  import errCode from 'err-code'
2
2
  import { messages, codes } from '../errors.js'
3
- import type { PeerRouting } from '@libp2p/interfaces/peer-routing'
4
- import type { DHT } from '@libp2p/interfaces/dht'
5
- import type { PeerId } from '@libp2p/interfaces/peer-id'
3
+ import type { PeerRouting } from '@libp2p/interface-peer-routing'
4
+ import type { DHT } from '@libp2p/interface-dht'
5
+ import type { PeerId } from '@libp2p/interface-peer-id'
6
6
  import type { AbortOptions } from '@libp2p/interfaces'
7
7
 
8
8
  /**
@@ -1,9 +1,9 @@
1
- import type { DualDHT, QueryEvent, SingleDHT } from '@libp2p/interfaces/dht'
2
- import type { PeerDiscoveryEvents } from '@libp2p/interfaces/peer-discovery'
1
+ import type { DualDHT, QueryEvent, SingleDHT } from '@libp2p/interface-dht'
2
+ import type { PeerDiscoveryEvents } from '@libp2p/interface-peer-discovery'
3
3
  import errCode from 'err-code'
4
4
  import { messages, codes } from '../errors.js'
5
5
  import { EventEmitter } from '@libp2p/interfaces/events'
6
- import { symbol } from '@libp2p/interfaces/peer-discovery'
6
+ import { symbol } from '@libp2p/interface-peer-discovery'
7
7
 
8
8
  export class DummyDHT extends EventEmitter<PeerDiscoveryEvents> implements DualDHT {
9
9
  get [symbol] (): true {
package/src/errors.ts CHANGED
@@ -70,5 +70,8 @@ export enum codes {
70
70
  ERR_NOT_IMPLEMENTED = 'ERR_NOT_IMPLEMENTED',
71
71
  ERR_WRONG_PING_ACK = 'ERR_WRONG_PING_ACK',
72
72
  ERR_INVALID_RECORD = 'ERR_INVALID_RECORD',
73
- ERR_ALREADY_SUCCEEDED = 'ERR_ALREADY_SUCCEEDED'
73
+ ERR_ALREADY_SUCCEEDED = 'ERR_ALREADY_SUCCEEDED',
74
+ ERR_NO_HANDLER_FOR_PROTOCOL = 'ERR_NO_HANDLER_FOR_PROTOCOL',
75
+ ERR_TOO_MANY_OUTBOUND_PROTOCOL_STREAMS = 'ERR_TOO_MANY_OUTBOUND_PROTOCOL_STREAMS',
76
+ ERR_TOO_MANY_INBOUND_PROTOCOL_STREAMS = 'ERR_TOO_MANY_INBOUND_PROTOCOL_STREAMS'
74
77
  }