libp2p 2.9.0 → 2.10.0-8484de8a2

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 (119) hide show
  1. package/dist/index.min.js +13 -17
  2. package/dist/index.min.js.map +4 -4
  3. package/dist/src/address-manager/dns-mappings.d.ts +1 -2
  4. package/dist/src/address-manager/dns-mappings.d.ts.map +1 -1
  5. package/dist/src/address-manager/dns-mappings.js +40 -44
  6. package/dist/src/address-manager/dns-mappings.js.map +1 -1
  7. package/dist/src/address-manager/index.d.ts.map +1 -1
  8. package/dist/src/address-manager/index.js +31 -14
  9. package/dist/src/address-manager/index.js.map +1 -1
  10. package/dist/src/address-manager/ip-mappings.d.ts +1 -0
  11. package/dist/src/address-manager/ip-mappings.d.ts.map +1 -1
  12. package/dist/src/address-manager/ip-mappings.js +51 -40
  13. package/dist/src/address-manager/ip-mappings.js.map +1 -1
  14. package/dist/src/address-manager/observed-addresses.d.ts.map +1 -1
  15. package/dist/src/address-manager/observed-addresses.js +1 -3
  16. package/dist/src/address-manager/observed-addresses.js.map +1 -1
  17. package/dist/src/address-manager/transport-addresses.d.ts.map +1 -1
  18. package/dist/src/address-manager/transport-addresses.js +6 -8
  19. package/dist/src/address-manager/transport-addresses.js.map +1 -1
  20. package/dist/src/config/connection-gater.browser.d.ts.map +1 -1
  21. package/dist/src/config/connection-gater.browser.js +3 -9
  22. package/dist/src/config/connection-gater.browser.js.map +1 -1
  23. package/dist/src/config.js +1 -1
  24. package/dist/src/config.js.map +1 -1
  25. package/dist/src/connection-manager/address-sorter.d.ts.map +1 -1
  26. package/dist/src/connection-manager/address-sorter.js +1 -2
  27. package/dist/src/connection-manager/address-sorter.js.map +1 -1
  28. package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -1
  29. package/dist/src/connection-manager/connection-pruner.js +7 -3
  30. package/dist/src/connection-manager/connection-pruner.js.map +1 -1
  31. package/dist/src/connection-manager/constants.defaults.d.ts +4 -0
  32. package/dist/src/connection-manager/constants.defaults.d.ts.map +1 -1
  33. package/dist/src/connection-manager/constants.defaults.js +4 -0
  34. package/dist/src/connection-manager/constants.defaults.js.map +1 -1
  35. package/dist/src/connection-manager/dial-queue.d.ts +2 -2
  36. package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
  37. package/dist/src/connection-manager/dial-queue.js +13 -25
  38. package/dist/src/connection-manager/dial-queue.js.map +1 -1
  39. package/dist/src/connection-manager/index.d.ts +10 -2
  40. package/dist/src/connection-manager/index.d.ts.map +1 -1
  41. package/dist/src/connection-manager/index.js +45 -27
  42. package/dist/src/connection-manager/index.js.map +1 -1
  43. package/dist/src/connection-manager/reconnect-queue.js +1 -1
  44. package/dist/src/connection-manager/reconnect-queue.js.map +1 -1
  45. package/dist/src/connection-manager/utils.d.ts +31 -3
  46. package/dist/src/connection-manager/utils.d.ts.map +1 -1
  47. package/dist/src/connection-manager/utils.js +99 -18
  48. package/dist/src/connection-manager/utils.js.map +1 -1
  49. package/dist/src/connection-monitor.d.ts +1 -1
  50. package/dist/src/connection-monitor.d.ts.map +1 -1
  51. package/dist/src/connection-monitor.js +2 -3
  52. package/dist/src/connection-monitor.js.map +1 -1
  53. package/dist/src/connection.d.ts +62 -0
  54. package/dist/src/connection.d.ts.map +1 -0
  55. package/dist/src/connection.js +239 -0
  56. package/dist/src/connection.js.map +1 -0
  57. package/dist/src/get-peer.js +3 -3
  58. package/dist/src/get-peer.js.map +1 -1
  59. package/dist/src/index.d.ts +2 -2
  60. package/dist/src/index.js +2 -2
  61. package/dist/src/libp2p.d.ts.map +1 -1
  62. package/dist/src/libp2p.js +5 -5
  63. package/dist/src/libp2p.js.map +1 -1
  64. package/dist/src/peer-routing.js +1 -1
  65. package/dist/src/peer-routing.js.map +1 -1
  66. package/dist/src/random-walk.d.ts.map +1 -1
  67. package/dist/src/random-walk.js +13 -3
  68. package/dist/src/random-walk.js.map +1 -1
  69. package/dist/src/registrar.d.ts +3 -3
  70. package/dist/src/registrar.d.ts.map +1 -1
  71. package/dist/src/registrar.js +50 -41
  72. package/dist/src/registrar.js.map +1 -1
  73. package/dist/src/transport-manager.js +15 -2
  74. package/dist/src/transport-manager.js.map +1 -1
  75. package/dist/src/upgrader.d.ts +27 -25
  76. package/dist/src/upgrader.d.ts.map +1 -1
  77. package/dist/src/upgrader.js +97 -336
  78. package/dist/src/upgrader.js.map +1 -1
  79. package/dist/src/utils.d.ts +3 -0
  80. package/dist/src/utils.d.ts.map +1 -0
  81. package/dist/src/utils.js +25 -0
  82. package/dist/src/utils.js.map +1 -0
  83. package/dist/src/version.d.ts +1 -1
  84. package/dist/src/version.d.ts.map +1 -1
  85. package/dist/src/version.js +1 -1
  86. package/dist/src/version.js.map +1 -1
  87. package/package.json +26 -30
  88. package/src/address-manager/dns-mappings.ts +51 -51
  89. package/src/address-manager/index.ts +37 -17
  90. package/src/address-manager/ip-mappings.ts +64 -44
  91. package/src/address-manager/observed-addresses.ts +1 -3
  92. package/src/address-manager/transport-addresses.ts +7 -9
  93. package/src/config/connection-gater.browser.ts +3 -12
  94. package/src/config.ts +1 -1
  95. package/src/connection-manager/address-sorter.ts +1 -2
  96. package/src/connection-manager/connection-pruner.ts +8 -3
  97. package/src/connection-manager/constants.defaults.ts +5 -0
  98. package/src/connection-manager/dial-queue.ts +14 -29
  99. package/src/connection-manager/index.ts +62 -29
  100. package/src/connection-manager/reconnect-queue.ts +1 -1
  101. package/src/connection-manager/utils.ts +129 -21
  102. package/src/connection-monitor.ts +3 -4
  103. package/src/connection.ts +316 -0
  104. package/src/get-peer.ts +3 -3
  105. package/src/index.ts +2 -2
  106. package/src/libp2p.ts +5 -6
  107. package/src/peer-routing.ts +1 -1
  108. package/src/random-walk.ts +13 -3
  109. package/src/registrar.ts +67 -54
  110. package/src/transport-manager.ts +18 -2
  111. package/src/upgrader.ts +143 -421
  112. package/src/utils.ts +31 -0
  113. package/src/version.ts +1 -1
  114. package/dist/src/connection/index.d.ts +0 -84
  115. package/dist/src/connection/index.d.ts.map +0 -1
  116. package/dist/src/connection/index.js +0 -144
  117. package/dist/src/connection/index.js.map +0 -1
  118. package/dist/typedoc-urls.json +0 -24
  119. package/src/connection/index.ts +0 -199
