libp2p 0.43.4 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/index.min.js +30 -30
  2. package/dist/src/autonat/index.d.ts +1 -2
  3. package/dist/src/autonat/index.d.ts.map +1 -1
  4. package/dist/src/autonat/index.js +4 -6
  5. package/dist/src/autonat/index.js.map +1 -1
  6. package/dist/src/circuit-relay/transport/reservation-store.d.ts +1 -1
  7. package/dist/src/circuit-relay/transport/reservation-store.d.ts.map +1 -1
  8. package/dist/src/circuit-relay/utils.d.ts.map +1 -1
  9. package/dist/src/circuit-relay/utils.js +3 -1
  10. package/dist/src/circuit-relay/utils.js.map +1 -1
  11. package/dist/src/components.d.ts +1 -6
  12. package/dist/src/components.d.ts.map +1 -1
  13. package/dist/src/components.js +0 -10
  14. package/dist/src/components.js.map +1 -1
  15. package/dist/src/config.d.ts.map +1 -1
  16. package/dist/src/config.js +0 -9
  17. package/dist/src/config.js.map +1 -1
  18. package/dist/src/connection-manager/auto-dial.d.ts +36 -0
  19. package/dist/src/connection-manager/auto-dial.d.ts.map +1 -0
  20. package/dist/src/connection-manager/auto-dial.js +122 -0
  21. package/dist/src/connection-manager/auto-dial.js.map +1 -0
  22. package/dist/src/connection-manager/connection-pruner.d.ts +28 -0
  23. package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -0
  24. package/dist/src/connection-manager/connection-pruner.js +96 -0
  25. package/dist/src/connection-manager/connection-pruner.js.map +1 -0
  26. package/dist/src/connection-manager/constants.d.ts +49 -0
  27. package/dist/src/connection-manager/constants.d.ts.map +1 -0
  28. package/dist/src/connection-manager/constants.js +49 -0
  29. package/dist/src/connection-manager/constants.js.map +1 -0
  30. package/dist/src/connection-manager/dial-queue.d.ts +77 -0
  31. package/dist/src/connection-manager/dial-queue.d.ts.map +1 -0
  32. package/dist/src/connection-manager/dial-queue.js +366 -0
  33. package/dist/src/connection-manager/dial-queue.js.map +1 -0
  34. package/dist/src/connection-manager/index.d.ts +65 -69
  35. package/dist/src/connection-manager/index.d.ts.map +1 -1
  36. package/dist/src/connection-manager/index.js +116 -234
  37. package/dist/src/connection-manager/index.js.map +1 -1
  38. package/dist/src/connection-manager/utils.d.ts +9 -0
  39. package/dist/src/connection-manager/utils.d.ts.map +1 -0
  40. package/dist/src/connection-manager/utils.js +66 -0
  41. package/dist/src/connection-manager/utils.js.map +1 -0
  42. package/dist/src/fetch/index.js +3 -3
  43. package/dist/src/fetch/index.js.map +1 -1
  44. package/dist/src/identify/index.js +5 -5
  45. package/dist/src/identify/index.js.map +1 -1
  46. package/dist/src/insecure/index.d.ts.map +1 -1
  47. package/dist/src/insecure/index.js +3 -1
  48. package/dist/src/insecure/index.js.map +1 -1
  49. package/dist/src/libp2p.d.ts +10 -2
  50. package/dist/src/libp2p.d.ts.map +1 -1
  51. package/dist/src/libp2p.js +7 -13
  52. package/dist/src/libp2p.js.map +1 -1
  53. package/dist/src/upgrader.d.ts +1 -1
  54. package/dist/src/upgrader.d.ts.map +1 -1
  55. package/dist/src/upgrader.js +2 -1
  56. package/dist/src/upgrader.js.map +1 -1
  57. package/dist/typedoc-urls.json +1 -1
  58. package/package.json +18 -18
  59. package/src/autonat/index.ts +6 -9
  60. package/src/circuit-relay/transport/reservation-store.ts +1 -1
  61. package/src/circuit-relay/utils.ts +3 -1
  62. package/src/components.ts +1 -17
  63. package/src/config.ts +0 -9
  64. package/src/connection-manager/auto-dial.ts +171 -0
  65. package/src/connection-manager/connection-pruner.ts +137 -0
  66. package/src/connection-manager/constants.ts +60 -0
  67. package/src/connection-manager/dial-queue.ts +504 -0
  68. package/src/connection-manager/index.ts +190 -323
  69. package/src/connection-manager/utils.ts +76 -0
  70. package/src/fetch/index.ts +4 -4
  71. package/src/identify/index.ts +5 -5
  72. package/src/insecure/index.ts +5 -1
  73. package/src/libp2p.ts +17 -15
  74. package/src/upgrader.ts +3 -2
  75. package/src/version.ts +1 -1
  76. package/dist/src/connection-manager/auto-dialler.d.ts +0 -42
  77. package/dist/src/connection-manager/auto-dialler.d.ts.map +0 -1
  78. package/dist/src/connection-manager/auto-dialler.js +0 -105
  79. package/dist/src/connection-manager/auto-dialler.js.map +0 -1
  80. package/dist/src/connection-manager/dialer/dial-request.d.ts +0 -27
  81. package/dist/src/connection-manager/dialer/dial-request.d.ts.map +0 -1
  82. package/dist/src/connection-manager/dialer/dial-request.js +0 -114
  83. package/dist/src/connection-manager/dialer/dial-request.js.map +0 -1
  84. package/dist/src/connection-manager/dialer/index.d.ts +0 -121
  85. package/dist/src/connection-manager/dialer/index.d.ts.map +0 -1
  86. package/dist/src/connection-manager/dialer/index.js +0 -324
  87. package/dist/src/connection-manager/dialer/index.js.map +0 -1
  88. package/dist/src/connection-manager/latency-monitor.d.ts +0 -120
  89. package/dist/src/connection-manager/latency-monitor.d.ts.map +0 -1
  90. package/dist/src/connection-manager/latency-monitor.js +0 -220
  91. package/dist/src/connection-manager/latency-monitor.js.map +0 -1
  92. package/dist/src/connection-manager/visibility-change-emitter.d.ts +0 -66
  93. package/dist/src/connection-manager/visibility-change-emitter.d.ts.map +0 -1
  94. package/dist/src/connection-manager/visibility-change-emitter.js +0 -118
  95. package/dist/src/connection-manager/visibility-change-emitter.js.map +0 -1
  96. package/dist/src/constants.d.ts +0 -27
  97. package/dist/src/constants.d.ts.map +0 -1
  98. package/dist/src/constants.js +0 -31
  99. package/dist/src/constants.js.map +0 -1
  100. package/src/connection-manager/auto-dialler.ts +0 -158
  101. package/src/connection-manager/dialer/dial-request.ts +0 -144
  102. package/src/connection-manager/dialer/index.ts +0 -461
  103. package/src/connection-manager/latency-monitor.ts +0 -319
  104. package/src/connection-manager/visibility-change-emitter.ts +0 -135
  105. package/src/constants.ts +0 -36
