libp2p 2.10.0 → 3.0.0-049bfa0fa
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.
- package/README.md +39 -37
- package/dist/index.min.js +14 -17
- package/dist/index.min.js.map +4 -4
- package/dist/src/address-manager/dns-mappings.d.ts +1 -2
- package/dist/src/address-manager/dns-mappings.d.ts.map +1 -1
- package/dist/src/address-manager/dns-mappings.js +39 -43
- package/dist/src/address-manager/dns-mappings.js.map +1 -1
- package/dist/src/address-manager/index.d.ts.map +1 -1
- package/dist/src/address-manager/index.js +31 -14
- package/dist/src/address-manager/index.js.map +1 -1
- package/dist/src/address-manager/ip-mappings.d.ts +1 -0
- package/dist/src/address-manager/ip-mappings.d.ts.map +1 -1
- package/dist/src/address-manager/ip-mappings.js +51 -40
- package/dist/src/address-manager/ip-mappings.js.map +1 -1
- package/dist/src/address-manager/observed-addresses.d.ts.map +1 -1
- package/dist/src/address-manager/observed-addresses.js +1 -3
- package/dist/src/address-manager/observed-addresses.js.map +1 -1
- package/dist/src/address-manager/transport-addresses.d.ts.map +1 -1
- package/dist/src/address-manager/transport-addresses.js +6 -8
- package/dist/src/address-manager/transport-addresses.js.map +1 -1
- package/dist/src/config/connection-gater.browser.d.ts.map +1 -1
- package/dist/src/config/connection-gater.browser.js +8 -22
- package/dist/src/config/connection-gater.browser.js.map +1 -1
- package/dist/src/config/connection-gater.d.ts.map +1 -1
- package/dist/src/config/connection-gater.js +1 -12
- package/dist/src/config/connection-gater.js.map +1 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +3 -22
- package/dist/src/config.js.map +1 -1
- package/dist/src/connection-manager/address-sorter.d.ts.map +1 -1
- package/dist/src/connection-manager/address-sorter.js +1 -2
- package/dist/src/connection-manager/address-sorter.js.map +1 -1
- package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -1
- package/dist/src/connection-manager/connection-pruner.js +7 -3
- package/dist/src/connection-manager/connection-pruner.js.map +1 -1
- package/dist/src/connection-manager/constants.defaults.d.ts +4 -0
- package/dist/src/connection-manager/constants.defaults.d.ts.map +1 -1
- package/dist/src/connection-manager/constants.defaults.js +4 -0
- package/dist/src/connection-manager/constants.defaults.js.map +1 -1
- package/dist/src/connection-manager/dial-queue.d.ts +2 -2
- package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
- package/dist/src/connection-manager/dial-queue.js +11 -23
- package/dist/src/connection-manager/dial-queue.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +10 -18
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +44 -26
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/connection-manager/reconnect-queue.js +1 -1
- package/dist/src/connection-manager/reconnect-queue.js.map +1 -1
- package/dist/src/connection-manager/utils.d.ts +31 -3
- package/dist/src/connection-manager/utils.d.ts.map +1 -1
- package/dist/src/connection-manager/utils.js +99 -18
- package/dist/src/connection-manager/utils.js.map +1 -1
- package/dist/src/connection-monitor.d.ts +1 -1
- package/dist/src/connection-monitor.d.ts.map +1 -1
- package/dist/src/connection-monitor.js +2 -3
- package/dist/src/connection-monitor.js.map +1 -1
- package/dist/src/connection.d.ts +14 -9
- package/dist/src/connection.d.ts.map +1 -1
- package/dist/src/connection.js +118 -139
- package/dist/src/connection.js.map +1 -1
- package/dist/src/get-peer.js +3 -3
- package/dist/src/get-peer.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +2 -2
- package/dist/src/libp2p.d.ts +3 -1
- package/dist/src/libp2p.d.ts.map +1 -1
- package/dist/src/libp2p.js +13 -7
- package/dist/src/libp2p.js.map +1 -1
- package/dist/src/peer-routing.js +1 -1
- package/dist/src/peer-routing.js.map +1 -1
- package/dist/src/random-walk.d.ts.map +1 -1
- package/dist/src/random-walk.js +13 -3
- package/dist/src/random-walk.js.map +1 -1
- package/dist/src/registrar.d.ts +8 -4
- package/dist/src/registrar.d.ts.map +1 -1
- package/dist/src/registrar.js +66 -46
- package/dist/src/registrar.js.map +1 -1
- package/dist/src/transport-manager.js +15 -2
- package/dist/src/transport-manager.js.map +1 -1
- package/dist/src/upgrader.d.ts +26 -16
- package/dist/src/upgrader.d.ts.map +1 -1
- package/dist/src/upgrader.js +88 -122
- package/dist/src/upgrader.js.map +1 -1
- package/dist/src/utils.d.ts +3 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +25 -0
- package/dist/src/utils.js.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.d.ts.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/package.json +27 -30
- package/src/address-manager/dns-mappings.ts +50 -50
- package/src/address-manager/index.ts +37 -17
- package/src/address-manager/ip-mappings.ts +64 -44
- package/src/address-manager/observed-addresses.ts +1 -3
- package/src/address-manager/transport-addresses.ts +7 -9
- package/src/config/connection-gater.browser.ts +8 -24
- package/src/config/connection-gater.ts +1 -12
- package/src/config.ts +3 -25
- package/src/connection-manager/address-sorter.ts +1 -2
- package/src/connection-manager/connection-pruner.ts +8 -3
- package/src/connection-manager/constants.defaults.ts +5 -0
- package/src/connection-manager/dial-queue.ts +12 -27
- package/src/connection-manager/index.ts +60 -45
- package/src/connection-manager/reconnect-queue.ts +1 -1
- package/src/connection-manager/utils.ts +129 -21
- package/src/connection-monitor.ts +3 -4
- package/src/connection.ts +142 -179
- package/src/get-peer.ts +3 -3
- package/src/index.ts +2 -2
- package/src/libp2p.ts +16 -9
- package/src/peer-routing.ts +1 -1
- package/src/random-walk.ts +13 -3
- package/src/registrar.ts +87 -61
- package/src/transport-manager.ts +18 -2
- package/src/upgrader.ts +132 -149
- package/src/utils.ts +31 -0
- package/src/version.ts +1 -1
- package/dist/typedoc-urls.json +0 -24
|
@@ -4,16 +4,5 @@ import type { ConnectionGater } from '@libp2p/interface'
|
|
|
4
4
|
* Returns a default connection gater implementation that allows everything
|
|
5
5
|
*/
|
|
6
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
|
-
}
|
|
7
|
+
return gater
|
|
19
8
|
}
|
package/src/config.ts
CHANGED
|
@@ -1,33 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { mergeOptions } from '@libp2p/utils/merge-options'
|
|
3
|
-
import { dnsaddrResolver } from './connection-manager/resolvers/dnsaddr.ts'
|
|
1
|
+
import { InvalidParametersError } from '@libp2p/interface'
|
|
4
2
|
import type { Libp2pInit } from './index.js'
|
|
5
3
|
import type { ServiceMap } from '@libp2p/interface'
|
|
6
|
-
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
7
|
-
|
|
8
|
-
const DefaultConfig: Libp2pInit = {
|
|
9
|
-
addresses: {
|
|
10
|
-
listen: [],
|
|
11
|
-
announce: [],
|
|
12
|
-
noAnnounce: [],
|
|
13
|
-
announceFilter: (multiaddrs: Multiaddr[]) => multiaddrs
|
|
14
|
-
},
|
|
15
|
-
connectionManager: {
|
|
16
|
-
resolvers: {
|
|
17
|
-
dnsaddr: dnsaddrResolver
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
transportManager: {
|
|
21
|
-
faultTolerance: FaultTolerance.FATAL_ALL
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
4
|
|
|
25
5
|
export async function validateConfig <T extends ServiceMap = Record<string, unknown>> (opts: Libp2pInit<T>): Promise<Libp2pInit<T>> {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (resultingOptions.connectionProtector === null && globalThis.process?.env?.LIBP2P_FORCE_PNET != null) {
|
|
6
|
+
if (opts.connectionProtector === null && globalThis.process?.env?.LIBP2P_FORCE_PNET != null) {
|
|
29
7
|
throw new InvalidParametersError('Private network is enforced, but no protector was provided')
|
|
30
8
|
}
|
|
31
9
|
|
|
32
|
-
return
|
|
10
|
+
return opts
|
|
33
11
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { isLoopback } from '@libp2p/utils
|
|
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 {
|
|
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
|
-
|
|
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
|
|
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
|
|
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'
|
|
@@ -103,7 +104,7 @@ export class DialQueue {
|
|
|
103
104
|
// a started job errored
|
|
104
105
|
this.queue.addEventListener('failure', (event) => {
|
|
105
106
|
if (event.detail?.error.name !== AbortError.name) {
|
|
106
|
-
this.log.error('error in dial queue - %e', event.detail)
|
|
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
|
-
|
|
140
|
-
|
|
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 (
|
|
151
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
|
@@ -66,30 +67,20 @@ export interface ConnectionManagerInit {
|
|
|
66
67
|
dialTimeout?: number
|
|
67
68
|
|
|
68
69
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
70
|
+
* How many ms to wait when closing a connection if an abort signal is not
|
|
71
|
+
* passed
|
|
71
72
|
*
|
|
72
|
-
* @default
|
|
73
|
+
* @default 1_000
|
|
73
74
|
*/
|
|
74
|
-
|
|
75
|
+
connectionCloseTimeout?: number
|
|
75
76
|
|
|
76
77
|
/**
|
|
77
|
-
* When a new
|
|
78
|
+
* When a new incoming connection is opened, the upgrade process (e.g.
|
|
78
79
|
* protect, encrypt, multiplex etc) must complete within this number of ms.
|
|
79
80
|
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* @deprecated This is handled by `dialTimeout`
|
|
83
|
-
*/
|
|
84
|
-
outboundUpgradeTimeout?: number
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Protocol negotiation must complete within this number of ms
|
|
88
|
-
*
|
|
89
|
-
* @default 2000
|
|
90
|
-
* @deprecated use outboundStreamProtocolNegotiationTimeout or inboundStreamProtocolNegotiationTimeout instead
|
|
81
|
+
* @default 10_000
|
|
91
82
|
*/
|
|
92
|
-
|
|
83
|
+
inboundUpgradeTimeout?: number
|
|
93
84
|
|
|
94
85
|
/**
|
|
95
86
|
* Outbound protocol negotiation must complete within this number of ms.
|
|
@@ -241,8 +232,8 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
|
|
|
241
232
|
this.onDisconnect = this.onDisconnect.bind(this)
|
|
242
233
|
|
|
243
234
|
// allow/deny lists
|
|
244
|
-
this.allow = (init.allow ?? []).map(str => multiaddrToIpNet(str))
|
|
245
|
-
this.deny = (init.deny ?? []).map(str => multiaddrToIpNet(str))
|
|
235
|
+
this.allow = (init.allow ?? []).map(str => multiaddrToIpNet(multiaddr(str)))
|
|
236
|
+
this.deny = (init.deny ?? []).map(str => multiaddrToIpNet(multiaddr(str)))
|
|
246
237
|
|
|
247
238
|
this.incomingPendingConnections = 0
|
|
248
239
|
this.maxIncomingPendingConnections = init.maxIncomingPendingConnections ?? defaultOptions.maxIncomingPendingConnections
|
|
@@ -399,16 +390,22 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
|
|
|
399
390
|
)
|
|
400
391
|
|
|
401
392
|
// Close all connections we're tracking
|
|
402
|
-
const tasks: Array<Promise<
|
|
393
|
+
const tasks: Array<Promise<any>> = []
|
|
403
394
|
for (const connectionList of this.connections.values()) {
|
|
404
395
|
for (const connection of connectionList) {
|
|
405
|
-
tasks.push(
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
396
|
+
tasks.push(
|
|
397
|
+
Promise.all([
|
|
398
|
+
pEvent(connection, 'close', {
|
|
399
|
+
signal: AbortSignal.timeout(500)
|
|
400
|
+
}),
|
|
401
|
+
connection.close({
|
|
402
|
+
signal: AbortSignal.timeout(500)
|
|
403
|
+
})
|
|
404
|
+
])
|
|
405
|
+
.catch(err => {
|
|
406
|
+
connection.abort(err)
|
|
407
|
+
})
|
|
408
|
+
)
|
|
412
409
|
}
|
|
413
410
|
}
|
|
414
411
|
|
|
@@ -504,7 +501,7 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
|
|
|
504
501
|
this.connections.delete(peerId)
|
|
505
502
|
|
|
506
503
|
// broadcast disconnect event
|
|
507
|
-
this.events.safeDispatchEvent('peer:disconnect', { detail:
|
|
504
|
+
this.events.safeDispatchEvent('peer:disconnect', { detail: peerId })
|
|
508
505
|
}
|
|
509
506
|
}
|
|
510
507
|
|
|
@@ -536,7 +533,7 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
|
|
|
536
533
|
try {
|
|
537
534
|
options.signal?.throwIfAborted()
|
|
538
535
|
|
|
539
|
-
const { peerId } = getPeerAddress(peerIdOrMultiaddr)
|
|
536
|
+
const { peerId, multiaddrs } = getPeerAddress(peerIdOrMultiaddr)
|
|
540
537
|
|
|
541
538
|
if (this.peerId.equals(peerId)) {
|
|
542
539
|
throw new InvalidPeerIdError('Can not dial self')
|
|
@@ -544,11 +541,10 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
|
|
|
544
541
|
|
|
545
542
|
if (peerId != null && options.force !== true) {
|
|
546
543
|
this.log('dial %p', peerId)
|
|
547
|
-
const existingConnection = this.getConnections(peerId)
|
|
548
|
-
.find(conn => conn.limits == null)
|
|
544
|
+
const existingConnection = findExistingConnection(peerId, this.getConnections(peerId), multiaddrs)
|
|
549
545
|
|
|
550
546
|
if (existingConnection != null) {
|
|
551
|
-
this.log('had an existing
|
|
547
|
+
this.log('had an existing connection to %p as %a', peerId, existingConnection.remoteAddr)
|
|
552
548
|
|
|
553
549
|
options.onProgress?.(new CustomProgressEvent('dial-queue:already-connected'))
|
|
554
550
|
return existingConnection
|
|
@@ -600,13 +596,22 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
|
|
|
600
596
|
}
|
|
601
597
|
}
|
|
602
598
|
|
|
599
|
+
async openStream (peerIdOrMultiaddr: PeerId | Multiaddr | Multiaddr[], protocol: string | string[], options: OpenConnectionOptions & NewStreamOptions = {}): Promise<Stream> {
|
|
600
|
+
const connection = await this.openConnection(peerIdOrMultiaddr, options)
|
|
601
|
+
|
|
602
|
+
return connection.newStream(protocol, options)
|
|
603
|
+
}
|
|
604
|
+
|
|
603
605
|
async closeConnections (peerId: PeerId, options: AbortOptions = {}): Promise<void> {
|
|
604
606
|
const connections = this.connections.get(peerId) ?? []
|
|
605
607
|
|
|
606
608
|
await Promise.all(
|
|
607
609
|
connections.map(async connection => {
|
|
608
610
|
try {
|
|
609
|
-
await
|
|
611
|
+
await Promise.all([
|
|
612
|
+
pEvent(connection, 'close', options),
|
|
613
|
+
connection.close(options)
|
|
614
|
+
])
|
|
610
615
|
} catch (err: any) {
|
|
611
616
|
connection.abort(err)
|
|
612
617
|
}
|
|
@@ -614,10 +619,15 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
|
|
|
614
619
|
)
|
|
615
620
|
}
|
|
616
621
|
|
|
617
|
-
|
|
622
|
+
acceptIncomingConnection (maConn: MultiaddrConnection): boolean {
|
|
618
623
|
// check deny list
|
|
619
|
-
const denyConnection = this.deny.some(
|
|
620
|
-
|
|
624
|
+
const denyConnection = this.deny.some(ipNet => {
|
|
625
|
+
if (isNetworkAddress(maConn.remoteAddr)) {
|
|
626
|
+
const config = getNetConfig(maConn.remoteAddr)
|
|
627
|
+
return ipNet.contains(config.host)
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
return false
|
|
621
631
|
})
|
|
622
632
|
|
|
623
633
|
if (denyConnection) {
|
|
@@ -627,7 +637,12 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
|
|
|
627
637
|
|
|
628
638
|
// check allow list
|
|
629
639
|
const allowConnection = this.allow.some(ipNet => {
|
|
630
|
-
|
|
640
|
+
if (isNetworkAddress(maConn.remoteAddr)) {
|
|
641
|
+
const config = getNetConfig(maConn.remoteAddr)
|
|
642
|
+
return ipNet.contains(config.host)
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
return true
|
|
631
646
|
})
|
|
632
647
|
|
|
633
648
|
if (allowConnection) {
|
|
@@ -642,13 +657,13 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
|
|
|
642
657
|
return false
|
|
643
658
|
}
|
|
644
659
|
|
|
645
|
-
if (maConn.remoteAddr
|
|
646
|
-
const
|
|
660
|
+
if (isNetworkAddress(maConn.remoteAddr)) {
|
|
661
|
+
const config = getNetConfig(maConn.remoteAddr)
|
|
647
662
|
|
|
648
663
|
try {
|
|
649
|
-
|
|
664
|
+
this.inboundConnectionRateLimiter.consume(config.host, 1)
|
|
650
665
|
} catch {
|
|
651
|
-
this.log('connection from %a refused - inboundConnectionThreshold exceeded by host %s', maConn.remoteAddr, host)
|
|
666
|
+
this.log('connection from %a refused - inboundConnectionThreshold exceeded by host %s', maConn.remoteAddr, config.host)
|
|
652
667
|
return false
|
|
653
668
|
}
|
|
654
669
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KEEP_ALIVE } from '@libp2p/interface'
|
|
2
|
-
import { PeerQueue } from '@libp2p/utils
|
|
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'
|
|
@@ -1,38 +1,146 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import { IpNet } from '@chainsafe/netmask'
|
|
2
|
+
import { InvalidParametersError } from '@libp2p/interface'
|
|
3
|
+
import { getNetConfig } from '@libp2p/utils'
|
|
4
|
+
import { Circuit } from '@multiformats/multiaddr-matcher'
|
|
5
|
+
import type { Connection, AbortOptions, PeerId } from '@libp2p/interface'
|
|
4
6
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
5
7
|
|
|
8
|
+
/**
|
|
9
|
+
* These are speculative protocols that are run automatically on connection open
|
|
10
|
+
* so are usually not the reason the connection was opened.
|
|
11
|
+
*
|
|
12
|
+
* Consequently when requested it should be safe to close connections that only
|
|
13
|
+
* have these protocol streams open.
|
|
14
|
+
*/
|
|
15
|
+
const DEFAULT_CLOSABLE_PROTOCOLS = [
|
|
16
|
+
// identify
|
|
17
|
+
'/ipfs/id/1.0.0',
|
|
18
|
+
|
|
19
|
+
// identify-push
|
|
20
|
+
'/ipfs/id/push/1.0.0',
|
|
21
|
+
|
|
22
|
+
// autonat
|
|
23
|
+
'/libp2p/autonat/1.0.0',
|
|
24
|
+
|
|
25
|
+
// dcutr
|
|
26
|
+
'/libp2p/dcutr'
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
export interface SafelyCloseConnectionOptions extends AbortOptions {
|
|
30
|
+
/**
|
|
31
|
+
* Only close the stream if it either has no protocol streams open or only
|
|
32
|
+
* ones in this list.
|
|
33
|
+
*
|
|
34
|
+
* @default ['/ipfs/id/1.0.0']
|
|
35
|
+
*/
|
|
36
|
+
closableProtocols?: string[]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Close the passed connection if it has no streams, or only closable protocol
|
|
41
|
+
* streams, falling back to aborting the connection if closing it cleanly fails.
|
|
42
|
+
*/
|
|
43
|
+
export async function safelyCloseConnectionIfUnused (connection?: Connection, options?: SafelyCloseConnectionOptions): Promise<void> {
|
|
44
|
+
const streamProtocols = connection?.streams?.map(stream => stream.protocol) ?? []
|
|
45
|
+
const closableProtocols = options?.closableProtocols ?? DEFAULT_CLOSABLE_PROTOCOLS
|
|
46
|
+
|
|
47
|
+
// if the connection has protocols not in the closable protocols list, do not
|
|
48
|
+
// close the connection
|
|
49
|
+
if (streamProtocols.filter(proto => proto != null && !closableProtocols.includes(proto)).length > 0) {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
await connection?.close(options)
|
|
55
|
+
} catch (err: any) {
|
|
56
|
+
connection?.abort(err)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
6
60
|
/**
|
|
7
61
|
* Converts a multiaddr string or object to an IpNet object.
|
|
8
62
|
* If the multiaddr doesn't include /ipcidr, it will encapsulate with the appropriate CIDR:
|
|
9
63
|
* - /ipcidr/32 for IPv4
|
|
10
64
|
* - /ipcidr/128 for IPv6
|
|
11
65
|
*
|
|
12
|
-
* @param {string | Multiaddr} ma - The multiaddr
|
|
66
|
+
* @param {string | Multiaddr} ma - The multiaddr object to convert.
|
|
13
67
|
* @returns {IpNet} The converted IpNet object.
|
|
14
68
|
* @throws {Error} Throws an error if the multiaddr is not valid.
|
|
15
69
|
*/
|
|
16
|
-
export function multiaddrToIpNet (ma:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (typeof ma === 'string') {
|
|
20
|
-
parsedMa = multiaddr(ma)
|
|
21
|
-
} else {
|
|
22
|
-
parsedMa = ma
|
|
23
|
-
}
|
|
70
|
+
export function multiaddrToIpNet (ma: Multiaddr): IpNet {
|
|
71
|
+
const config = getNetConfig(ma)
|
|
72
|
+
let mask = config.cidr
|
|
24
73
|
|
|
25
|
-
|
|
74
|
+
if (config.type !== 'ip4' && config.type !== 'ip6') {
|
|
75
|
+
throw new InvalidParametersError(`Multiaddr ${ma} was not an IPv4 or IPv6 address`)
|
|
76
|
+
}
|
|
26
77
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
78
|
+
// Check if /ipcidr is already present
|
|
79
|
+
if (mask == null) {
|
|
80
|
+
switch (config.type) {
|
|
81
|
+
case 'ip4': {
|
|
82
|
+
mask = 32
|
|
83
|
+
break
|
|
84
|
+
}
|
|
85
|
+
case 'ip6': {
|
|
86
|
+
mask = 128
|
|
87
|
+
break
|
|
88
|
+
}
|
|
89
|
+
default: {
|
|
90
|
+
throw new InvalidParametersError(`Multiaddr ${ma} was not an IPv4 or IPv6 address`)
|
|
91
|
+
}
|
|
32
92
|
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return new IpNet(config.host, mask)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Returns true if the passed multiaddr would result in a direct connection to
|
|
100
|
+
* the peer.
|
|
101
|
+
*
|
|
102
|
+
* Currently only circuit relay addresses are supported as indirect connections.
|
|
103
|
+
*/
|
|
104
|
+
export function isDirect (ma: Multiaddr): boolean {
|
|
105
|
+
return !Circuit.exactMatch(ma)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* If there is an existing non-limited connection to the remote peer return it,
|
|
110
|
+
* unless it is indirect and at least one of the passed dial addresses would
|
|
111
|
+
* result in a direct connection
|
|
112
|
+
*/
|
|
113
|
+
export function findExistingConnection (peerId?: PeerId, connections?: Connection[], dialAddresses?: Multiaddr[]): Connection | undefined {
|
|
114
|
+
if (peerId == null || connections == null) {
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const existingConnection = connections
|
|
119
|
+
.sort((a, b) => {
|
|
120
|
+
if (a.direct) {
|
|
121
|
+
return -1
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (b.direct) {
|
|
125
|
+
return 1
|
|
126
|
+
}
|
|
33
127
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
128
|
+
return 0
|
|
129
|
+
})
|
|
130
|
+
.find(con => con.limits == null)
|
|
131
|
+
|
|
132
|
+
if (existingConnection == null || existingConnection.direct || dialAddresses == null) {
|
|
133
|
+
return existingConnection
|
|
37
134
|
}
|
|
135
|
+
|
|
136
|
+
// we have an indirect, but unlimited connection - test the dial addresses to
|
|
137
|
+
// see if any of them would result in a direct connection, in which case allow
|
|
138
|
+
// the attempt to upgrade to a direct connection
|
|
139
|
+
const wouldUpgradeToDirect = dialAddresses.some(ma => isDirect(ma))
|
|
140
|
+
|
|
141
|
+
if (wouldUpgradeToDirect) {
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return existingConnection
|
|
38
146
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { randomBytes } from '@libp2p/crypto'
|
|
2
2
|
import { serviceCapabilities } from '@libp2p/interface'
|
|
3
|
-
import { AdaptiveTimeout } from '@libp2p/utils
|
|
4
|
-
import { byteStream } from 'it-byte-stream'
|
|
3
|
+
import { AdaptiveTimeout, byteStream } from '@libp2p/utils'
|
|
5
4
|
import { setMaxListeners } from 'main-event'
|
|
6
5
|
import type { ComponentLogger, Logger, Metrics, Startable } from '@libp2p/interface'
|
|
7
6
|
import type { ConnectionManager } from '@libp2p/interface-internal'
|
|
8
|
-
import type { AdaptiveTimeoutInit } from '@libp2p/utils
|
|
7
|
+
import type { AdaptiveTimeoutInit } from '@libp2p/utils'
|
|
9
8
|
|
|
10
9
|
const DEFAULT_PING_INTERVAL_MS = 10000
|
|
11
10
|
const PROTOCOL_VERSION = '1.0.0'
|
|
@@ -120,7 +119,7 @@ export class ConnectionMonitor implements Startable {
|
|
|
120
119
|
|
|
121
120
|
conn.rtt = Date.now() - start
|
|
122
121
|
|
|
123
|
-
await
|
|
122
|
+
await stream.close({
|
|
124
123
|
signal
|
|
125
124
|
})
|
|
126
125
|
} catch (err: any) {
|