libp2p 2.3.0 → 2.3.1-339b7df88

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.
@@ -13,19 +13,24 @@ export interface AddressManagerInit {
13
13
  announceFilter?: AddressFilter
14
14
 
15
15
  /**
16
- * list of multiaddrs string representation to listen
16
+ * A list of string multiaddrs to listen on
17
17
  */
18
18
  listen?: string[]
19
19
 
20
20
  /**
21
- * list of multiaddrs string representation to announce
21
+ * A list of string multiaddrs to use instead of those reported by transports
22
22
  */
23
23
  announce?: string[]
24
24
 
25
25
  /**
26
- * list of multiaddrs string representation to never announce
26
+ * A list of string multiaddrs string to never announce
27
27
  */
28
28
  noAnnounce?: string[]
29
+
30
+ /**
31
+ * A list of string multiaddrs to add to the list of announced addresses
32
+ */
33
+ appendAnnounce?: string[]
29
34
  }
30
35
 
31
36
  export interface AddressManagerComponents {
@@ -73,6 +78,13 @@ const CODEC_IP4 = 0x04
73
78
  const CODEC_IP6 = 0x29
74
79
  const CODEC_DNS4 = 0x36
75
80
  const CODEC_DNS6 = 0x37
81
+ const CODEC_TCP = 0x06
82
+ const CODEC_UDP = 0x0111
83
+
84
+ interface PublicAddressMapping {
85
+ externalIp: string
86
+ externalPort: number
87
+ }
76
88
 
77
89
  export class AddressManager implements AddressManagerInterface {
78
90
  private readonly log: Logger
@@ -80,11 +92,11 @@ export class AddressManager implements AddressManagerInterface {
80
92
  // this is an array to allow for duplicates, e.g. multiples of `/ip4/0.0.0.0/tcp/0`
81
93
  private readonly listen: string[]
82
94
  private readonly announce: Set<string>
95
+ private readonly appendAnnounce: Set<string>
83
96
  private readonly observed: Map<string, ObservedAddressMetadata>
84
97
  private readonly announceFilter: AddressFilter
85
98
  private readonly ipDomainMappings: Map<string, string>
86
-
87
- private readonly where: Error
99
+ private readonly publicAddressMappings: Map<string, PublicAddressMapping[]>
88
100
 
89
101
  /**
90
102
  * Responsible for managing the peer addresses.
@@ -93,14 +105,16 @@ export class AddressManager implements AddressManagerInterface {
93
105
  * while the announce addresses will be used for the peer addresses' to other peers in the network.
94
106
  */
95
107
  constructor (components: AddressManagerComponents, init: AddressManagerInit = {}) {
96
- const { listen = [], announce = [] } = init
108
+ const { listen = [], announce = [], appendAnnounce = [] } = init
97
109
 
98
110
  this.components = components
99
111
  this.log = components.logger.forComponent('libp2p:address-manager')
100
112
  this.listen = listen.map(ma => ma.toString())
101
113
  this.announce = new Set(announce.map(ma => ma.toString()))
114
+ this.appendAnnounce = new Set(appendAnnounce.map(ma => ma.toString()))
102
115
  this.observed = new Map()
103
116
  this.ipDomainMappings = new Map()
117
+ this.publicAddressMappings = new Map()
104
118
  this.announceFilter = init.announceFilter ?? defaultAddressFilter
105
119
 
106
120
  // this method gets called repeatedly on startup when transports start listening so
@@ -115,8 +129,6 @@ export class AddressManager implements AddressManagerInterface {
115
129
  components.events.addEventListener('transport:close', () => {
116
130
  this._updatePeerStoreAddresses()
117
131
  })
118
-
119
- this.where = new Error('where')
120
132
  }
121
133
 
122
134
  readonly [Symbol.toStringTag] = '@libp2p/address-manager'
@@ -124,13 +136,8 @@ export class AddressManager implements AddressManagerInterface {
124
136
  _updatePeerStoreAddresses (): void {
125
137
  // if announce addresses have been configured, ensure they make it into our peer
126
138
  // record for things like identify
127
- const addrs = this.getAnnounceAddrs()
128
- .concat(this.components.transportManager.getAddrs())
129
- .concat(
130
- [...this.observed.entries()]
131
- .filter(([_, metadata]) => metadata.confident)
132
- .map(([str]) => multiaddr(str))
133
- ).map(ma => {
139
+ const addrs = this.getAddresses()
140
+ .map(ma => {
134
141
  // strip our peer id if it is present
135
142
  if (ma.getPeerId() === this.components.peerId.toString()) {
136
143
  return ma.decapsulate(`/p2p/${this.components.peerId.toString()}`)
@@ -159,6 +166,13 @@ export class AddressManager implements AddressManagerInterface {
159
166
  return Array.from(this.announce).map((a) => multiaddr(a))
160
167
  }
161
168
 
169
+ /**
170
+ * Get peer announcing multiaddrs
171
+ */
172
+ getAppendAnnounceAddrs (): Multiaddr[] {
173
+ return Array.from(this.appendAnnounce).map((a) => multiaddr(a))
174
+ }
175
+
162
176
  /**
163
177
  * Get observed multiaddrs
164
178
  */
@@ -218,19 +232,62 @@ export class AddressManager implements AddressManagerInterface {
218
232
  multiaddrs = this.components.transportManager.getAddrs()
219
233
  }
220
234
 
221
- // add observed addresses we are confident in
222
235
  multiaddrs = multiaddrs
223
236
  .concat(
237
+ // add additional announce addresses
238
+ ...this.getAppendAnnounceAddrs(),
239
+
240
+ // add observed addresses we are confident in
224
241
  Array.from(this.observed)
225
242
  .filter(([ma, metadata]) => metadata.confident)
226
243
  .map(([ma]) => multiaddr(ma))
227
244
  )
228
245
 
229
- const mappedMultiaddrs: Multiaddr[] = []
246
+ // add public addresses
247
+ const ipMappedMultiaddrs: Multiaddr[] = []
248
+ multiaddrs.forEach(ma => {
249
+ const tuples = ma.stringTuples()
250
+ let tuple: string | undefined
251
+
252
+ // see if the internal host/port/protocol tuple has been mapped externally
253
+ if ((tuples[0][0] === CODEC_IP4 || tuples[0][0] === CODEC_IP6) && tuples[1][0] === CODEC_TCP) {
254
+ tuple = `${tuples[0][1]}-${tuples[1][1]}-tcp`
255
+ } else if ((tuples[0][0] === CODEC_IP4 || tuples[0][0] === CODEC_IP6) && tuples[1][0] === CODEC_UDP) {
256
+ tuple = `${tuples[0][1]}-${tuples[1][1]}-udp`
257
+ }
258
+
259
+ if (tuple == null) {
260
+ return
261
+ }
262
+
263
+ const mappings = this.publicAddressMappings.get(tuple)
264
+
265
+ if (mappings == null) {
266
+ return
267
+ }
268
+
269
+ mappings.forEach(mapping => {
270
+ tuples[0][1] = mapping.externalIp
271
+ tuples[1][1] = `${mapping.externalPort}`
272
+
273
+ ipMappedMultiaddrs.push(
274
+ multiaddr(`/${
275
+ tuples.map(tuple => {
276
+ return [
277
+ protocols(tuple[0]).name,
278
+ tuple[1]
279
+ ].join('/')
280
+ }).join('/')
281
+ }`)
282
+ )
283
+ })
284
+ })
285
+ multiaddrs = multiaddrs.concat(ipMappedMultiaddrs)
230
286
 
231
287
  // add ip->domain mappings
288
+ const dnsMappedMultiaddrs: Multiaddr[] = []
232
289
  for (const ma of multiaddrs) {
233
- const tuples = [...ma.stringTuples()]
290
+ const tuples = ma.stringTuples()
234
291
  let mappedIp = false
235
292
 
236
293
  for (const [ip, domain] of this.ipDomainMappings.entries()) {
@@ -254,7 +311,7 @@ export class AddressManager implements AddressManagerInterface {
254
311
  }
255
312
 
256
313
  if (mappedIp) {
257
- mappedMultiaddrs.push(
314
+ dnsMappedMultiaddrs.push(
258
315
  multiaddr(`/${
259
316
  tuples.map(tuple => {
260
317
  return [
@@ -266,8 +323,7 @@ export class AddressManager implements AddressManagerInterface {
266
323
  )
267
324
  }
268
325
  }
269
-
270
- multiaddrs = multiaddrs.concat(mappedMultiaddrs)
326
+ multiaddrs = multiaddrs.concat(dnsMappedMultiaddrs)
271
327
 
272
328
  // dedupe multiaddrs
273
329
  const addrSet = new Set<string>()
@@ -305,15 +361,46 @@ export class AddressManager implements AddressManagerInterface {
305
361
 
306
362
  addDNSMapping (domain: string, addresses: string[]): void {
307
363
  addresses.forEach(ip => {
364
+ this.log('add DNS mapping %s to %s', ip, domain)
308
365
  this.ipDomainMappings.set(ip, domain)
309
366
  })
367
+ this._updatePeerStoreAddresses()
310
368
  }
311
369
 
312
370
  removeDNSMapping (domain: string): void {
313
371
  for (const [key, value] of this.ipDomainMappings.entries()) {
314
372
  if (value === domain) {
373
+ this.log('remove DNS mapping for %s', domain)
315
374
  this.ipDomainMappings.delete(key)
316
375
  }
317
376
  }
377
+ this._updatePeerStoreAddresses()
378
+ }
379
+
380
+ addPublicAddressMapping (internalIp: string, internalPort: number, externalIp: string, externalPort: number = internalPort, protocol: 'tcp' | 'udp' = 'tcp'): void {
381
+ const key = `${internalIp}-${internalPort}-${protocol}`
382
+ const mappings = this.publicAddressMappings.get(key) ?? []
383
+ mappings.push({
384
+ externalIp,
385
+ externalPort
386
+ })
387
+
388
+ this.publicAddressMappings.set(key, mappings)
389
+ this._updatePeerStoreAddresses()
390
+ }
391
+
392
+ removePublicAddressMapping (internalIp: string, internalPort: number, externalIp: string, externalPort: number = internalPort, protocol: 'tcp' | 'udp' = 'tcp'): void {
393
+ const key = `${internalIp}-${internalPort}-${protocol}`
394
+ const mappings = (this.publicAddressMappings.get(key) ?? []).filter(mapping => {
395
+ return mapping.externalIp !== externalIp && mapping.externalPort !== externalPort
396
+ })
397
+
398
+ if (mappings.length === 0) {
399
+ this.publicAddressMappings.delete(key)
400
+ } else {
401
+ this.publicAddressMappings.set(key, mappings)
402
+ }
403
+
404
+ this._updatePeerStoreAddresses()
318
405
  }
319
406
  }
@@ -1,19 +1,33 @@
1
1
  import { isPrivateIp } from '@libp2p/utils/private-ip'
2
+ import { WebSockets } from '@multiformats/multiaddr-matcher'
2
3
  import type { ConnectionGater } from '@libp2p/interface'
3
4
  import type { Multiaddr } from '@multiformats/multiaddr'
4
5
 
6
+ const CODEC_IP4 = 0x04
7
+ const CODEC_IP6 = 0x29
8
+
5
9
  /**
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.
10
+ * Returns a connection gater that disallows dialling private addresses or
11
+ * insecure websockets by default.
12
+ *
13
+ * Browsers are severely limited in their resource usage so don't waste time
14
+ * trying to dial undiallable addresses, and they also print verbose error
15
+ * messages when making connections over insecure transports which causes
16
+ * confusion.
9
17
  */
10
18
  export function connectionGater (gater: ConnectionGater = {}): ConnectionGater {
11
19
  return {
12
20
  denyDialPeer: async () => false,
13
21
  denyDialMultiaddr: async (multiaddr: Multiaddr) => {
22
+ // do not connect to insecure websockets by default
23
+ if (WebSockets.matches(multiaddr)) {
24
+ return false
25
+ }
26
+
14
27
  const tuples = multiaddr.stringTuples()
15
28
 
16
- if (tuples[0][0] === 4 || tuples[0][0] === 41) {
29
+ // do not connect to private addresses by default
30
+ if (tuples[0][0] === CODEC_IP4 || tuples[0][0] === CODEC_IP6) {
17
31
  return Boolean(isPrivateIp(`${tuples[0][1]}`))
18
32
  }
19
33
 
@@ -1,11 +1,11 @@
1
1
  /* eslint-disable max-depth */
2
2
  import { TimeoutError, DialError, setMaxListeners, AbortError } from '@libp2p/interface'
3
3
  import { PeerMap } from '@libp2p/peer-collections'
4
- import { PriorityQueue, type PriorityQueueJobOptions } from '@libp2p/utils/priority-queue'
5
- import { type Multiaddr, type Resolver, resolvers, multiaddr } from '@multiformats/multiaddr'
4
+ import { PriorityQueue } from '@libp2p/utils/priority-queue'
5
+ import { resolvers, multiaddr } from '@multiformats/multiaddr'
6
6
  import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers'
7
7
  import { Circuit } from '@multiformats/multiaddr-matcher'
8
- import { type ClearableSignal, anySignal } from 'any-signal'
8
+ import { anySignal } from 'any-signal'
9
9
  import { CustomProgressEvent } from 'progress-events'
10
10
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
11
11
  import { DialDeniedError, NoValidAddressesError } from '../errors.js'
@@ -23,7 +23,9 @@ import { resolveMultiaddrs } from './utils.js'
23
23
  import { DEFAULT_DIAL_PRIORITY } from './index.js'
24
24
  import type { AddressSorter, ComponentLogger, Logger, Connection, ConnectionGater, Metrics, PeerId, Address, PeerStore, PeerRouting, IsDialableOptions, OpenConnectionProgressEvents } from '@libp2p/interface'
25
25
  import type { OpenConnectionOptions, TransportManager } from '@libp2p/interface-internal'
26
+ import type { PriorityQueueJobOptions } from '@libp2p/utils/priority-queue'
26
27
  import type { DNS } from '@multiformats/dns'
28
+ import type { Multiaddr, Resolver } from '@multiformats/multiaddr'
27
29
  import type { ProgressOptions } from 'progress-events'
28
30
 
29
31
  export interface PendingDialTarget {
@@ -204,7 +206,12 @@ export class DialQueue {
204
206
  options?.onProgress?.(new CustomProgressEvent('dial-queue:start-dial'))
205
207
  // create abort conditions - need to do this before `calculateMultiaddrs` as
206
208
  // we may be about to resolve a dns addr which can time out
207
- const signal = this.createDialAbortController(options?.signal)
209
+ const signal = anySignal([
210
+ this.shutDownController.signal,
211
+ options.signal
212
+ ])
213
+ setMaxListeners(Infinity, signal)
214
+
208
215
  let addrsToDial: Address[]
209
216
 
210
217
  try {
@@ -299,25 +306,11 @@ export class DialQueue {
299
306
  peerId,
300
307
  priority: options.priority ?? DEFAULT_DIAL_PRIORITY,
301
308
  multiaddrs: new Set(multiaddrs.map(ma => ma.toString())),
302
- signal: options.signal,
309
+ signal: options.signal ?? AbortSignal.timeout(this.dialTimeout),
303
310
  onProgress: options.onProgress
304
311
  })
305
312
  }
306
313
 
307
- private createDialAbortController (userSignal?: AbortSignal): ClearableSignal {
308
- // let any signal abort the dial
309
- const signal = anySignal([
310
- AbortSignal.timeout(this.dialTimeout),
311
- this.shutDownController.signal,
312
- userSignal
313
- ])
314
-
315
- // This emitter gets listened to a lot
316
- setMaxListeners(Infinity, signal)
317
-
318
- return signal
319
- }
320
-
321
314
  // eslint-disable-next-line complexity
322
315
  private async calculateMultiaddrs (peerId?: PeerId, multiaddrs: Set<string> = new Set<string>(), options: OpenConnectionOptions = {}): Promise<Address[]> {
323
316
  const addrs: Address[] = [...multiaddrs].map(ma => ({
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
- export const version = '2.3.0'
2
- export const name = 'libp2p'
1
+ export const version = '2.3.1-339b7df88'
2
+ export const name = 'js-libp2p'
package/LICENSE DELETED
@@ -1,4 +0,0 @@
1
- This project is dual licensed under MIT and Apache-2.0.
2
-
3
- MIT: https://www.opensource.org/licenses/mit
4
- Apache-2.0: https://www.apache.org/licenses/license-2.0
@@ -1,19 +0,0 @@
1
- {
2
- "AddressFilter": "https://libp2p.github.io/js-libp2p/interfaces/libp2p.index.AddressFilter.html",
3
- "AddressManagerInit": "https://libp2p.github.io/js-libp2p/interfaces/libp2p.index.AddressManagerInit.html",
4
- "ConnectionManagerInit": "https://libp2p.github.io/js-libp2p/interfaces/libp2p.index.ConnectionManagerInit.html",
5
- "ConnectionMonitorInit": "https://libp2p.github.io/js-libp2p/interfaces/libp2p.index.ConnectionMonitorInit.html",
6
- "Libp2pInit": "https://libp2p.github.io/js-libp2p/interfaces/libp2p.index.Libp2pInit.html",
7
- ".:Libp2pInit": "https://libp2p.github.io/js-libp2p/interfaces/libp2p.index.Libp2pInit.html",
8
- "TransportManagerInit": "https://libp2p.github.io/js-libp2p/interfaces/libp2p.index.TransportManagerInit.html",
9
- "Libp2pOptions": "https://libp2p.github.io/js-libp2p/types/libp2p.index.Libp2pOptions.html",
10
- ".:Libp2pOptions": "https://libp2p.github.io/js-libp2p/types/libp2p.index.Libp2pOptions.html",
11
- "ServiceFactoryMap": "https://libp2p.github.io/js-libp2p/types/libp2p.index.ServiceFactoryMap.html",
12
- ".:ServiceFactoryMap": "https://libp2p.github.io/js-libp2p/types/libp2p.index.ServiceFactoryMap.html",
13
- "createLibp2p": "https://libp2p.github.io/js-libp2p/functions/libp2p.index.createLibp2p.html",
14
- ".:createLibp2p": "https://libp2p.github.io/js-libp2p/functions/libp2p.index.createLibp2p.html",
15
- "name": "https://libp2p.github.io/js-libp2p/variables/libp2p.version.name.html",
16
- "./version:name": "https://libp2p.github.io/js-libp2p/variables/libp2p.version.name.html",
17
- "version": "https://libp2p.github.io/js-libp2p/variables/libp2p.version.version.html",
18
- "./version:version": "https://libp2p.github.io/js-libp2p/variables/libp2p.version.version.html"
19
- }