libp2p 2.3.1 → 2.4.0-127abe24b
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 +9 -25
- package/dist/index.min.js +18 -15
- package/dist/src/address-manager/dns-mappings.d.ts +20 -0
- package/dist/src/address-manager/dns-mappings.d.ts.map +1 -0
- package/dist/src/address-manager/dns-mappings.js +139 -0
- package/dist/src/address-manager/dns-mappings.js.map +1 -0
- package/dist/src/{address-manager.d.ts → address-manager/index.d.ts} +54 -10
- package/dist/src/address-manager/index.d.ts.map +1 -0
- package/dist/src/address-manager/index.js +264 -0
- package/dist/src/address-manager/index.js.map +1 -0
- package/dist/src/address-manager/ip-mappings.d.ts +18 -0
- package/dist/src/address-manager/ip-mappings.d.ts.map +1 -0
- package/dist/src/address-manager/ip-mappings.js +143 -0
- package/dist/src/address-manager/ip-mappings.js.map +1 -0
- package/dist/src/address-manager/observed-addresses.d.ts +19 -0
- package/dist/src/address-manager/observed-addresses.d.ts.map +1 -0
- package/dist/src/address-manager/observed-addresses.js +70 -0
- package/dist/src/address-manager/observed-addresses.js.map +1 -0
- package/dist/src/address-manager/transport-addresses.d.ts +19 -0
- package/dist/src/address-manager/transport-addresses.d.ts.map +1 -0
- package/dist/src/address-manager/transport-addresses.js +83 -0
- package/dist/src/address-manager/transport-addresses.js.map +1 -0
- package/dist/src/config/connection-gater.browser.d.ts +7 -3
- package/dist/src/config/connection-gater.browser.d.ts.map +1 -1
- package/dist/src/config/connection-gater.browser.js +16 -4
- package/dist/src/config/connection-gater.browser.js.map +1 -1
- package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -1
- package/dist/src/connection-manager/connection-pruner.js +4 -3
- package/dist/src/connection-manager/connection-pruner.js.map +1 -1
- package/dist/src/connection-manager/dial-queue.d.ts +3 -3
- package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
- package/dist/src/connection-manager/dial-queue.js +6 -13
- package/dist/src/connection-manager/dial-queue.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +1 -0
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +10 -6
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/connection-manager/utils.d.ts +13 -1
- package/dist/src/connection-manager/utils.d.ts.map +1 -1
- package/dist/src/connection-manager/utils.js +33 -1
- package/dist/src/connection-manager/utils.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/libp2p.js +1 -1
- package/dist/src/libp2p.js.map +1 -1
- package/dist/src/version.d.ts +2 -2
- package/dist/src/version.d.ts.map +1 -1
- package/dist/src/version.js +2 -2
- package/dist/src/version.js.map +1 -1
- package/package.json +27 -25
- package/src/address-manager/dns-mappings.ts +182 -0
- package/src/address-manager/index.ts +413 -0
- package/src/address-manager/ip-mappings.ts +191 -0
- package/src/address-manager/observed-addresses.ts +94 -0
- package/src/address-manager/transport-addresses.ts +116 -0
- package/src/config/connection-gater.browser.ts +18 -4
- package/src/connection-manager/connection-pruner.ts +6 -4
- package/src/connection-manager/dial-queue.ts +12 -19
- package/src/connection-manager/index.ts +14 -8
- package/src/connection-manager/utils.ts +35 -2
- package/src/index.ts +1 -1
- package/src/libp2p.ts +1 -1
- package/src/version.ts +2 -2
- package/LICENSE +0 -4
- package/dist/src/address-manager.d.ts.map +0 -1
- package/dist/src/address-manager.js +0 -214
- package/dist/src/address-manager.js.map +0 -1
- package/dist/typedoc-urls.json +0 -19
- package/src/address-manager.ts +0 -319
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { isPrivateIp } from '@libp2p/utils/private-ip'
|
|
2
|
+
import { multiaddr, protocols } from '@multiformats/multiaddr'
|
|
3
|
+
import type { AddressManagerComponents, AddressManagerInit } from './index.js'
|
|
4
|
+
import type { Logger } from '@libp2p/interface'
|
|
5
|
+
import type { NodeAddress } from '@libp2p/interface-internal'
|
|
6
|
+
import type { Multiaddr, StringTuple } from '@multiformats/multiaddr'
|
|
7
|
+
|
|
8
|
+
const MAX_DATE = 8_640_000_000_000_000
|
|
9
|
+
|
|
10
|
+
export const defaultValues = {
|
|
11
|
+
maxObservedAddresses: 10
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface DNSMapping {
|
|
15
|
+
domain: string
|
|
16
|
+
verified: boolean
|
|
17
|
+
expires: number
|
|
18
|
+
lastVerified?: number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const CODEC_TLS = 0x01c0
|
|
22
|
+
const CODEC_SNI = 0x01c1
|
|
23
|
+
const CODEC_DNS = 0x35
|
|
24
|
+
const CODEC_DNS4 = 0x36
|
|
25
|
+
const CODEC_DNS6 = 0x37
|
|
26
|
+
const CODEC_DNSADDR = 0x38
|
|
27
|
+
|
|
28
|
+
export class DNSMappings {
|
|
29
|
+
private readonly log: Logger
|
|
30
|
+
private readonly mappings: Map<string, DNSMapping>
|
|
31
|
+
|
|
32
|
+
constructor (components: AddressManagerComponents, init: AddressManagerInit = {}) {
|
|
33
|
+
this.log = components.logger.forComponent('libp2p:address-manager:dns-mappings')
|
|
34
|
+
this.mappings = new Map()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
has (ma: Multiaddr): boolean {
|
|
38
|
+
const host = this.findHost(ma)
|
|
39
|
+
|
|
40
|
+
for (const mapping of this.mappings.values()) {
|
|
41
|
+
if (mapping.domain === host) {
|
|
42
|
+
return true
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
add (domain: string, addresses: string[]): void {
|
|
50
|
+
addresses.forEach(ip => {
|
|
51
|
+
this.log('add DNS mapping %s to %s', ip, domain)
|
|
52
|
+
// we are only confident if this is an local domain mapping, otherwise
|
|
53
|
+
// we will require external validation
|
|
54
|
+
const verified = isPrivateIp(ip) === true
|
|
55
|
+
|
|
56
|
+
this.mappings.set(ip, {
|
|
57
|
+
domain,
|
|
58
|
+
verified,
|
|
59
|
+
expires: verified ? MAX_DATE - Date.now() : 0,
|
|
60
|
+
lastVerified: verified ? MAX_DATE - Date.now() : undefined
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
remove (ma: Multiaddr): boolean {
|
|
66
|
+
const host = this.findHost(ma)
|
|
67
|
+
let wasConfident = false
|
|
68
|
+
|
|
69
|
+
for (const [ip, mapping] of this.mappings.entries()) {
|
|
70
|
+
if (mapping.domain === host) {
|
|
71
|
+
this.log('removing %s to %s DNS mapping %e', ip, mapping.domain, new Error('where'))
|
|
72
|
+
this.mappings.delete(ip)
|
|
73
|
+
wasConfident = wasConfident || mapping.verified
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return wasConfident
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
getAll (addresses: NodeAddress[]): NodeAddress[] {
|
|
81
|
+
const dnsMappedAddresses: NodeAddress[] = []
|
|
82
|
+
|
|
83
|
+
for (let i = 0; i < addresses.length; i++) {
|
|
84
|
+
const address = addresses[i]
|
|
85
|
+
const tuples = address.multiaddr.stringTuples()
|
|
86
|
+
const host = tuples[0][1]
|
|
87
|
+
|
|
88
|
+
if (host == null) {
|
|
89
|
+
continue
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (const [ip, mapping] of this.mappings.entries()) {
|
|
93
|
+
if (host !== ip) {
|
|
94
|
+
continue
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// insert SNI tuple after TLS tuple, if one is present
|
|
98
|
+
const mappedIp = this.maybeAddSNITuple(tuples, mapping.domain)
|
|
99
|
+
|
|
100
|
+
if (mappedIp) {
|
|
101
|
+
// remove the address and replace it with the version that includes
|
|
102
|
+
// the SNI tuple
|
|
103
|
+
addresses.splice(i, 1)
|
|
104
|
+
i--
|
|
105
|
+
|
|
106
|
+
dnsMappedAddresses.push({
|
|
107
|
+
multiaddr: multiaddr(`/${
|
|
108
|
+
tuples.map(tuple => {
|
|
109
|
+
return [
|
|
110
|
+
protocols(tuple[0]).name,
|
|
111
|
+
tuple[1]
|
|
112
|
+
].join('/')
|
|
113
|
+
}).join('/')
|
|
114
|
+
}`),
|
|
115
|
+
verified: mapping.verified,
|
|
116
|
+
type: 'dns-mapping',
|
|
117
|
+
expires: mapping.expires,
|
|
118
|
+
lastVerified: mapping.lastVerified
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return dnsMappedAddresses
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private maybeAddSNITuple (tuples: StringTuple[], domain: string): boolean {
|
|
128
|
+
for (let j = 0; j < tuples.length; j++) {
|
|
129
|
+
if (tuples[j][0] === CODEC_TLS && tuples[j + 1]?.[0] !== CODEC_SNI) {
|
|
130
|
+
tuples.splice(j + 1, 0, [CODEC_SNI, domain])
|
|
131
|
+
return true
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return false
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
confirm (ma: Multiaddr, ttl: number): boolean {
|
|
139
|
+
const host = this.findHost(ma)
|
|
140
|
+
let startingConfidence = false
|
|
141
|
+
|
|
142
|
+
for (const [ip, mapping] of this.mappings.entries()) {
|
|
143
|
+
if (mapping.domain === host) {
|
|
144
|
+
this.log('marking %s to %s DNS mapping as verified', ip, mapping.domain)
|
|
145
|
+
startingConfidence = mapping.verified
|
|
146
|
+
mapping.verified = true
|
|
147
|
+
mapping.expires = Date.now() + ttl
|
|
148
|
+
mapping.lastVerified = Date.now()
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return startingConfidence
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
unconfirm (ma: Multiaddr, ttl: number): boolean {
|
|
156
|
+
const host = this.findHost(ma)
|
|
157
|
+
let wasConfident = false
|
|
158
|
+
|
|
159
|
+
for (const [ip, mapping] of this.mappings.entries()) {
|
|
160
|
+
if (mapping.domain === host) {
|
|
161
|
+
this.log('removing verification of %s to %s DNS mapping', ip, mapping.domain)
|
|
162
|
+
wasConfident = wasConfident || mapping.verified
|
|
163
|
+
mapping.verified = false
|
|
164
|
+
mapping.expires = Date.now() + ttl
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return wasConfident
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private findHost (ma: Multiaddr): string | undefined {
|
|
172
|
+
for (const tuple of ma.stringTuples()) {
|
|
173
|
+
if (tuple[0] === CODEC_SNI) {
|
|
174
|
+
return tuple[1]
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (tuple[0] === CODEC_DNS || tuple[0] === CODEC_DNS4 || tuple[0] === CODEC_DNS6 || tuple[0] === CODEC_DNSADDR) {
|
|
178
|
+
return tuple[1]
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/* eslint-disable complexity */
|
|
2
|
+
import { isIPv4 } from '@chainsafe/is-ip'
|
|
3
|
+
import { peerIdFromString } from '@libp2p/peer-id'
|
|
4
|
+
import { debounce } from '@libp2p/utils/debounce'
|
|
5
|
+
import { createScalableCuckooFilter } from '@libp2p/utils/filters'
|
|
6
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
7
|
+
import { DNSMappings } from './dns-mappings.js'
|
|
8
|
+
import { IPMappings } from './ip-mappings.js'
|
|
9
|
+
import { ObservedAddresses } from './observed-addresses.js'
|
|
10
|
+
import { TransportAddresses } from './transport-addresses.js'
|
|
11
|
+
import type { ComponentLogger, Libp2pEvents, Logger, TypedEventTarget, PeerId, PeerStore } from '@libp2p/interface'
|
|
12
|
+
import type { AddressManager as AddressManagerInterface, TransportManager, NodeAddress, ConfirmAddressOptions } from '@libp2p/interface-internal'
|
|
13
|
+
import type { Filter } from '@libp2p/utils/filters'
|
|
14
|
+
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
15
|
+
|
|
16
|
+
const ONE_MINUTE = 60_000
|
|
17
|
+
|
|
18
|
+
export const defaultValues = {
|
|
19
|
+
maxObservedAddresses: 10,
|
|
20
|
+
addressVerificationTTL: ONE_MINUTE * 10,
|
|
21
|
+
addressVerificationRetry: ONE_MINUTE * 5
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface AddressManagerInit {
|
|
25
|
+
/**
|
|
26
|
+
* Pass an function in this field to override the list of addresses
|
|
27
|
+
* that are announced to the network
|
|
28
|
+
*/
|
|
29
|
+
announceFilter?: AddressFilter
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A list of string multiaddrs to listen on
|
|
33
|
+
*/
|
|
34
|
+
listen?: string[]
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A list of string multiaddrs to use instead of those reported by transports
|
|
38
|
+
*/
|
|
39
|
+
announce?: string[]
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A list of string multiaddrs string to never announce
|
|
43
|
+
*/
|
|
44
|
+
noAnnounce?: string[]
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* A list of string multiaddrs to add to the list of announced addresses
|
|
48
|
+
*/
|
|
49
|
+
appendAnnounce?: string[]
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Limits the number of observed addresses we will store
|
|
53
|
+
*/
|
|
54
|
+
maxObservedAddresses?: number
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* How long before each public address should be reverified in ms.
|
|
58
|
+
*
|
|
59
|
+
* Requires `@libp2p/autonat` or some other verification method to be
|
|
60
|
+
* configured.
|
|
61
|
+
*
|
|
62
|
+
* @default 600_000
|
|
63
|
+
*/
|
|
64
|
+
addressVerificationTTL?: number
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* After a transport or mapped address has failed to verify, how long to wait
|
|
68
|
+
* before retrying it in ms
|
|
69
|
+
*
|
|
70
|
+
* Requires `@libp2p/autonat` or some other verification method to be
|
|
71
|
+
* configured.
|
|
72
|
+
*
|
|
73
|
+
* @default 300_000
|
|
74
|
+
*/
|
|
75
|
+
addressVerificationRetry?: number
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface AddressManagerComponents {
|
|
79
|
+
peerId: PeerId
|
|
80
|
+
transportManager: TransportManager
|
|
81
|
+
peerStore: PeerStore
|
|
82
|
+
events: TypedEventTarget<Libp2pEvents>
|
|
83
|
+
logger: ComponentLogger
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* A function that takes a list of multiaddrs and returns a list
|
|
88
|
+
* to announce
|
|
89
|
+
*/
|
|
90
|
+
export interface AddressFilter {
|
|
91
|
+
(addrs: Multiaddr[]): Multiaddr[]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const defaultAddressFilter = (addrs: Multiaddr[]): Multiaddr[] => addrs
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* If the passed multiaddr contains the passed peer id, remove it
|
|
98
|
+
*/
|
|
99
|
+
function stripPeerId (ma: Multiaddr, peerId: PeerId): Multiaddr {
|
|
100
|
+
const observedPeerIdStr = ma.getPeerId()
|
|
101
|
+
|
|
102
|
+
// strip our peer id if it has been passed
|
|
103
|
+
if (observedPeerIdStr != null) {
|
|
104
|
+
const observedPeerId = peerIdFromString(observedPeerIdStr)
|
|
105
|
+
|
|
106
|
+
// use same encoding for comparison
|
|
107
|
+
if (observedPeerId.equals(peerId)) {
|
|
108
|
+
ma = ma.decapsulate(multiaddr(`/p2p/${peerId.toString()}`))
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return ma
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export class AddressManager implements AddressManagerInterface {
|
|
116
|
+
private readonly log: Logger
|
|
117
|
+
private readonly components: AddressManagerComponents
|
|
118
|
+
// this is an array to allow for duplicates, e.g. multiples of `/ip4/0.0.0.0/tcp/0`
|
|
119
|
+
private readonly listen: string[]
|
|
120
|
+
private readonly announce: Set<string>
|
|
121
|
+
private readonly appendAnnounce: Set<string>
|
|
122
|
+
private readonly announceFilter: AddressFilter
|
|
123
|
+
private readonly observed: ObservedAddresses
|
|
124
|
+
private readonly dnsMappings: DNSMappings
|
|
125
|
+
private readonly ipMappings: IPMappings
|
|
126
|
+
private readonly transportAddresses: TransportAddresses
|
|
127
|
+
private readonly observedAddressFilter: Filter
|
|
128
|
+
private readonly addressVerificationTTL: number
|
|
129
|
+
private readonly addressVerificationRetry: number
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Responsible for managing the peer addresses.
|
|
133
|
+
* Peers can specify their listen and announce addresses.
|
|
134
|
+
* The listen addresses will be used by the libp2p transports to listen for new connections,
|
|
135
|
+
* while the announce addresses will be used for the peer addresses' to other peers in the network.
|
|
136
|
+
*/
|
|
137
|
+
constructor (components: AddressManagerComponents, init: AddressManagerInit = {}) {
|
|
138
|
+
const { listen = [], announce = [], appendAnnounce = [] } = init
|
|
139
|
+
|
|
140
|
+
this.components = components
|
|
141
|
+
this.log = components.logger.forComponent('libp2p:address-manager')
|
|
142
|
+
this.listen = listen.map(ma => ma.toString())
|
|
143
|
+
this.announce = new Set(announce.map(ma => ma.toString()))
|
|
144
|
+
this.appendAnnounce = new Set(appendAnnounce.map(ma => ma.toString()))
|
|
145
|
+
this.observed = new ObservedAddresses(components, init)
|
|
146
|
+
this.dnsMappings = new DNSMappings(components, init)
|
|
147
|
+
this.ipMappings = new IPMappings(components, init)
|
|
148
|
+
this.transportAddresses = new TransportAddresses(components, init)
|
|
149
|
+
this.announceFilter = init.announceFilter ?? defaultAddressFilter
|
|
150
|
+
this.observedAddressFilter = createScalableCuckooFilter(1024)
|
|
151
|
+
this.addressVerificationTTL = init.addressVerificationTTL ?? defaultValues.addressVerificationTTL
|
|
152
|
+
this.addressVerificationRetry = init.addressVerificationRetry ?? defaultValues.addressVerificationRetry
|
|
153
|
+
|
|
154
|
+
// this method gets called repeatedly on startup when transports start listening so
|
|
155
|
+
// debounce it so we don't cause multiple self:peer:update events to be emitted
|
|
156
|
+
this._updatePeerStoreAddresses = debounce(this._updatePeerStoreAddresses.bind(this), 1000)
|
|
157
|
+
|
|
158
|
+
// update our stored addresses when new transports listen
|
|
159
|
+
components.events.addEventListener('transport:listening', () => {
|
|
160
|
+
this._updatePeerStoreAddresses()
|
|
161
|
+
})
|
|
162
|
+
// update our stored addresses when existing transports stop listening
|
|
163
|
+
components.events.addEventListener('transport:close', () => {
|
|
164
|
+
this._updatePeerStoreAddresses()
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
readonly [Symbol.toStringTag] = '@libp2p/address-manager'
|
|
169
|
+
|
|
170
|
+
_updatePeerStoreAddresses (): void {
|
|
171
|
+
// if announce addresses have been configured, ensure they make it into our peer
|
|
172
|
+
// record for things like identify
|
|
173
|
+
const addrs = this.getAddresses()
|
|
174
|
+
.map(ma => {
|
|
175
|
+
// strip our peer id if it is present
|
|
176
|
+
if (ma.getPeerId() === this.components.peerId.toString()) {
|
|
177
|
+
return ma.decapsulate(`/p2p/${this.components.peerId.toString()}`)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return ma
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
this.components.peerStore.patch(this.components.peerId, {
|
|
184
|
+
multiaddrs: addrs
|
|
185
|
+
})
|
|
186
|
+
.catch(err => {
|
|
187
|
+
this.log.error('error updating addresses', err)
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Get peer listen multiaddrs
|
|
193
|
+
*/
|
|
194
|
+
getListenAddrs (): Multiaddr[] {
|
|
195
|
+
return Array.from(this.listen).map((a) => multiaddr(a))
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Get peer announcing multiaddrs
|
|
200
|
+
*/
|
|
201
|
+
getAnnounceAddrs (): Multiaddr[] {
|
|
202
|
+
return Array.from(this.announce).map((a) => multiaddr(a))
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Get peer announcing multiaddrs
|
|
207
|
+
*/
|
|
208
|
+
getAppendAnnounceAddrs (): Multiaddr[] {
|
|
209
|
+
return Array.from(this.appendAnnounce).map((a) => multiaddr(a))
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Get observed multiaddrs
|
|
214
|
+
*/
|
|
215
|
+
getObservedAddrs (): Multiaddr[] {
|
|
216
|
+
return this.observed.getAll().map(addr => addr.multiaddr)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Add peer observed addresses
|
|
221
|
+
*/
|
|
222
|
+
addObservedAddr (addr: Multiaddr): void {
|
|
223
|
+
const tuples = addr.stringTuples()
|
|
224
|
+
const socketAddress = `${tuples[0][1]}:${tuples[1][1]}`
|
|
225
|
+
|
|
226
|
+
// ignore if this address if it's been observed before
|
|
227
|
+
if (this.observedAddressFilter.has(socketAddress)) {
|
|
228
|
+
return
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
this.observedAddressFilter.add(socketAddress)
|
|
232
|
+
|
|
233
|
+
addr = stripPeerId(addr, this.components.peerId)
|
|
234
|
+
|
|
235
|
+
// ignore observed address if it is an IP mapping
|
|
236
|
+
if (this.ipMappings.has(addr)) {
|
|
237
|
+
return
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ignore observed address if it is a DNS mapping
|
|
241
|
+
if (this.dnsMappings.has(addr)) {
|
|
242
|
+
return
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
this.observed.add(addr)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
confirmObservedAddr (addr: Multiaddr, options?: ConfirmAddressOptions): void {
|
|
249
|
+
addr = stripPeerId(addr, this.components.peerId)
|
|
250
|
+
let startingConfidence = true
|
|
251
|
+
|
|
252
|
+
if (this.observed.has(addr)) {
|
|
253
|
+
startingConfidence = this.observed.confirm(addr, options?.ttl ?? this.addressVerificationTTL)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (this.transportAddresses.has(addr)) {
|
|
257
|
+
startingConfidence = this.transportAddresses.confirm(addr, options?.ttl ?? this.addressVerificationTTL)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (this.dnsMappings.has(addr)) {
|
|
261
|
+
startingConfidence = this.dnsMappings.confirm(addr, options?.ttl ?? this.addressVerificationTTL)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (this.ipMappings.has(addr)) {
|
|
265
|
+
startingConfidence = this.ipMappings.confirm(addr, options?.ttl ?? this.addressVerificationTTL)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// only trigger the 'self:peer:update' event if our confidence in an address has changed
|
|
269
|
+
if (!startingConfidence) {
|
|
270
|
+
this._updatePeerStoreAddresses()
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
removeObservedAddr (addr: Multiaddr, options?: ConfirmAddressOptions): void {
|
|
275
|
+
addr = stripPeerId(addr, this.components.peerId)
|
|
276
|
+
|
|
277
|
+
let startingConfidence = false
|
|
278
|
+
|
|
279
|
+
if (this.observed.has(addr)) {
|
|
280
|
+
startingConfidence = this.observed.remove(addr)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (this.transportAddresses.has(addr)) {
|
|
284
|
+
startingConfidence = this.transportAddresses.unconfirm(addr, options?.ttl ?? this.addressVerificationRetry)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (this.dnsMappings.has(addr)) {
|
|
288
|
+
startingConfidence = this.dnsMappings.unconfirm(addr, options?.ttl ?? this.addressVerificationRetry)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (this.ipMappings.has(addr)) {
|
|
292
|
+
startingConfidence = this.ipMappings.unconfirm(addr, options?.ttl ?? this.addressVerificationRetry)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// only trigger the 'self:peer:update' event if our confidence in an address has changed
|
|
296
|
+
if (startingConfidence) {
|
|
297
|
+
this._updatePeerStoreAddresses()
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
getAddresses (): Multiaddr[] {
|
|
302
|
+
const addresses = new Set<string>()
|
|
303
|
+
|
|
304
|
+
const multiaddrs = this.getAddressesWithMetadata()
|
|
305
|
+
.filter(addr => {
|
|
306
|
+
if (!addr.verified) {
|
|
307
|
+
return false
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const maStr = addr.multiaddr.toString()
|
|
311
|
+
|
|
312
|
+
if (addresses.has(maStr)) {
|
|
313
|
+
return false
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
addresses.add(maStr)
|
|
317
|
+
|
|
318
|
+
return true
|
|
319
|
+
})
|
|
320
|
+
.map(address => address.multiaddr)
|
|
321
|
+
|
|
322
|
+
// filter addressees before returning
|
|
323
|
+
return this.announceFilter(
|
|
324
|
+
multiaddrs.map(str => {
|
|
325
|
+
const ma = multiaddr(str)
|
|
326
|
+
|
|
327
|
+
// do not append our peer id to a path multiaddr as it will become invalid
|
|
328
|
+
if (ma.protos().pop()?.path === true) {
|
|
329
|
+
return ma
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (ma.getPeerId() === this.components.peerId.toString()) {
|
|
333
|
+
return ma
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return ma.encapsulate(`/p2p/${this.components.peerId.toString()}`)
|
|
337
|
+
})
|
|
338
|
+
)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
getAddressesWithMetadata (): NodeAddress[] {
|
|
342
|
+
const announceMultiaddrs = this.getAnnounceAddrs()
|
|
343
|
+
|
|
344
|
+
if (announceMultiaddrs.length > 0) {
|
|
345
|
+
return announceMultiaddrs.map(multiaddr => ({
|
|
346
|
+
multiaddr,
|
|
347
|
+
verified: true,
|
|
348
|
+
type: 'announce',
|
|
349
|
+
expires: Date.now() + this.addressVerificationTTL,
|
|
350
|
+
lastVerified: Date.now()
|
|
351
|
+
}))
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
let addresses: NodeAddress[] = []
|
|
355
|
+
|
|
356
|
+
// add transport addresses
|
|
357
|
+
addresses = addresses.concat(
|
|
358
|
+
this.components.transportManager.getAddrs()
|
|
359
|
+
.map(multiaddr => this.transportAddresses.get(multiaddr, this.addressVerificationTTL))
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
// add append announce addresses
|
|
363
|
+
addresses = addresses.concat(
|
|
364
|
+
this.getAppendAnnounceAddrs().map(multiaddr => ({
|
|
365
|
+
multiaddr,
|
|
366
|
+
verified: true,
|
|
367
|
+
type: 'announce',
|
|
368
|
+
expires: Date.now() + this.addressVerificationTTL,
|
|
369
|
+
lastVerified: Date.now()
|
|
370
|
+
}))
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
// add observed addresses
|
|
374
|
+
addresses = addresses.concat(
|
|
375
|
+
this.observed.getAll()
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
// add ip mapped addresses
|
|
379
|
+
addresses = addresses.concat(
|
|
380
|
+
this.ipMappings.getAll(addresses)
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
// add ip->domain mappings, must be done after IP mappings
|
|
384
|
+
addresses = addresses.concat(
|
|
385
|
+
this.dnsMappings.getAll(addresses)
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
return addresses
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
addDNSMapping (domain: string, addresses: string[]): void {
|
|
392
|
+
this.dnsMappings.add(domain, addresses)
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
removeDNSMapping (domain: string): void {
|
|
396
|
+
if (this.dnsMappings.remove(multiaddr(`/dns/${domain}`))) {
|
|
397
|
+
this._updatePeerStoreAddresses()
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
addPublicAddressMapping (internalIp: string, internalPort: number, externalIp: string, externalPort: number = internalPort, protocol: 'tcp' | 'udp' = 'tcp'): void {
|
|
402
|
+
this.ipMappings.add(internalIp, internalPort, externalIp, externalPort, protocol)
|
|
403
|
+
|
|
404
|
+
// remove duplicate observed addresses
|
|
405
|
+
this.observed.removePrefixed(`/ip${isIPv4(externalIp) ? 4 : 6}/${externalIp}/${protocol}/${externalPort}`)
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
removePublicAddressMapping (internalIp: string, internalPort: number, externalIp: string, externalPort: number = internalPort, protocol: 'tcp' | 'udp' = 'tcp'): void {
|
|
409
|
+
if (this.ipMappings.remove(multiaddr(`/ip${isIPv4(externalIp) ? 4 : 6}/${externalIp}/${protocol}/${externalPort}`))) {
|
|
410
|
+
this._updatePeerStoreAddresses()
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|