@@ -0,0 +1,76 @@
1
+ import { AbortOptions, multiaddr } from '@multiformats/multiaddr'
2
+ import type { Multiaddr } from '@multiformats/multiaddr'
3
+ import { logger } from '@libp2p/logger'
4
+ import { ClearableSignal, anySignal } from 'any-signal'
5
+ import { setMaxListeners } from 'events'
6
+
7
+ const log = logger('libp2p:connection-manager:utils')
8
+
9
+ /**
10
+ * Resolve multiaddr recursively
11
+ */
12
+ export async function resolveMultiaddrs (ma: Multiaddr, options: AbortOptions): Promise<Multiaddr[]> {
13
+ // TODO: recursive logic should live in multiaddr once dns4/dns6 support is in place
14
+ // Now only supporting resolve for dnsaddr
15
+ const resolvableProto = ma.protoNames().includes('dnsaddr')
16
+
17
+ // Multiaddr is not resolvable? End recursion!
18
+ if (!resolvableProto) {
19
+ return [ma]
20
+ }
21
+
22
+ const resolvedMultiaddrs = await resolveRecord(ma, options)
23
+ const recursiveMultiaddrs = await Promise.all(resolvedMultiaddrs.map(async (nm) => {
24
+ return await resolveMultiaddrs(nm, options)
25
+ }))
26
+
27
+ const addrs = recursiveMultiaddrs.flat()
28
+ const output = addrs.reduce<Multiaddr[]>((array, newM) => {
29
+ if (array.find(m => m.equals(newM)) == null) {
30
+ array.push(newM)
31
+ }
32
+ return array
33
+ }, ([]))
34
+
35
+ log('resolved %s to', ma, output.map(ma => ma.toString()))
36
+
37
+ return output
38
+ }
39
+
40
+ /**
41
+ * Resolve a given multiaddr. If this fails, an empty array will be returned
42
+ */
43
+ async function resolveRecord (ma: Multiaddr, options: AbortOptions): Promise<Multiaddr[]> {
44
+ try {
45
+ ma = multiaddr(ma.toString()) // Use current multiaddr module
46
+ const multiaddrs = await ma.resolve(options)
47
+ return multiaddrs
48
+ } catch (err) {
49
+ log.error(`multiaddr ${ma.toString()} could not be resolved`, err)
50
+ return []
51
+ }
52
+ }
53
+
54
+ export function combineSignals (...signals: Array<AbortSignal | undefined>): ClearableSignal {
55
+ const sigs: AbortSignal[] = []
56
+
57
+ for (const sig of signals) {
58
+ if (sig != null) {
59
+ try {
60
+ // fails on node < 15.4
61
+ setMaxListeners?.(Infinity, sig)
62
+ } catch { }
63
+ sigs.push(sig)
64
+ }
65
+ }
66
+
67
+ // let any signal abort the dial
68
+ const signal = anySignal(sigs)
69
+
70
+ try {
71
+ // fails on node < 15.4
72
+ setMaxListeners?.(Infinity, signal)
73
+ } catch {}
74
+
75
+ return signal
76
+ }
@@ -127,9 +127,9 @@ export class FetchService implements Startable {
127
127
 
128
128
  const result = await pipe(
129
129
  [FetchRequest.encode({ identifier: key })],
130
- lp.encode(),
130
+ (source) => lp.encode(source),
131
131
  source,
132
- lp.decode(),
132
+ (source) => lp.decode(source),
133
133
  async function (source) {
134
134
  const buf = await first(source)
135
135
 
@@ -184,7 +184,7 @@ export class FetchService implements Startable {
184
184
 
185
185
  await pipe(
186
186
  stream,
187
- lp.decode(),
187
+ (source) => lp.decode(source),
188
188
  async function * (source) {
189
189
  const buf = await first(source)
190
190
 
@@ -215,7 +215,7 @@ export class FetchService implements Startable {
215
215
 
216
216
  yield FetchResponse.encode(response)
217
217
  },
218
- lp.encode(),
218
+ (source) => lp.encode(source),
219
219
  stream
220
220
  )
221
221
  }
@@ -197,7 +197,7 @@ export class IdentifyService implements Startable {
197
197
  signedPeerRecord,
198
198
  protocols
199
199
  })],
200
- lp.encode()
200
+ (source) => lp.encode(source)
201
201
  ))
