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