@@ -1,6 +1,6 @@
1
1
  import { isIPv4 } from '@chainsafe/is-ip'
2
- import { trackedMap } from '@libp2p/utils/tracked-map'
3
- import { multiaddr, protocols } from '@multiformats/multiaddr'
2
+ import { getNetConfig, isNetworkAddress, trackedMap } from '@libp2p/utils'
3
+ import { CODE_IP4, CODE_IP6, multiaddr } from '@multiformats/multiaddr'
4
4
  import type { AddressManagerComponents, AddressManagerInit } from './index.js'
5
5
  import type { Logger } from '@libp2p/interface'
6
6
  import type { NodeAddress } from '@libp2p/interface-internal'
@@ -22,11 +22,6 @@ interface PublicAddressMapping {
22
22
  lastVerified?: number
23
23
  }
24
24
 
25
- const CODEC_IP4 = 0x04
26
- const CODEC_IP6 = 0x29
27
- const CODEC_TCP = 0x06
28
- const CODEC_UDP = 0x0111
29
-
30
25
  export class IPMappings {
31
26
  private readonly log: Logger
32
27
  private readonly mappings: Map<string, PublicAddressMapping[]>
@@ -40,11 +35,15 @@ export class IPMappings {
40
35
  }
41
36
 
42
37
  has (ma: Multiaddr): boolean {
43
- const tuples = ma.stringTuples()
38
+ const config = getNetConfig(ma)
39
+
40
+ if (config.type !== 'ip4' && config.type !== 'ip6') {
41
+ return false
42
+ }
44
43
 
45
44
  for (const mappings of this.mappings.values()) {
46
45
  for (const mapping of mappings) {
47
- if (mapping.externalIp === tuples[0][1]) {
46
+ if (mapping.externalIp === config.host) {
48
47
  return true
49
48
  }
50
49
  }
@@ -72,18 +71,20 @@ export class IPMappings {
72
71
  }
73
72
 
74
73
  remove (ma: Multiaddr): boolean {
75
- const tuples = ma.stringTuples()
76
- const host = tuples[0][1] ?? ''
77
- const protocol = tuples[1][0] === CODEC_TCP ? 'tcp' : 'udp'
78
- const port = parseInt(tuples[1][1] ?? '0')
74
+ const config = getNetConfig(ma)
75
+
76
+ if (config.type !== 'ip4' && config.type !== 'ip6') {
77
+ return false
78
+ }
79
+
79
80
  let wasConfident = false
80
81
 
81
82
  for (const [key, mappings] of this.mappings.entries()) {
82
83
  for (let i = 0; i < mappings.length; i++) {
83
84
  const mapping = mappings[i]
84
85
 
85
- if (mapping.externalIp === host && mapping.externalPort === port && mapping.protocol === protocol) {
86
- this.log('removing %s:%s to %s:%s %s IP mapping', mapping.externalIp, mapping.externalPort, host, port, protocol)
86
+ if (mapping.externalIp === config.host && mapping.externalPort === config.port && mapping.protocol === config.protocol) {
87
+ this.log('removing %s:%s to %s:%s %s IP mapping', mapping.externalIp, mapping.externalPort, config.host, config.port, config.protocol)
87
88
 
88
89
  wasConfident = wasConfident || mapping.verified
89
90
  mappings.splice(i, 1)
@@ -103,40 +104,38 @@ export class IPMappings {
103
104
  const ipMappedAddresses: NodeAddress[] = []
104
105
 
105
106
  for (const { multiaddr: ma } of addresses) {
106
- const tuples = ma.stringTuples()
107
- let tuple: string | undefined
107
+ if (!isNetworkAddress(ma)) {
108
+ continue
109
+ }
110
+
111
+ const config = getNetConfig(ma)
112
+
113
+ if (config.type !== 'ip4' && config.type !== 'ip6') {
114
+ continue
115
+ }
116
+
117
+ let key: string | undefined
108
118
 
109
119
  // see if the internal host/port/protocol tuple has been mapped externally
110
- if ((tuples[0][0] === CODEC_IP4 || tuples[0][0] === CODEC_IP6) && tuples[1][0] === CODEC_TCP) {
111
- tuple = `${tuples[0][1]}-${tuples[1][1]}-tcp`
112
- } else if ((tuples[0][0] === CODEC_IP4 || tuples[0][0] === CODEC_IP6) && tuples[1][0] === CODEC_UDP) {
113
- tuple = `${tuples[0][1]}-${tuples[1][1]}-udp`
120
+ if (config.protocol === 'tcp') {
121
+ key = `${config.host}-${config.port}-tcp`
122
+ } else if (config.protocol === 'udp') {
123
+ key = `${config.host}-${config.port}-udp`
114
124
  }
115
125
 
116
- if (tuple == null) {
126
+ if (key == null) {
117
127
  continue
118
128
  }
119
129
 
120
- const mappings = this.mappings.get(tuple)
130
+ const mappings = this.mappings.get(key)
121
131
 
122
132
  if (mappings == null) {
123
133
  continue
124
134
  }
125
135
 
126
136
  for (const mapping of mappings) {
127
- tuples[0][0] = mapping.externalFamily === 4 ? CODEC_IP4 : CODEC_IP6
128
- tuples[0][1] = mapping.externalIp
129
- tuples[1][1] = `${mapping.externalPort}`
130
-
131
137
  ipMappedAddresses.push({
132
- multiaddr: multiaddr(`/${
133
- tuples.map(tuple => {
134
- return [
135
- protocols(tuple[0]).name,
136
- tuple[1]
137
- ].join('/')
138
- }).join('/')
139
- }`),
138
+ multiaddr: this.maybeOverrideIp(ma, mapping.externalIp, mapping.externalFamily, mapping.protocol, mapping.externalPort),
140
139
  verified: mapping.verified,
141
140
  type: 'ip-mapping',
142
141
  expires: mapping.expires,
@@ -148,14 +147,34 @@ export class IPMappings {
148
147
  return ipMappedAddresses
149
148
  }
150
149
 
150
+ private maybeOverrideIp (ma: Multiaddr, externalIp: string, externalFamily: number, protocol: 'tcp' | 'udp', externalPort: number): Multiaddr {
151
+ const components = ma.getComponents()
152
+
153
+ const ipIndex = components.findIndex(c => c.code === CODE_IP4 || c.code === CODE_IP6)
154
+ const portIndex = components.findIndex(c => c.name === protocol)
155
+
156
+ if (ipIndex > -1 && portIndex > -1) {
157
+ components[ipIndex].value = externalIp
158
+ components[ipIndex].code = externalFamily === 4 ? CODE_IP4 : CODE_IP6
159
+ components[portIndex].value = `${externalPort}`
160
+
161
+ return multiaddr(components)
162
+ }
163
+
164
+ return ma
165
+ }
166
+
151
167
  confirm (ma: Multiaddr, ttl: number): boolean {
152
- const tuples = ma.stringTuples()
153
- const host = tuples[0][1]
168
+ if (!isNetworkAddress(ma)) {
169
+ return false
170
+ }
171
+
172
+ const config = getNetConfig(ma)
154
173
  let startingConfidence = false
155
174
 
156
175
  for (const mappings of this.mappings.values()) {
157
176
  for (const mapping of mappings) {
158
- if (mapping.externalIp === host) {
177
+ if (mapping.externalIp === config.host) {
159
178
  this.log('marking %s to %s IP mapping as verified', mapping.internalIp, mapping.externalIp)
160
179
  startingConfidence = mapping.verified
161
180
  mapping.verified = true
@@ -169,18 +188,19 @@ export class IPMappings {
169
188
  }
170
189
 
171
190
  unconfirm (ma: Multiaddr, ttl: number): boolean {
172
- const tuples = ma.stringTuples()
173
- const host = tuples[0][1] ?? ''
174
- const protocol = tuples[1][0] === CODEC_TCP ? 'tcp' : 'udp'
175
- const port = parseInt(tuples[1][1] ?? '0')
191
+ if (!isNetworkAddress(ma)) {
192
+ return false
193
+ }
194
+
195
+ const config = getNetConfig(ma)
176
196
  let wasConfident = false
177
197
 
178
198
  for (const mappings of this.mappings.values()) {
179
199
  for (let i = 0; i < mappings.length; i++) {
180
200
  const mapping = mappings[i]
181
201
 
182
- if (mapping.externalIp === host && mapping.externalPort === port && mapping.protocol === protocol) {
183
- this.log('removing verification of %s:%s to %s:%s %s IP mapping', mapping.externalIp, mapping.externalPort, host, port, protocol)
202
+ if (mapping.externalIp === config.host && mapping.externalPort === config.port && mapping.protocol === config.protocol) {
203
+ this.log('removing verification of %s:%s to %s:%s %s IP mapping', mapping.externalIp, mapping.externalPort, config.host, config.port, config.protocol)
184
204
 
185
205
  wasConfident = wasConfident || mapping.verified
186
206
  mapping.verified = false
@@ -1,6 +1,4 @@
1
- import { isLinkLocal } from '@libp2p/utils/multiaddr/is-link-local'
2
- import { isPrivate } from '@libp2p/utils/multiaddr/is-private'
3
- import { trackedMap } from '@libp2p/utils/tracked-map'
1
+ import { isLinkLocal, isPrivate, trackedMap } from '@libp2p/utils'
4
2
  import { multiaddr } from '@multiformats/multiaddr'
5
3
  import type { AddressManagerComponents, AddressManagerInit } from './index.js'
6
4
  import type { Logger } from '@libp2p/interface'
@@ -1,6 +1,4 @@
1
- import { isNetworkAddress } from '@libp2p/utils/multiaddr/is-network-address'
2
- import { isPrivate } from '@libp2p/utils/multiaddr/is-private'
3
- import { trackedMap } from '@libp2p/utils/tracked-map'
1
+ import { getNetConfig, isNetworkAddress, isPrivate, trackedMap } from '@libp2p/utils'
4
2
  import type { AddressManagerComponents, AddressManagerInit } from './index.js'
5
3
  import type { Logger } from '@libp2p/interface'
6
4
  import type { NodeAddress } from '@libp2p/interface-internal'
@@ -114,13 +112,13 @@ export class TransportAddresses {
114
112
  }
115
113
 
116
114
  private toKey (ma: Multiaddr): string {
117
- if (isNetworkAddress(ma)) {
118
- // only works for dns/ip based addresses
119
- const options = ma.toOptions()
120
-
121
- return `${options.host}-${options.port}-${options.transport}`
115
+ if (!isNetworkAddress(ma)) {
116
+ return ma.toString()
122
117
  }
123
118
 
124
- return ma.toString()
119
+ // only works for dns/ip based addresses
120
+ const config = getNetConfig(ma)
121
+
122
+ return `${config.host}-${config.port}-${config.protocol}`
125
123
  }
126
124
  }
@@ -1,11 +1,8 @@
1
- import { isPrivateIp } from '@libp2p/utils/private-ip'
1
+ import { isPrivate } from '@libp2p/utils'
2
2
  import { WebSockets } from '@multiformats/multiaddr-matcher'
3
3
  import type { ConnectionGater } from '@libp2p/interface'
4
4
  import type { Multiaddr } from '@multiformats/multiaddr'
5
5
 
6
- const CODEC_IP4 = 0x04
7
- const CODEC_IP6 = 0x29
8
-
9
6
  /**
10
7
  * Returns a connection gater that disallows dialling private addresses or
11
8
  * insecure websockets by default.
@@ -21,17 +18,11 @@ export function connectionGater (gater: ConnectionGater = {}): ConnectionGater {
21
18
  denyDialMultiaddr: async (multiaddr: Multiaddr) => {
22
19
  // do not connect to insecure websockets by default
23
20
  if (WebSockets.matches(multiaddr)) {
24
- return false
21
+ return true
25
22
  }
26
23
 
27
- const tuples = multiaddr.stringTuples()
28
-
29
24
  // do not connect to private addresses by default
30
- if (tuples[0][0] === CODEC_IP4 || tuples[0][0] === CODEC_IP6) {
31
- return Boolean(isPrivateIp(`${tuples[0][1]}`))
32
- }
33
-
34
- return false
25
+ return isPrivate(multiaddr)
35
26
  },
36
27
  denyInboundConnection: async () => false,
37
28
  denyOutboundConnection: async () => false,
package/src/config.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { FaultTolerance, InvalidParametersError } from '@libp2p/interface'
2
- import { mergeOptions } from '@libp2p/utils/merge-options'
2
+ import { mergeOptions } from '@libp2p/utils'
3
3
  import { dnsaddrResolver } from './connection-manager/resolvers/dnsaddr.ts'
4
4
  import type { Libp2pInit } from './index.js'
5
5
  import type { ServiceMap } from '@libp2p/interface'
@@ -1,5 +1,4 @@
1
- import { isLoopback } from '@libp2p/utils/multiaddr/is-loopback'
2
- import { isPrivate } from '@libp2p/utils/multiaddr/is-private'
1
+ import { isLoopback, isPrivate } from '@libp2p/utils'
3
2
  import { Circuit, WebSockets, WebSocketsSecure, WebRTC, WebRTCDirect, WebTransport, TCP } from '@multiformats/multiaddr-matcher'
4
3
  import type { Address } from '@libp2p/interface'
5
4
 
@@ -1,6 +1,6 @@
1
1
  import { PeerMap } from '@libp2p/peer-collections'
2
- import { safelyCloseConnectionIfUnused } from '@libp2p/utils/close'
3
- import { multiaddrToIpNet } from './utils.js'
2
+ import { getNetConfig, isNetworkAddress } from '@libp2p/utils'
3
+ import { multiaddrToIpNet, safelyCloseConnectionIfUnused } from './utils.js'
4
4
  import type { IpNet } from '@chainsafe/netmask'
5
5
  import type { Libp2pEvents, Logger, ComponentLogger, PeerStore, Connection } from '@libp2p/interface'
6
6
  import type { ConnectionManager } from '@libp2p/interface-internal'
@@ -103,7 +103,12 @@ export class ConnectionPruner {
103
103
  this.log('too many connections open - closing a connection to %p', connection.remotePeer)
104
104
  // check allow list
105
105
  const connectionInAllowList = this.allow.some((ipNet) => {
106
- return ipNet.contains(connection.remoteAddr.nodeAddress().address)
106
+ if (isNetworkAddress(connection.remoteAddr)) {
107
+ const config = getNetConfig(connection.remoteAddr)
108
+ return ipNet.contains(config.host)
109
+ }
110
+
111
+ return true
107
112
  })
108
113
 
109
114
  // Connections in the allow list should be excluded from pruning
@@ -3,6 +3,11 @@
3
3
  */
4
4
  export const DIAL_TIMEOUT = 10_000
5
5
 
6
+ /**
7
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#connectionCloseTimeout
8
+ */
9
+ export const CONNECTION_CLOSE_TIMEOUT = 1_000
10
+
6
11
  /**
7
12
  * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#inboundUpgradeTimeout
8
13
  */
@@ -1,8 +1,8 @@
1
1
  /* eslint-disable max-depth */
2
2
  import { TimeoutError, DialError, AbortError } from '@libp2p/interface'
3
3
  import { PeerMap } from '@libp2p/peer-collections'
4
- import { PriorityQueue } from '@libp2p/utils/priority-queue'
5
- import { multiaddr } from '@multiformats/multiaddr'
4
+ import { PriorityQueue } from '@libp2p/utils'
5
+ import { CODE_P2P, multiaddr } from '@multiformats/multiaddr'
6
6
  import { Circuit } from '@multiformats/multiaddr-matcher'
7
7
  import { anySignal } from 'any-signal'
8
8
  import { setMaxListeners } from 'main-event'
@@ -20,10 +20,11 @@ import {
20
20
  LAST_DIAL_SUCCESS_KEY
21
21
  } from './constants.js'
22
22
  import { resolveMultiaddr, dnsaddrResolver } from './resolvers/index.js'
23
+ import { findExistingConnection } from './utils.ts'
23
24
  import { DEFAULT_DIAL_PRIORITY } from './index.js'
24
25
  import type { AddressSorter, ComponentLogger, Logger, Connection, ConnectionGater, Metrics, PeerId, Address, PeerStore, PeerRouting, IsDialableOptions, OpenConnectionProgressEvents, MultiaddrResolver } from '@libp2p/interface'
25
26
  import type { OpenConnectionOptions, TransportManager } from '@libp2p/interface-internal'
26
- import type { PriorityQueueJobOptions } from '@libp2p/utils/priority-queue'
27
+ import type { PriorityQueueJobOptions } from '@libp2p/utils'
27
28
  import type { DNS } from '@multiformats/dns'
28
29
  import type { Multiaddr } from '@multiformats/multiaddr'
29
30
  import type { ProgressOptions } from 'progress-events'
@@ -101,9 +102,9 @@ export class DialQueue {
101
102
  metrics: components.metrics
102
103
  })
103
104
  // a started job errored
104
- this.queue.addEventListener('error', (event) => {
105
- if (event.detail?.name !== AbortError.name) {
106
- this.log.error('error in dial queue - %e', event.detail)
105
+ this.queue.addEventListener('failure', (event) => {
106
+ if (event.detail?.error.name !== AbortError.name) {
107
+ this.log.error('error in dial queue - %e', event.detail.error)
107
108
  }
108
109
  })
109
110
  }
@@ -136,30 +137,14 @@ export class DialQueue {
136
137
  async dial (peerIdOrMultiaddr: PeerId | Multiaddr | Multiaddr[], options: OpenConnectionOptions = {}): Promise<Connection> {
137
138
  const { peerId, multiaddrs } = getPeerAddress(peerIdOrMultiaddr)
138
139
 
139
- // make sure we don't have an existing non-limited connection to any of the
140
- // addresses we are about to dial
141
- const existingConnection = Array.from(this.connections.values()).flat().find(conn => {
142
- if (options.force === true) {
143
- return false
144
- }
145
-
146
- if (conn.limits != null) {
147
- return false
148
- }
140
+ if (peerId != null && options.force !== true) {
141
+ const existingConnection = findExistingConnection(peerId, this.connections.get(peerId), multiaddrs)
149
142
 
150
- if (conn.remotePeer.equals(peerId)) {
151
- return true
143
+ if (existingConnection != null) {
144
+ this.log('already connected to %a', existingConnection.remoteAddr)
145
+ options.onProgress?.(new CustomProgressEvent('dial-queue:already-connected'))
146
+ return existingConnection
152
147
  }
153
-
154
- return multiaddrs.find(addr => {
155
- return addr.equals(conn.remoteAddr)
156
- })
157
- })
158
-
159
- if (existingConnection?.status === 'open') {
160
- this.log('already connected to %a', existingConnection.remoteAddr)
161
- options.onProgress?.(new CustomProgressEvent('dial-queue:already-connected'))
162
- return existingConnection
163
148
  }
164
149
 
165
150
  // ready to dial, all async work finished - make sure we don't have any
@@ -461,7 +446,7 @@ export class DialQueue {
461
446
  // if the resolved multiaddr has a PeerID but it's the wrong one, ignore it
462
447
  // - this can happen with addresses like bootstrap.libp2p.io that resolve
463
448
  // to multiple different peers
464
- const addrPeerId = addr.multiaddr.getPeerId()
449
+ const addrPeerId = addr.multiaddr.getComponents().findLast(c => c.code === CODE_P2P)?.value
465
450
  if (peerId != null && addrPeerId != null) {
466
451
  return peerId.equals(addrPeerId)
467
452
  }
@@ -1,7 +1,8 @@
1
1
  import { ConnectionClosedError, InvalidMultiaddrError, InvalidParametersError, InvalidPeerIdError, NotStartedError, start, stop } from '@libp2p/interface'
2
2
  import { PeerMap } from '@libp2p/peer-collections'
3
- import { RateLimiter } from '@libp2p/utils/rate-limiter'
3
+ import { getNetConfig, isNetworkAddress, RateLimiter } from '@libp2p/utils'
4
4
  import { multiaddr } from '@multiformats/multiaddr'
5
+ import { pEvent } from 'p-event'
5
6
  import { CustomProgressEvent } from 'progress-events'
6
7
  import { getPeerAddress } from '../get-peer.js'
7
8
  import { ConnectionPruner } from './connection-pruner.js'
@@ -9,11 +10,11 @@ import { DIAL_TIMEOUT, INBOUND_CONNECTION_THRESHOLD, MAX_CONNECTIONS, MAX_DIAL_Q
9
10
  import { DialQueue } from './dial-queue.js'
10
11
  import { ReconnectQueue } from './reconnect-queue.js'
11
12
  import { dnsaddrResolver } from './resolvers/index.ts'
12
- import { multiaddrToIpNet } from './utils.js'
13
+ import { findExistingConnection, multiaddrToIpNet } from './utils.js'
13
14
  import type { IpNet } from '@chainsafe/netmask'
14
- import type { PendingDial, AddressSorter, Libp2pEvents, AbortOptions, ComponentLogger, Logger, Connection, MultiaddrConnection, ConnectionGater, Metrics, PeerId, PeerStore, Startable, PendingDialStatus, PeerRouting, IsDialableOptions, MultiaddrResolver } from '@libp2p/interface'
15
+ import type { PendingDial, AddressSorter, Libp2pEvents, AbortOptions, ComponentLogger, Logger, Connection, MultiaddrConnection, ConnectionGater, Metrics, PeerId, PeerStore, Startable, PendingDialStatus, PeerRouting, IsDialableOptions, MultiaddrResolver, Stream, NewStreamOptions } from '@libp2p/interface'
15
16
  import type { ConnectionManager, OpenConnectionOptions, TransportManager } from '@libp2p/interface-internal'
16
- import type { JobStatus } from '@libp2p/utils/queue'
17
+ import type { JobStatus } from '@libp2p/utils'
17
18
  import type { Multiaddr } from '@multiformats/multiaddr'
18
19
  import type { TypedEventTarget } from 'main-event'
19
20
 
@@ -65,6 +66,14 @@ export interface ConnectionManagerInit {
65
66
  */
66
67
  dialTimeout?: number
67
68
 
69
+ /**
70
+ * How many ms to wait when closing a connection if an abort signal is not
71
+ * passed
72
+ *
73
+ * @default 1_000
74
+ */
75
+ connectionCloseTimeout?: number
76
+
68
77
  /**
69
78
  * When a new incoming connection is opened, the upgrade process (e.g.
70
79
  * protect, encrypt, multiplex etc) must complete within this number of ms.
@@ -241,8 +250,8 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
241
250
  this.onDisconnect = this.onDisconnect.bind(this)
242
251
 
243
252
  // allow/deny lists
244
- this.allow = (init.allow ?? []).map(str => multiaddrToIpNet(str))
245
- this.deny = (init.deny ?? []).map(str => multiaddrToIpNet(str))
253
+ this.allow = (init.allow ?? []).map(str => multiaddrToIpNet(multiaddr(str)))
254
+ this.deny = (init.deny ?? []).map(str => multiaddrToIpNet(multiaddr(str)))
246
255
 
247
256
  this.incomingPendingConnections = 0
248
257
  this.maxIncomingPendingConnections = init.maxIncomingPendingConnections ?? defaultOptions.maxIncomingPendingConnections
@@ -399,16 +408,22 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
399
408
  )
400
409
 
401
410
  // Close all connections we're tracking
402
- const tasks: Array<Promise<void>> = []
411
+ const tasks: Array<Promise<any>> = []
403
412
  for (const connectionList of this.connections.values()) {
404
413
  for (const connection of connectionList) {
405
- tasks.push((async () => {
406
- try {
407
- await connection.close()
408
- } catch (err) {
409
- this.log.error(err)
410
- }
411
- })())
414
+ tasks.push(
415
+ Promise.all([
416
+ pEvent(connection, 'close', {
417
+ signal: AbortSignal.timeout(500)
418
+ }),
419
+ connection.close({
420
+ signal: AbortSignal.timeout(500)
421
+ })
422
+ ])
423
+ .catch(err => {
424
+ connection.abort(err)
425
+ })
426
+ )
412
427
  }
413
428
  }
414
429
 
@@ -500,11 +515,11 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
500
515
 
501
516
  if (filteredPeerConns.length === 0) {
502
517
  // trigger disconnect event if no connections remain
503
- this.log('onDisconnect remove all connections for peer %p', peerId)
518
+ this.log.trace('peer %p disconnected, removing connection map entry', peerId)
504
519
  this.connections.delete(peerId)
505
520
 
506
521
  // broadcast disconnect event
507
- this.events.safeDispatchEvent('peer:disconnect', { detail: connection.remotePeer })
522
+ this.events.safeDispatchEvent('peer:disconnect', { detail: peerId })
508
523
  }
509
524
  }
510
525
 
@@ -536,7 +551,7 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
536
551
  try {
537
552
  options.signal?.throwIfAborted()
538
553
 
539
- const { peerId } = getPeerAddress(peerIdOrMultiaddr)
554
+ const { peerId, multiaddrs } = getPeerAddress(peerIdOrMultiaddr)
540
555
 
541
556
  if (this.peerId.equals(peerId)) {
542
557
  throw new InvalidPeerIdError('Can not dial self')
@@ -544,11 +559,10 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
544
559
 
545
560
  if (peerId != null && options.force !== true) {
546
561
  this.log('dial %p', peerId)
547
- const existingConnection = this.getConnections(peerId)
548
- .find(conn => conn.limits == null)
562
+ const existingConnection = findExistingConnection(peerId, this.getConnections(peerId), multiaddrs)
549
563
 
550
564
  if (existingConnection != null) {
551
- this.log('had an existing non-limited connection to %p', peerId)
565
+ this.log('had an existing connection to %p as %a', peerId, existingConnection.remoteAddr)
552
566
 
553
567
  options.onProgress?.(new CustomProgressEvent('dial-queue:already-connected'))
554
568
  return existingConnection
@@ -600,13 +614,22 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
600
614
  }
601
615
  }
602
616
 
617
+ async openStream (peerIdOrMultiaddr: PeerId | Multiaddr | Multiaddr[], protocol: string | string[], options: OpenConnectionOptions & NewStreamOptions = {}): Promise<Stream> {
618
+ const connection = await this.openConnection(peerIdOrMultiaddr, options)
619
+
620
+ return connection.newStream(protocol, options)
621
+ }
622
+
603
623
  async closeConnections (peerId: PeerId, options: AbortOptions = {}): Promise<void> {
604
624
  const connections = this.connections.get(peerId) ?? []
605
625
 
606
626
  await Promise.all(
607
627
  connections.map(async connection => {
608
628
  try {
609
- await connection.close(options)
629
+ await Promise.all([
630
+ pEvent(connection, 'close', options),
631
+ connection.close(options)
632
+ ])
610
633
  } catch (err: any) {
611
634
  connection.abort(err)
612
635
  }
@@ -614,10 +637,15 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
614
637
  )
615
638
  }
616
639
 
617
- async acceptIncomingConnection (maConn: MultiaddrConnection): Promise<boolean> {
640
+ acceptIncomingConnection (maConn: MultiaddrConnection): boolean {
618
641
  // check deny list
619
- const denyConnection = this.deny.some(ma => {
620
- return ma.contains(maConn.remoteAddr.nodeAddress().address)
642
+ const denyConnection = this.deny.some(ipNet => {
643
+ if (isNetworkAddress(maConn.remoteAddr)) {
644
+ const config = getNetConfig(maConn.remoteAddr)
645
+ return ipNet.contains(config.host)
646
+ }
647
+
648
+ return false
621
649
  })
622
650
 
623
651
  if (denyConnection) {
@@ -627,7 +655,12 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
627
655
 
628
656
  // check allow list
629
657
  const allowConnection = this.allow.some(ipNet => {
630
- return ipNet.contains(maConn.remoteAddr.nodeAddress().address)
658
+ if (isNetworkAddress(maConn.remoteAddr)) {
659
+ const config = getNetConfig(maConn.remoteAddr)
660
+ return ipNet.contains(config.host)
661
+ }
662
+
663
+ return true
631
664
  })
632
665
 
633
666
  if (allowConnection) {
@@ -642,13 +675,13 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
642
675
  return false
643
676
  }
644
677
 
645
- if (maConn.remoteAddr.isThinWaistAddress()) {
646
- const host = maConn.remoteAddr.nodeAddress().address
678
+ if (isNetworkAddress(maConn.remoteAddr)) {
679
+ const config = getNetConfig(maConn.remoteAddr)
647
680
 
648
681
  try {
649
- await this.inboundConnectionRateLimiter.consume(host, 1)
682
+ this.inboundConnectionRateLimiter.consume(config.host, 1)
650
683
  } catch {
651
- this.log('connection from %a refused - inboundConnectionThreshold exceeded by host %s', maConn.remoteAddr, host)
684
+ this.log('connection from %a refused - inboundConnectionThreshold exceeded by host %s', maConn.remoteAddr, config.host)
652
685
  return false
653
686
  }
654
687
  }
@@ -1,5 +1,5 @@
1
1
  import { KEEP_ALIVE } from '@libp2p/interface'
2
- import { PeerQueue } from '@libp2p/utils/peer-queue'
2
+ import { PeerQueue } from '@libp2p/utils'
3
3
  import pRetry from 'p-retry'
4
4
  import { MAX_PARALLEL_RECONNECTS } from './constants.js'
5
5
  import type { ComponentLogger, Libp2pEvents, Logger, Metrics, Peer, PeerId, PeerStore, Startable } from '@libp2p/interface'