202
202
  } catch (err: any) {
203
203
  // Just log errors
@@ -266,7 +266,7 @@ export class IdentifyService implements Startable {
266
266
  const data = await pipe(
267
267
  [],
268
268
  source,
269
- lp.decode({
269
+ (source) => lp.decode(source, {
270
270
  maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
271
271
  }),
272
272
  async (source) => await first(source)
@@ -348,7 +348,7 @@ export class IdentifyService implements Startable {
348
348
  await this.components.peerStore.metadataBook.setValue(id, 'ProtocolVersion', uint8ArrayFromString(protocolVersion))
349
349
  }
350
350
 
351
- log('identify completed for peer %p with and protocols %o', id, protocols)
351
+ log('identify completed for peer %p with protocols %o', id, protocols)
352
352
 
353
353
  return
354
354
  }
@@ -431,7 +431,7 @@ export class IdentifyService implements Startable {
431
431
  // make stream abortable
432
432
  const source = abortableDuplex(stream, timeoutController.signal)
433
433
 
434
- const msgWithLenPrefix = pipe([message], lp.encode())
434
+ const msgWithLenPrefix = pipe([message], (source) => lp.encode(source))
435
435
  await source.sink(msgWithLenPrefix)
436
436
  } catch (err: any) {
437
437
  log.error('could not respond to identify request', err)
@@ -461,7 +461,7 @@ export class IdentifyService implements Startable {
461
461
  const data = await pipe(
462
462
  [],
463
463
  source,
464
- lp.decode({
464
+ (source) => lp.decode(source, {
465
465
  maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
466
466
  }),
467
467
  async (source) => await first(source)
@@ -71,8 +71,12 @@ async function encrypt (localId: PeerId, conn: Duplex<Uint8Array>, remoteId?: Pe
71
71
  log('write pubkey exchange to peer %p', remoteId)
72
72
 
73
73
  // Get the Exchange message
74
- // @ts-expect-error needs to be generator
75
74
  const response = (await lp.decode.fromReader(shake.reader).next()).value
75
+
76
+ if (response == null) {
77
+ throw new Error('Did not read response')
78
+ }
79
+
76
80
  const id = Exchange.decode(response)
77
81
  log('read pubkey exchange from peer %p', remoteId)
78
82
 
package/src/libp2p.ts CHANGED
@@ -9,7 +9,6 @@ import { CompoundContentRouting } from './content-routing/index.js'
9
9
  import { codes } from './errors.js'
10
10
  import { DefaultAddressManager } from './address-manager/index.js'
11
11
  import { DefaultConnectionManager } from './connection-manager/index.js'
12
- import { AutoDialler } from './connection-manager/auto-dialler.js'
13
12
  import { DefaultKeyChain } from '@libp2p/keychain'
14
13
  import { DefaultTransportManager } from './transport-manager.js'
15
14
  import { DefaultUpgrader } from './upgrader.js'
@@ -46,7 +45,6 @@ import type { Metrics } from '@libp2p/interface-metrics'
46
45
  import { DummyDHT } from './dht/dummy-dht.js'
47
46
  import { DummyPubSub } from './pubsub/dummy-pubsub.js'
48
47
  import { PeerSet } from '@libp2p/peer-collections'
49
- import { DefaultDialer } from './connection-manager/dialer/index.js'
50
48
  import { peerIdFromString } from '@libp2p/peer-id'
51
49
  import type { Datastore } from 'interface-datastore'
52
50
  import type { KeyChain } from '@libp2p/interface-keychain'
@@ -55,6 +53,15 @@ import type { CircuitRelayService } from './circuit-relay/index.js'
55
53
 
56
54
  const log = logger('libp2p')
57
55
 
56
+ export type PendingDialStatus = 'queued' | 'active' | 'error' | 'success'
57
+
58
+ export interface PendingDial {
59
+ id: string
60
+ status: PendingDialStatus
61
+ peerId?: PeerId
62
+ multiaddrs: Multiaddr[]
63
+ }
64
+
58
65
  export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
59
66
  public peerId: PeerId
60
67
  public dht: DualDHT
@@ -131,8 +138,8 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
131
138
  inboundUpgradeTimeout: init.connectionManager.inboundUpgradeTimeout
132
139
  })
133
140
 
134
- // Create the dialer
135
- this.components.dialer = new DefaultDialer(this.components, init.connectionManager)
141
+ // Setup the transport manager
142
+ this.components.transportManager = new DefaultTransportManager(this.components, init.transportManager)
136
143
 
137
144
  // Create the Connection Manager
138
145
  this.connectionManager = this.components.connectionManager = new DefaultConnectionManager(this.components, init.connectionManager)
@@ -148,9 +155,6 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
148
155
  // Create the Registrar
149
156
  this.registrar = this.components.registrar = new DefaultRegistrar(this.components)
150
157
 
151
- // Setup the transport manager
152
- this.components.transportManager = new DefaultTransportManager(this.components, init.transportManager)
153
-
154
158
  // Addresses {listen, announce, noAnnounce}
155
159
  this.components.addressManager = new DefaultAddressManager(this.components, init.addresses)
156
160
 
@@ -230,11 +234,6 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
230
234
  ...init.autonat
231
235
  }))
232
236
 
233
- this.configureComponent(new AutoDialler(this.components, {
234
- minConnections: init.connectionManager.minConnections,
235
- autoDialInterval: init.connectionManager.autoDialInterval
236
- }))
237
-
238
237
  if (init.relay != null) {
239
238
  this.circuitService = this.configureComponent(init.relay(this.components))
240
239
  }
@@ -354,6 +353,10 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
354
353
  return this.components.connectionManager.getConnections(peerId)
355
354
  }
356
355
 
356
+ getDialQueue (): PendingDial[] {
357
+ return this.components.connectionManager.getDialQueue()
358
+ }
359
+
357
360
  getPeers (): PeerId[] {
358
361
  const peerSet = new PeerSet()
359
362
 
@@ -365,7 +368,6 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
365
368
  }
366
369
 
367
370
  async dial (peer: PeerId | Multiaddr | Multiaddr[], options: AbortOptions = {}): Promise<Connection> {
368
- // @ts-expect-error
369
371
  return await this.components.connectionManager.openConnection(peer, options)
370
372
  }
371
373
 
@@ -493,8 +495,8 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
493
495
  }
494
496
 
495
497
  /**
496
- * Called whenever peer discovery services emit `peer` events.
497
- * Known peers may be emitted.
498
+ * Called whenever peer discovery services emit `peer` events and adds peers
499
+ * to the peer store.
498
500
  */
499
501
  onDiscoveryPeer (evt: CustomEvent<PeerInfo>): void {
500
502
  const { detail: peer } = evt
package/src/upgrader.ts CHANGED
@@ -21,6 +21,7 @@ import type { Metrics } from '@libp2p/interface-metrics'
21
21
  import type { ConnectionManager } from '@libp2p/interface-connection-manager'
22
22
  import type { PeerStore } from '@libp2p/interface-peer-store'
23
23
  import type { ConnectionGater } from '@libp2p/interface-connection-gater'
24
+ import { INBOUND_UPGRADE_TIMEOUT } from './connection-manager/constants.js'
24
25
 
25
26
  const log = logger('libp2p:upgrader')
26
27
 
@@ -51,7 +52,7 @@ export interface UpgraderInit {
51
52
  * An amount of ms by which an inbound connection upgrade
52
53
  * must complete
53
54
  */
54
- inboundUpgradeTimeout: number
55
+ inboundUpgradeTimeout?: number
55
56
  }
56
57
 
57
58
  function findIncomingStreamLimit (protocol: string, registrar: Registrar): number | undefined {
@@ -126,7 +127,7 @@ export class DefaultUpgrader extends EventEmitter<UpgraderEvents> implements Upg
126
127
  this.muxers.set(muxer.protocol, muxer)
127
128
  })
128
129
 
129
- this.inboundUpgradeTimeout = init.inboundUpgradeTimeout
130
+ this.inboundUpgradeTimeout = init.inboundUpgradeTimeout ?? INBOUND_UPGRADE_TIMEOUT
130
131
  }
131
132
 
132
133
  /**
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
- export const version = '0.43.4'
1
+ export const version = '0.44.0'
2
2
  export const name = 'libp2p'
@@ -1,42 +0,0 @@
1
- import type { Startable } from '@libp2p/interfaces/startable';
2
- import type { PeerId } from '@libp2p/interface-peer-id';
3
- import type { ConnectionManager } from '@libp2p/interface-connection-manager';
4
- import type { PeerStore } from '@libp2p/interface-peer-store';
5
- export interface AutoDiallerInit {
6
- /**
7
- * The minimum number of connections to avoid pruning
8
- */
9
- minConnections?: number;
10
- /**
11
- * How often, in milliseconds, it should preemptively guarantee connections are above the low watermark
12
- */
13
- autoDialInterval?: number;
14
- }
15
- export interface AutoDiallerComponents {
16
- peerId: PeerId;
17
- connectionManager: ConnectionManager;
18
- peerStore: PeerStore;
19
- }
20
- export declare class AutoDialler implements Startable {
21
- private readonly components;
22
- private readonly options;
23
- private running;
24
- private autoDialTimeout?;
25
- /**
26
- * Proactively tries to connect to known peers stored in the PeerStore.
27
- * It will keep the number of connections below the upper limit and sort
28
- * the peers to connect based on wether we know their keys and protocols.
29
- */
30
- constructor(components: AutoDiallerComponents, init: AutoDiallerInit);
31
- isStarted(): boolean;
32
- /**
33
- * Starts the auto dialer
34
- */
35
- start(): Promise<void>;
36
- /**
37
- * Stops the auto dialler
38
- */
39
- stop(): Promise<void>;
40
- _autoDial(): Promise<void>;
41
- }
42
- //# sourceMappingURL=auto-dialler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auto-dialler.d.ts","sourceRoot":"","sources":["../../../src/connection-manager/auto-dialler.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAA;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAI7D,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,SAAS,EAAE,SAAS,CAAA;CACrB;AAOD,qBAAa,WAAY,YAAW,SAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAAC,CAAqB;IAE7C;;;;OAIG;gBACU,UAAU,EAAE,qBAAqB,EAAE,IAAI,EAAE,eAAe;IASrE,SAAS,IAAK,OAAO;IAIrB;;OAEG;IACG,KAAK,IAAK,OAAO,CAAC,IAAI,CAAC;IAU7B;;OAEG;IACG,IAAI,IAAK,OAAO,CAAC,IAAI,CAAC;IAUtB,SAAS,IAAK,OAAO,CAAC,IAAI,CAAC;CAyElC"}
@@ -1,105 +0,0 @@
1
- import { logger } from '@libp2p/logger';
2
- import mergeOptions from 'merge-options';
3
- // @ts-expect-error retimer does not have types
4
- import retimer from 'retimer';
5
- const log = logger('libp2p:connection-manager:auto-dialler');
6
- const defaultOptions = {
7
- minConnections: 0,
8
- autoDialInterval: 10000
9
- };
10
- export class AutoDialler {
11
- /**
12
- * Proactively tries to connect to known peers stored in the PeerStore.
13
- * It will keep the number of connections below the upper limit and sort
14
- * the peers to connect based on wether we know their keys and protocols.
15
- */
16
- constructor(components, init) {
17
- this.components = components;
18
- this.options = mergeOptions.call({ ignoreUndefined: true }, defaultOptions, init);
19
- this.running = false;
20
- this._autoDial = this._autoDial.bind(this);
21
- log('options: %j', this.options);
22
- }
23
- isStarted() {
24
- return this.running;
25
- }
26
- /**
27
- * Starts the auto dialer
28
- */
29
- async start() {
30
- this.running = true;
31
- void this._autoDial().catch(err => {
32
- log.error('could not start autodial', err);
33
- });
34
- log('started');
35
- }
36
- /**
37
- * Stops the auto dialler
38
- */
39
- async stop() {
40
- this.running = false;
41
- if (this.autoDialTimeout != null) {
42
- this.autoDialTimeout.clear();
43
- }
44
- log('stopped');
45
- }
46
- async _autoDial() {
47
- if (this.autoDialTimeout != null) {
48
- this.autoDialTimeout.clear();
49
- }
50
- const minConnections = this.options.minConnections;
51
- // Already has enough connections
52
- if (this.components.connectionManager.getConnections().length >= minConnections) {
53
- this.autoDialTimeout = retimer(this._autoDial, this.options.autoDialInterval);
54
- return;
55
- }
56
- // Sort peers on whether we know protocols or public keys for them
57
- let peers = await this.components.peerStore.all();
58
- peers = peers.filter((peer) => {
59
- // do not dial ourselves
60
- if (peer.id.equals(this.components.peerId)) {
61
- return false;
62
- }
63
- // do not dial peers without multiaddrs
64
- if (peer.addresses.length === 0) {
65
- return false;
66
- }
67
- return true;
68
- });
69
- // shuffle the peers
70
- peers = peers.sort(() => Math.random() > 0.5 ? 1 : -1);
71
- peers = peers.sort((a, b) => {
72
- // dial peers with the most protocols first
73
- if (b.protocols.length > a.protocols.length) {
74
- return 1;
75
- }
76
- // dial peers with public keys first
77
- if (b.id.publicKey != null && a.id.publicKey == null) {
78
- return 1;
79
- }
80
- return -1;
81
- });
82
- for (let i = 0; this.running && i < peers.length && this.components.connectionManager.getConnections().length < minConnections; i++) {
83
- // Connection Manager was stopped during async dial
84
- if (!this.running) {
85
- return;
86
- }
87
- const peer = peers[i];
88
- if (this.components.connectionManager.getConnections(peer.id).length === 0) {
89
- log('connecting to a peerStore stored peer %p', peer.id);
90
- try {
91
- await this.components.connectionManager.openConnection(peer.id);
92
- }
93
- catch (err) {
94
- log.error('could not connect to peerStore stored peer', err);
95
- }
96
- }
97
- }
98
- // Connection Manager was stopped
99
- if (!this.running) {
100
- return;
101
- }
102
- this.autoDialTimeout = retimer(this._autoDial, this.options.autoDialInterval);
103
- }
104
- }
105
- //# sourceMappingURL=auto-dialler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auto-dialler.js","sourceRoot":"","sources":["../../../src/connection-manager/auto-dialler.ts"],"names":[],"mappings":"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"}
@@ -1,27 +0,0 @@
1
- import type { Multiaddr } from '@multiformats/multiaddr';
2
- import type { Connection } from '@libp2p/interface-connection';
3
- import type { AbortOptions } from '@libp2p/interfaces';
4
- import type { Dialer } from '@libp2p/interface-connection-manager';
5
- export interface DialAction {
6
- (m: Multiaddr, options: AbortOptions): Promise<Connection>;
7
- }
8
- export interface DialRequestOptions {
9
- addrs: Multiaddr[];
10
- dialAction: DialAction;
11
- dialer: Dialer;
12
- }
13
- export declare class DialRequest {
14
- private readonly addrs;
15
- private readonly dialer;
16
- private readonly dialAction;
17
- /**
18
- * Manages running the `dialAction` on multiple provided `addrs` in parallel
19
- * up to a maximum determined by the number of tokens returned
20
- * from `dialer.getTokens`. Once a DialRequest is created, it can be
21
- * started using `DialRequest.run(options)`. Once a single dial has succeeded,
22
- * all other dials in the request will be cancelled.
23
- */
24
- constructor(options: DialRequestOptions);
25
- run(options?: AbortOptions): Promise<Connection>;
26
- }
27
- //# sourceMappingURL=dial-request.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dial-request.d.ts","sourceRoot":"","sources":["../../../../src/connection-manager/dialer/dial-request.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sCAAsC,CAAA;AAIlE,MAAM,WAAW,UAAU;IACzB,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;CAC3D;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,UAAU,EAAE,UAAU,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IAEvC;;;;;;OAMG;gBACU,OAAO,EAAE,kBAAkB;IAYlC,GAAG,CAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;CAgG5D"}
@@ -1,114 +0,0 @@
1
- import { CodeError } from '@libp2p/interfaces/errors';
2
- import { anySignal } from 'any-signal';
3
- import FIFO from 'p-fifo';
4
- import { setMaxListeners } from 'events';
5
- import { codes } from '../../errors.js';
6
- import { logger } from '@libp2p/logger';
7
- const log = logger('libp2p:dialer:dial-request');
8
- export class DialRequest {
9
- /**
10
- * Manages running the `dialAction` on multiple provided `addrs` in parallel
11
- * up to a maximum determined by the number of tokens returned
12
- * from `dialer.getTokens`. Once a DialRequest is created, it can be
13
- * started using `DialRequest.run(options)`. Once a single dial has succeeded,
14
- * all other dials in the request will be cancelled.
15
- */
16
- constructor(options) {
17
- const { addrs, dialAction, dialer } = options;
18
- this.addrs = addrs;
19
- this.dialer = dialer;
20
- this.dialAction = dialAction;
21
- }
22
- async run(options = {}) {
23
- const tokens = this.dialer.getTokens(this.addrs.length);
24
- // If no tokens are available, throw
25
- if (tokens.length < 1) {
26
- throw new CodeError('No dial tokens available', codes.ERR_NO_DIAL_TOKENS);
27
- }
28
- const tokenHolder = new FIFO();
29
- for (const token of tokens) {
30
- void tokenHolder.push(token).catch(err => {
31
- log.error(err);
32
- });
33
- }
34
- const dialAbortControllers = this.addrs.map(() => {
35
- const controller = new AbortController();
36
- try {
37
- // fails on node < 15.4
38
- setMaxListeners?.(Infinity, controller.signal);
39
- }
40
- catch { }
41
- return controller;
42
- });
43
- if (options.signal != null) {
44
- try {
45
- // fails on node < 15.4
46
- setMaxListeners?.(Infinity, options.signal);
47
- }
48
- catch { }
49
- }
50
- let completedDials = 0;
51
- let done = false;
52
- try {
53
- return await Promise.any(this.addrs.map(async (addr, i) => {
54
- const token = await tokenHolder.shift(); // get token
55
- // End attempt once another attempt succeeded
56
- if (done) {
57
- this.dialer.releaseToken(tokens.splice(tokens.indexOf(token), 1)[0]);
58
- throw new CodeError('dialAction already succeeded', codes.ERR_ALREADY_SUCCEEDED);
59
- }
60
- const controller = dialAbortControllers[i];
61
- if (controller == null) {
62
- throw new CodeError('dialAction did not come with an AbortController', codes.ERR_INVALID_PARAMETERS);
63
- }
64
- let conn;
65
- try {
66
- const signal = controller.signal;
67
- conn = await this.dialAction(addr, { ...options, signal: (options.signal != null) ? anySignal([signal, options.signal]) : signal });
68
- // Remove the successful AbortController so it is not aborted
69
- dialAbortControllers[i] = undefined;
70
- }
71
- finally {
72
- completedDials++;
73
- // If we have more or equal dials remaining than tokens, recycle the token, otherwise release it
74
- if (this.addrs.length - completedDials >= tokens.length) {
75
- void tokenHolder.push(token).catch(err => {
76
- log.error(err);
77
- });
78
- }
79
- else {
80
- this.dialer.releaseToken(tokens.splice(tokens.indexOf(token), 1)[0]);
81
- }
82
- }
83
- if (conn == null) {
84
- // Notify Promise.any that attempt was not successful
85
- // to prevent from returning undefined despite there
86
- // were successful dial attempts
87
- throw new CodeError('dialAction led to empty object', codes.ERR_TRANSPORT_DIAL_FAILED);
88
- }
89
- else {
90
- // This dial succeeded, don't attempt anything else
91
- done = true;
92
- }
93
- return conn;
94
- }));
95
- }
96
- catch (err) {
97
- // if we only dialed one address, unwrap the AggregateError
98
- if (this.addrs.length === 1 && err.name === 'AggregateError') {
99
- throw err.errors[0];
100
- }
101
- throw err;
102
- }
103
- finally {
104
- // success/failure happened, abort everything else
105
- dialAbortControllers.forEach(c => {
106
- if (c !== undefined) {
107
- c.abort();
108
- }
109
- });
110
- tokens.forEach(token => { this.dialer.releaseToken(token); }); // release tokens back to the dialer
111
- }
112
- }
113
- }
114
- //# sourceMappingURL=dial-request.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dial-request.js","sourceRoot":"","sources":["../../../../src/connection-manager/dialer/dial-request.ts"],"names":[],"mappings":"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"}