libp2p 0.45.4 → 0.45.5-775f8928

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 (48) hide show
  1. package/dist/index.min.js +21 -21
  2. package/dist/src/autonat/index.js +4 -4
  3. package/dist/src/circuit-relay/transport/discovery.d.ts.map +1 -1
  4. package/dist/src/circuit-relay/transport/discovery.js +11 -4
  5. package/dist/src/circuit-relay/transport/discovery.js.map +1 -1
  6. package/dist/src/circuit-relay/transport/reservation-store.d.ts +5 -0
  7. package/dist/src/circuit-relay/transport/reservation-store.d.ts.map +1 -1
  8. package/dist/src/circuit-relay/transport/reservation-store.js +14 -2
  9. package/dist/src/circuit-relay/transport/reservation-store.js.map +1 -1
  10. package/dist/src/connection-manager/auto-dial.d.ts +3 -0
  11. package/dist/src/connection-manager/auto-dial.d.ts.map +1 -1
  12. package/dist/src/connection-manager/auto-dial.js +64 -27
  13. package/dist/src/connection-manager/auto-dial.js.map +1 -1
  14. package/dist/src/connection-manager/constants.d.ts +4 -0
  15. package/dist/src/connection-manager/constants.d.ts.map +1 -1
  16. package/dist/src/connection-manager/constants.js +4 -0
  17. package/dist/src/connection-manager/constants.js.map +1 -1
  18. package/dist/src/connection-manager/index.d.ts +5 -0
  19. package/dist/src/connection-manager/index.d.ts.map +1 -1
  20. package/dist/src/connection-manager/index.js +11 -10
  21. package/dist/src/connection-manager/index.js.map +1 -1
  22. package/dist/src/identify/identify.d.ts.map +1 -1
  23. package/dist/src/identify/identify.js +65 -49
  24. package/dist/src/identify/identify.js.map +1 -1
  25. package/dist/src/upnp-nat/index.d.ts +1 -1
  26. package/dist/src/upnp-nat/index.d.ts.map +1 -1
  27. package/dist/src/upnp-nat/index.js +3 -3
  28. package/dist/src/upnp-nat/index.js.map +1 -1
  29. package/dist/src/utils/peer-job-queue.d.ts +33 -0
  30. package/dist/src/utils/peer-job-queue.d.ts.map +1 -0
  31. package/dist/src/utils/peer-job-queue.js +82 -0
  32. package/dist/src/utils/peer-job-queue.js.map +1 -0
  33. package/dist/src/version.d.ts +1 -1
  34. package/dist/src/version.d.ts.map +1 -1
  35. package/dist/src/version.js +1 -1
  36. package/dist/src/version.js.map +1 -1
  37. package/package.json +7 -6
  38. package/src/autonat/index.ts +4 -4
  39. package/src/circuit-relay/transport/discovery.ts +11 -4
  40. package/src/circuit-relay/transport/reservation-store.ts +22 -3
  41. package/src/connection-manager/auto-dial.ts +75 -31
  42. package/src/connection-manager/constants.ts +5 -0
  43. package/src/connection-manager/index.ts +18 -12
  44. package/src/identify/identify.ts +68 -49
  45. package/src/upnp-nat/index.ts +3 -3
  46. package/src/utils/peer-job-queue.ts +119 -0
  47. package/src/version.ts +1 -1
  48. package/dist/typedoc-urls.json +0 -58
@@ -1,7 +1,7 @@
1
1
  import { logger } from '@libp2p/logger'
2
2
  import { PeerMap, PeerSet } from '@libp2p/peer-collections'
3
- import PQueue from 'p-queue'
4
- import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_INTERVAL, AUTO_DIAL_PRIORITY, MIN_CONNECTIONS } from './constants.js'
3
+ import { PeerJobQueue } from '../utils/peer-job-queue.js'
4
+ import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_INTERVAL, AUTO_DIAL_MAX_QUEUE_LENGTH, AUTO_DIAL_PRIORITY, MIN_CONNECTIONS } from './constants.js'
5
5
  import type { ConnectionManager } from '@libp2p/interface-connection-manager'
6
6
  import type { Libp2pEvents } from '@libp2p/interface-libp2p'
7
7
  import type { PeerStore } from '@libp2p/interface-peer-store'
@@ -12,6 +12,7 @@ const log = logger('libp2p:connection-manager:auto-dial')
12
12
 
13
13
  interface AutoDialInit {
14
14
  minConnections?: number
15
+ maxQueueLength?: number
15
16
  autoDialConcurrency?: number
16
17
  autoDialPriority?: number
17
18
  autoDialInterval?: number
@@ -25,6 +26,7 @@ interface AutoDialComponents {
25
26
 
26
27
  const defaultOptions = {
27
28
  minConnections: MIN_CONNECTIONS,
29
+ maxQueueLength: AUTO_DIAL_MAX_QUEUE_LENGTH,
28
30
  autoDialConcurrency: AUTO_DIAL_CONCURRENCY,
29
31
  autoDialPriority: AUTO_DIAL_PRIORITY,
30
32
  autoDialInterval: AUTO_DIAL_INTERVAL
@@ -33,12 +35,14 @@ const defaultOptions = {
33
35
  export class AutoDial implements Startable {
34
36
  private readonly connectionManager: ConnectionManager
35
37
  private readonly peerStore: PeerStore
36
- private readonly queue: PQueue
38
+ private readonly queue: PeerJobQueue
37
39
  private readonly minConnections: number
38
40
  private readonly autoDialPriority: number
39
41
  private readonly autoDialIntervalMs: number
42
+ private readonly autoDialMaxQueueLength: number
40
43
  private autoDialInterval?: ReturnType<typeof setInterval>
41
44
  private started: boolean
45
+ private running: boolean
42
46
 
43
47
  /**
44
48
  * Proactively tries to connect to known peers stored in the PeerStore.
@@ -51,8 +55,10 @@ export class AutoDial implements Startable {
51
55
  this.minConnections = init.minConnections ?? defaultOptions.minConnections
52
56
  this.autoDialPriority = init.autoDialPriority ?? defaultOptions.autoDialPriority
53
57
  this.autoDialIntervalMs = init.autoDialInterval ?? defaultOptions.autoDialInterval
58
+ this.autoDialMaxQueueLength = init.maxQueueLength ?? defaultOptions.maxQueueLength
54
59
  this.started = false
55
- this.queue = new PQueue({
60
+ this.running = false
61
+ this.queue = new PeerJobQueue({
56
62
  concurrency: init.autoDialConcurrency ?? defaultOptions.autoDialConcurrency
57
63
  })
58
64
  this.queue.addListener('error', (err) => {
@@ -73,7 +79,7 @@ export class AutoDial implements Startable {
73
79
  }
74
80
 
75
81
  start (): void {
76
- this.autoDialInterval = setInterval(() => {
82
+ this.autoDialInterval = setTimeout(() => {
77
83
  this.autoDial()
78
84
  .catch(err => {
79
85
  log.error('error while autodialing', err)
@@ -92,8 +98,9 @@ export class AutoDial implements Startable {
92
98
  stop (): void {
93
99
  // clear the queue
94
100
  this.queue.clear()
95
- clearInterval(this.autoDialInterval)
101
+ clearTimeout(this.autoDialInterval)
96
102
  this.started = false
103
+ this.running = false
97
104
  }
98
105
 
99
106
  async autoDial (): Promise<void> {
@@ -103,12 +110,6 @@ export class AutoDial implements Startable {
103
110
 
104
111
  const connections = this.connectionManager.getConnectionsMap()
105
112
  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
- )
112
113
 
113
114
  // Already has enough connections
114
115
  if (numConnections >= this.minConnections) {
@@ -116,34 +117,64 @@ export class AutoDial implements Startable {
116
117
  return
117
118
  }
118
119
 
119
- log('not enough connections %d/%d - will dial peers to increase the number of connections', numConnections, this.minConnections)
120
+ if (this.queue.size > this.autoDialMaxQueueLength) {
121
+ log('not enough connections %d/%d but auto dial queue is full', numConnections, this.minConnections)
122
+ return
123
+ }
120
124
 
121
- // Sort peers on whether we know protocols or public keys for them
122
- const peers = await this.peerStore.all()
125
+ if (this.running) {
126
+ log('not enough connections %d/%d - but skipping autodial as it is already running', numConnections, this.minConnections)
127
+ return
128
+ }
123
129
 
124
- // Remove some peers
125
- const filteredPeers = peers.filter((peer) => {
126
- // Remove peers without addresses
127
- if (peer.addresses.length === 0) {
128
- return false
129
- }
130
+ this.running = true
130
131
 
131
- // remove peers we are already connected to
132
- if (connections.has(peer.id)) {
133
- return false
134
- }
132
+ log('not enough connections %d/%d - will dial peers to increase the number of connections', numConnections, this.minConnections)
135
133
 
136
- // remove peers we are already dialling
137
- if (dialQueue.has(peer.id)) {
138
- return false
139
- }
134
+ const dialQueue = new PeerSet(
135
+ // @ts-expect-error boolean filter removes falsy peer IDs
136
+ this.connectionManager.getDialQueue()
137
+ .map(queue => queue.peerId)
138
+ .filter(Boolean)
139
+ )
140
140
 
141
- return true
141
+ // Sort peers on whether we know protocols or public keys for them
142
+ const peers = await this.peerStore.all({
143
+ filters: [
144
+ // Remove some peers
145
+ (peer) => {
146
+ // Remove peers without addresses
147
+ if (peer.addresses.length === 0) {
148
+ log.trace('not autodialing %p because they have no addresses')
149
+ return false
150
+ }
151
+
152
+ // remove peers we are already connected to
153
+ if (connections.has(peer.id)) {
154
+ log.trace('not autodialing %p because they are already connected')
155
+ return false
156
+ }
157
+
158
+ // remove peers we are already dialling
159
+ if (dialQueue.has(peer.id)) {
160
+ log.trace('not autodialing %p because they are already being dialed')
161
+ return false
162
+ }
163
+
164
+ // remove peers already in the autodial queue
165
+ if (this.queue.hasJob(peer.id)) {
166
+ log.trace('not autodialing %p because they are already being autodialed')
167
+ return false
168
+ }
169
+
170
+ return true
171
+ }
172
+ ]
142
173
  })
143
174
 
144
175
  // shuffle the peers - this is so peers with the same tag values will be
145
176
  // dialled in a different order each time
146
- const shuffledPeers = filteredPeers.sort(() => Math.random() > 0.5 ? 1 : -1)
177
+ const shuffledPeers = peers.sort(() => Math.random() > 0.5 ? 1 : -1)
147
178
 
148
179
  // Sort shuffled peers by tag value
149
180
  const peerValues = new PeerMap<number>()
@@ -192,9 +223,22 @@ export class AutoDial implements Startable {
192
223
  // @ts-expect-error needs adding to the ConnectionManager interface
193
224
  priority: this.autoDialPriority
194
225
  })
226
+ }, {
227
+ peerId: peer.id
195
228
  }).catch(err => {
196
229
  log.error('could not connect to peerStore stored peer', err)
197
230
  })
198
231
  }
232
+
233
+ this.running = false
234
+
235
+ if (this.started) {
236
+ this.autoDialInterval = setTimeout(() => {
237
+ this.autoDial()
238
+ .catch(err => {
239
+ log.error('error while autodialing', err)
240
+ })
241
+ }, this.autoDialIntervalMs)
242
+ }
199
243
  }
200
244
  }
@@ -49,6 +49,11 @@ export const AUTO_DIAL_CONCURRENCY = 25
49
49
  */
50
50
  export const AUTO_DIAL_PRIORITY = 0
51
51
 
52
+ /**
53
+ * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#autoDialMaxQueueLength
54
+ */
55
+ export const AUTO_DIAL_MAX_QUEUE_LENGTH = 100
56
+
52
57
  /**
53
58
  * @see https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerConfig.html#inboundConnectionThreshold
54
59
  */
@@ -10,7 +10,7 @@ import { codes } from '../errors.js'
10
10
  import { getPeerAddress } from '../get-peer.js'
11
11
  import { AutoDial } from './auto-dial.js'
12
12
  import { ConnectionPruner } from './connection-pruner.js'
13
- import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_PRIORITY, DIAL_TIMEOUT, INBOUND_CONNECTION_THRESHOLD, MAX_CONNECTIONS, MAX_INCOMING_PENDING_CONNECTIONS, MAX_PARALLEL_DIALS, MAX_PEER_ADDRS_TO_DIAL, MIN_CONNECTIONS } from './constants.js'
13
+ import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_MAX_QUEUE_LENGTH, AUTO_DIAL_PRIORITY, DIAL_TIMEOUT, INBOUND_CONNECTION_THRESHOLD, MAX_CONNECTIONS, MAX_INCOMING_PENDING_CONNECTIONS, MAX_PARALLEL_DIALS, MAX_PEER_ADDRS_TO_DIAL, MIN_CONNECTIONS } from './constants.js'
14
14
  import { DialQueue } from './dial-queue.js'
15
15
  import type { Connection, MultiaddrConnection } from '@libp2p/interface-connection'
16
16
  import type { ConnectionGater } from '@libp2p/interface-connection-gater'
@@ -18,7 +18,7 @@ import type { ConnectionManager } from '@libp2p/interface-connection-manager'
18
18
  import type { PendingDial, AddressSorter, Libp2pEvents } from '@libp2p/interface-libp2p'
19
19
  import type { Metrics } from '@libp2p/interface-metrics'
20
20
  import type { PeerId } from '@libp2p/interface-peer-id'
21
- import type { PeerStore } from '@libp2p/interface-peer-store'
21
+ import type { Peer, PeerStore } from '@libp2p/interface-peer-store'
22
22
  import type { TransportManager } from '@libp2p/interface-transport'
23
23
  import type { AbortOptions } from '@libp2p/interfaces'
24
24
  import type { EventEmitter } from '@libp2p/interfaces/events'
@@ -61,6 +61,12 @@ export interface ConnectionManagerInit {
61
61
  */
62
62
  autoDialPriority?: number
63
63
 
64
+ /**
65
+ * Limit the maximum number of peers to dial when trying to keep the number of
66
+ * open connections above `minConnections`. (default: 100)
67
+ */
68
+ autoDialMaxQueueLength?: number
69
+
64
70
  /**
65
71
  * Sort the known addresses of a peer before trying to dial, By default public
66
72
  * addresses will be dialled before private (e.g. loopback or LAN) addresses.
@@ -136,7 +142,8 @@ const defaultOptions = {
136
142
  inboundConnectionThreshold: INBOUND_CONNECTION_THRESHOLD,
137
143
  maxIncomingPendingConnections: MAX_INCOMING_PENDING_CONNECTIONS,
138
144
  autoDialConcurrency: AUTO_DIAL_CONCURRENCY,
139
- autoDialPriority: AUTO_DIAL_PRIORITY
145
+ autoDialPriority: AUTO_DIAL_PRIORITY,
146
+ autoDialMaxQueueLength: AUTO_DIAL_MAX_QUEUE_LENGTH
140
147
  }
141
148
 
142
149
  export interface DefaultConnectionManagerComponents {
@@ -217,7 +224,8 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
217
224
  }, {
218
225
  minConnections,
219
226
  autoDialConcurrency: init.autoDialConcurrency ?? defaultOptions.autoDialConcurrency,
220
- autoDialPriority: init.autoDialPriority ?? defaultOptions.autoDialPriority
227
+ autoDialPriority: init.autoDialPriority ?? defaultOptions.autoDialPriority,
228
+ maxQueueLength: init.autoDialMaxQueueLength ?? defaultOptions.autoDialMaxQueueLength
221
229
  })
222
230
 
223
231
  // controls what happens when we have too many connections
@@ -344,17 +352,15 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
344
352
  // re-connect to any peers with the KEEP_ALIVE tag
345
353
  void Promise.resolve()
346
354
  .then(async () => {
347
- const keepAlivePeers: PeerId[] = []
348
-
349
- for (const peer of await this.peerStore.all()) {
350
- if (peer.tags.has(KEEP_ALIVE)) {
351
- keepAlivePeers.push(peer.id)
352
- }
353
- }
355
+ const keepAlivePeers: Peer[] = await this.peerStore.all({
356
+ filters: [(peer) => {
357
+ return peer.tags.has(KEEP_ALIVE)
358
+ }]
359
+ })
354
360
 
355
361
  await Promise.all(
356
362
  keepAlivePeers.map(async peer => {
357
- await this.openConnection(peer)
363
+ await this.openConnection(peer.id)
358
364
  .catch(err => {
359
365
  log.error(err)
360
366
  })
@@ -429,79 +429,98 @@ export class DefaultIdentifyService implements Startable {
429
429
  }
430
430
 
431
431
  async #consumeIdentifyMessage (remotePeer: PeerId, message: Identify): Promise<SignedPeerRecord | undefined> {
432
+ log('received identify from %p', remotePeer)
433
+
432
434
  if (message == null) {
433
435
  throw new Error('Message was null or undefined')
434
436
  }
435
437
 
436
- log('received identify from %p', remotePeer)
437
-
438
- if (message.signedPeerRecord == null) {
439
- return
438
+ const peer = {
439
+ addresses: message.listenAddrs.map(buf => ({
440
+ isCertified: false,
441
+ multiaddr: multiaddr(buf)
442
+ })),
443
+ protocols: message.protocols,
444
+ metadata: new Map(),
445
+ peerRecordEnvelope: message.signedPeerRecord
440
446
  }
441
447
 
442
- let peerRecordEnvelope = message.signedPeerRecord
443
- const envelope = await RecordEnvelope.openAndCertify(peerRecordEnvelope, PeerRecord.DOMAIN)
444
- let peerRecord = PeerRecord.createFromProtobuf(envelope.payload)
448
+ let output: SignedPeerRecord | undefined
445
449
 
446
- // Verify peerId
447
- if (!peerRecord.peerId.equals(envelope.peerId)) {
448
- throw new Error('signing key does not match PeerId in the PeerRecord')
449
- }
450
+ // if the peer record has been sent, prefer the addresses in the record as they are signed by the remote peer
451
+ if (message.signedPeerRecord != null) {
452
+ log('received signedPeerRecord in push from %p', remotePeer)
450
453
 
451
- // Make sure remote peer is the one sending the record
452
- if (!remotePeer.equals(peerRecord.peerId)) {
453
- throw new Error('signing key does not match remote PeerId')
454
- }
454
+ let peerRecordEnvelope = message.signedPeerRecord
455
+ const envelope = await RecordEnvelope.openAndCertify(peerRecordEnvelope, PeerRecord.DOMAIN)
456
+ let peerRecord = PeerRecord.createFromProtobuf(envelope.payload)
455
457
 
456
- let peer: Peer | undefined
458
+ // Verify peerId
459
+ if (!peerRecord.peerId.equals(envelope.peerId)) {
460
+ throw new Error('signing key does not match PeerId in the PeerRecord')
461
+ }
457
462
 
458
- try {
459
- peer = await this.peerStore.get(peerRecord.peerId)
460
- } catch (err: any) {
461
- if (err.code !== 'ERR_NOT_FOUND') {
462
- throw err
463
+ // Make sure remote peer is the one sending the record
464
+ if (!remotePeer.equals(peerRecord.peerId)) {
465
+ throw new Error('signing key does not match remote PeerId')
466
+ }
467
+
468
+ let existingPeer: Peer | undefined
469
+
470
+ try {
471
+ existingPeer = await this.peerStore.get(peerRecord.peerId)
472
+ } catch (err: any) {
473
+ if (err.code !== 'ERR_NOT_FOUND') {
474
+ throw err
475
+ }
463
476
  }
464
- }
465
477
 
466
- log('received signedPeerRecord in push from %p', remotePeer)
467
- const metadata = peer?.metadata ?? new Map()
478
+ if (existingPeer != null) {
479
+ // don't lose any existing metadata
480
+ peer.metadata = existingPeer.metadata
468
481
 
469
- if (peer?.peerRecordEnvelope != null) {
470
- const storedEnvelope = await RecordEnvelope.createFromProtobuf(peer.peerRecordEnvelope)
471
- const storedRecord = PeerRecord.createFromProtobuf(storedEnvelope.payload)
482
+ // if we have previously received a signed record for this peer, compare it to the incoming one
483
+ if (existingPeer.peerRecordEnvelope != null) {
484
+ const storedEnvelope = await RecordEnvelope.createFromProtobuf(existingPeer.peerRecordEnvelope)
485
+ const storedRecord = PeerRecord.createFromProtobuf(storedEnvelope.payload)
472
486
 
473
- // ensure seq is greater than, or equal to, the last received
474
- if (storedRecord.seqNumber >= peerRecord.seqNumber) {
475
- log('sequence number was lower or equal to existing sequence number - stored: %d received: %d', storedRecord.seqNumber, peerRecord.seqNumber)
476
- peerRecord = storedRecord
477
- peerRecordEnvelope = peer.peerRecordEnvelope
487
+ // ensure seq is greater than, or equal to, the last received
488
+ if (storedRecord.seqNumber >= peerRecord.seqNumber) {
489
+ log('sequence number was lower or equal to existing sequence number - stored: %d received: %d', storedRecord.seqNumber, peerRecord.seqNumber)
490
+ peerRecord = storedRecord
491
+ peerRecordEnvelope = existingPeer.peerRecordEnvelope
492
+ }
493
+ }
478
494
  }
495
+
496
+ // store the signed record for next time
497
+ peer.peerRecordEnvelope = peerRecordEnvelope
498
+
499
+ // override the stored addresses with the signed multiaddrs
500
+ peer.addresses = peerRecord.multiaddrs.map(multiaddr => ({
501
+ isCertified: true,
502
+ multiaddr
503
+ }))
504
+
505
+ output = {
506
+ seq: peerRecord.seqNumber,
507
+ addresses: peerRecord.multiaddrs
508
+ }
509
+ } else {
510
+ log('%p did not send a signed peer record', remotePeer)
479
511
  }
480
512
 
481
513
  if (message.agentVersion != null) {
482
- metadata.set('AgentVersion', uint8ArrayFromString(message.agentVersion))
514
+ peer.metadata.set('AgentVersion', uint8ArrayFromString(message.agentVersion))
483
515
  }
484
516
 
485
517
  if (message.protocolVersion != null) {
486
- metadata.set('ProtocolVersion', uint8ArrayFromString(message.protocolVersion))
518
+ peer.metadata.set('ProtocolVersion', uint8ArrayFromString(message.protocolVersion))
487
519
  }
488
520
 
489
- await this.peerStore.patch(peerRecord.peerId, {
490
- peerRecordEnvelope,
491
- protocols: message.protocols,
492
- addresses: peerRecord.multiaddrs.map(multiaddr => ({
493
- isCertified: true,
494
- multiaddr
495
- })),
496
- metadata
497
- })
498
-
499
- log('consumed signedPeerRecord sent in push from %p', remotePeer)
521
+ await this.peerStore.patch(remotePeer, peer)
500
522
 
501
- return {
502
- seq: peerRecord.seqNumber,
503
- addresses: peerRecord.multiaddrs
504
- }
523
+ return output
505
524
  }
506
525
  }
507
526
 
@@ -142,7 +142,7 @@ class UPnPNAT implements Startable {
142
142
  continue
143
143
  }
144
144
 
145
- const client = await this._getClient()
145
+ const client = this._getClient()
146
146
  const publicIp = this.externalAddress ?? await client.externalIp()
147
147
  const isPrivate = isPrivateIp(publicIp)
148
148
 
@@ -173,12 +173,12 @@ class UPnPNAT implements Startable {
173
173
  }
174
174
  }
175
175
 
176
- async _getClient (): Promise<NatAPI> {
176
+ _getClient (): NatAPI {
177
177
  if (this.client != null) {
178
178
  return this.client
179
179
  }
180
180
 
181
- this.client = await upnpNat({
181
+ this.client = upnpNat({
182
182
  description: this.description,
183
183
  ttl: this.ttl,
184
184
  keepAlive: this.keepAlive,
@@ -0,0 +1,119 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+
3
+ import { CodeError } from '@libp2p/interfaces/errors'
4
+ import PQueue from 'p-queue'
5
+ import { codes } from '../errors.js'
6
+ import type { PeerId } from '@libp2p/interface-peer-id'
7
+ import type { QueueAddOptions, Options, Queue } from 'p-queue'
8
+
9
+ // Port of lower_bound from https://en.cppreference.com/w/cpp/algorithm/lower_bound
10
+ // Used to compute insertion index to keep queue sorted after insertion
11
+ function lowerBound<T> (array: readonly T[], value: T, comparator: (a: T, b: T) => number): number {
12
+ let first = 0
13
+ let count = array.length
14
+
15
+ while (count > 0) {
16
+ const step = Math.trunc(count / 2)
17
+ let it = first + step
18
+
19
+ if (comparator(array[it]!, value) <= 0) {
20
+ first = ++it
21
+ count -= step + 1
22
+ } else {
23
+ count = step
24
+ }
25
+ }
26
+
27
+ return first
28
+ }
29
+
30
+ interface RunFunction { (): Promise<unknown> }
31
+
32
+ export interface PeerPriorityQueueOptions extends QueueAddOptions {
33
+ peerId: PeerId
34
+ }
35
+
36
+ interface PeerJob {
37
+ priority: number
38
+ peerId: PeerId
39
+ run: RunFunction
40
+ }
41
+
42
+ /**
43
+ * Port of https://github.com/sindresorhus/p-queue/blob/main/source/priority-queue.ts
44
+ * that adds support for filtering jobs by peer id
45
+ */
46
+ class PeerPriorityQueue implements Queue<RunFunction, PeerPriorityQueueOptions> {
47
+ readonly #queue: PeerJob[] = []
48
+
49
+ enqueue (run: RunFunction, options?: Partial<PeerPriorityQueueOptions>): void {
50
+ const peerId = options?.peerId
51
+ const priority = options?.priority ?? 0
52
+
53
+ if (peerId == null) {
54
+ throw new CodeError('missing peer id', codes.ERR_INVALID_PARAMETERS)
55
+ }
56
+
57
+ const element: PeerJob = {
58
+ priority,
59
+ peerId,
60
+ run
61
+ }
62
+
63
+ if (this.size > 0 && this.#queue[this.size - 1]!.priority >= priority) {
64
+ this.#queue.push(element)
65
+ return
66
+ }
67
+
68
+ const index = lowerBound(
69
+ this.#queue, element,
70
+ (a: Readonly<PeerPriorityQueueOptions>, b: Readonly<PeerPriorityQueueOptions>) => b.priority! - a.priority!
71
+ )
72
+ this.#queue.splice(index, 0, element)
73
+ }
74
+
75
+ dequeue (): RunFunction | undefined {
76
+ const item = this.#queue.shift()
77
+ return item?.run
78
+ }
79
+
80
+ filter (options: Readonly<Partial<PeerPriorityQueueOptions>>): RunFunction[] {
81
+ if (options.peerId != null) {
82
+ const peerId = options.peerId
83
+
84
+ return this.#queue.filter(
85
+ (element: Readonly<PeerPriorityQueueOptions>) => peerId.equals(element.peerId)
86
+ ).map((element: Readonly<{ run: RunFunction }>) => element.run)
87
+ }
88
+
89
+ return this.#queue.filter(
90
+ (element: Readonly<PeerPriorityQueueOptions>) => element.priority === options.priority
91
+ ).map((element: Readonly<{ run: RunFunction }>) => element.run)
92
+ }
93
+
94
+ get size (): number {
95
+ return this.#queue.length
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Extends PQueue to add support for querying queued jobs by peer id
101
+ */
102
+ export class PeerJobQueue extends PQueue<PeerPriorityQueue, PeerPriorityQueueOptions> {
103
+ constructor (options: Options<PeerPriorityQueue, PeerPriorityQueueOptions> = {}) {
104
+ super({
105
+ ...options,
106
+ queueClass: PeerPriorityQueue
107
+ })
108
+ }
109
+
110
+ /**
111
+ * Returns true if this queue has a job for the passed peer id that has not yet
112
+ * started to run
113
+ */
114
+ hasJob (peerId: PeerId): boolean {
115
+ return this.sizeBy({
116
+ peerId
117
+ }) > 0
118
+ }
119
+ }
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
- export const version = '0.45.4'
1
+ export const version = '0.45.5-775f8928'
2
2
  export const name = 'libp2p'
@@ -1,58 +0,0 @@
1
- {
2
- "AutoNATComponents": "https://libp2p.github.io/js-libp2p/interfaces/autonat.AutoNATComponents.html",
3
- "AutoNATServiceInit": "https://libp2p.github.io/js-libp2p/interfaces/autonat.AutoNATServiceInit.html",
4
- "autoNATService": "https://libp2p.github.io/js-libp2p/functions/autonat.autoNATService.html",
5
- "codec": "https://libp2p.github.io/js-libp2p/functions/circuit_relay._internal_.Limit.codec.html",
6
- "decode": "https://libp2p.github.io/js-libp2p/functions/circuit_relay._internal_.Limit.decode.html",
7
- "encode": "https://libp2p.github.io/js-libp2p/functions/circuit_relay._internal_.Limit.encode.html",
8
- "AdvertServiceComponents": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay._internal_.AdvertServiceComponents.html",
9
- "AdvertServiceInit": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay._internal_.AdvertServiceInit.html",
10
- "CircuitRelayServerComponents": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay._internal_.CircuitRelayServerComponents.html",
11
- "CircuitRelayServerInit": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay._internal_.CircuitRelayServerInit.html",
12
- "CircuitRelayTransportComponents": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay._internal_.CircuitRelayTransportComponents.html",
13
- "CircuitRelayTransportInit": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay._internal_.CircuitRelayTransportInit.html",
14
- "Limit": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay._internal_.Limit-1.html",
15
- "RelayDiscoveryComponents": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay._internal_.RelayDiscoveryComponents.html",
16
- "RelayStoreInit": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay._internal_.RelayStoreInit.html",
17
- "ReservationStoreInit": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay._internal_.ReservationStoreInit.html",
18
- "CircuitRelayService": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay.CircuitRelayService.html",
19
- "CircuitRelayServiceEvents": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay.CircuitRelayServiceEvents.html",
20
- "RelayReservation": "https://libp2p.github.io/js-libp2p/interfaces/circuit_relay.RelayReservation.html",
21
- "circuitRelayServer": "https://libp2p.github.io/js-libp2p/functions/circuit_relay.circuitRelayServer.html",
22
- "circuitRelayTransport": "https://libp2p.github.io/js-libp2p/functions/circuit_relay.circuitRelayTransport.html",
23
- "FetchService": "https://libp2p.github.io/js-libp2p/interfaces/fetch.FetchService.html",
24
- "FetchServiceComponents": "https://libp2p.github.io/js-libp2p/interfaces/fetch.FetchServiceComponents.html",
25
- "FetchServiceInit": "https://libp2p.github.io/js-libp2p/interfaces/fetch.FetchServiceInit.html",
26
- "HandleMessageOptions": "https://libp2p.github.io/js-libp2p/interfaces/fetch.HandleMessageOptions.html",
27
- "LookupFunction": "https://libp2p.github.io/js-libp2p/interfaces/fetch.LookupFunction.html",
28
- "fetchService": "https://libp2p.github.io/js-libp2p/functions/fetch.fetchService-1.html",
29
- "DefaultIdentifyService": "https://libp2p.github.io/js-libp2p/classes/identify._internal_.DefaultIdentifyService.html",
30
- "Identify": "https://libp2p.github.io/js-libp2p/interfaces/identify._internal_.Identify-1.html",
31
- "IdentifyServiceComponents": "https://libp2p.github.io/js-libp2p/interfaces/identify.IdentifyServiceComponents.html",
32
- "IdentifyServiceInit": "https://libp2p.github.io/js-libp2p/interfaces/identify.IdentifyServiceInit.html",
33
- "Message": "https://libp2p.github.io/js-libp2p/variables/identify.Message.html",
34
- "multicodecs": "https://libp2p.github.io/js-libp2p/variables/identify.multicodecs.html",
35
- "identifyService": "https://libp2p.github.io/js-libp2p/functions/identify.identifyService.html",
36
- "AddressFilter": "https://libp2p.github.io/js-libp2p/interfaces/index._internal_.AddressFilter.html",
37
- "AddressManagerInit": "https://libp2p.github.io/js-libp2p/interfaces/index._internal_.AddressManagerInit.html",
38
- "Components": "https://libp2p.github.io/js-libp2p/interfaces/index._internal_.Components.html",
39
- "ConnectionManagerInit": "https://libp2p.github.io/js-libp2p/interfaces/index._internal_.ConnectionManagerInit.html",
40
- "TransportManagerInit": "https://libp2p.github.io/js-libp2p/interfaces/index._internal_.TransportManagerInit.html",
41
- "Libp2pInit": "https://libp2p.github.io/js-libp2p/interfaces/index.Libp2pInit.html",
42
- "Libp2pOptions": "https://libp2p.github.io/js-libp2p/types/index.Libp2pOptions.html",
43
- "ServiceFactoryMap": "https://libp2p.github.io/js-libp2p/types/index.ServiceFactoryMap.html",
44
- "createLibp2p": "https://libp2p.github.io/js-libp2p/functions/index.createLibp2p.html",
45
- "plaintext": "https://libp2p.github.io/js-libp2p/functions/insecure.plaintext.html",
46
- "PingService": "https://libp2p.github.io/js-libp2p/interfaces/ping.PingService.html",
47
- "PingServiceComponents": "https://libp2p.github.io/js-libp2p/interfaces/ping.PingServiceComponents.html",
48
- "PingServiceInit": "https://libp2p.github.io/js-libp2p/interfaces/ping.PingServiceInit.html",
49
- "pingService": "https://libp2p.github.io/js-libp2p/functions/ping.pingService-1.html",
50
- "ProtectorInit": "https://libp2p.github.io/js-libp2p/interfaces/pnet.ProtectorInit.html",
51
- "generateKey": "https://libp2p.github.io/js-libp2p/functions/pnet.generateKey.html",
52
- "preSharedKey": "https://libp2p.github.io/js-libp2p/functions/pnet.preSharedKey.html",
53
- "UPnPNAT": "https://libp2p.github.io/js-libp2p/classes/upnp_nat._internal_.UPnPNAT.html",
54
- "PMPOptions": "https://libp2p.github.io/js-libp2p/interfaces/upnp_nat.PMPOptions.html",
55
- "UPnPNATComponents": "https://libp2p.github.io/js-libp2p/interfaces/upnp_nat.UPnPNATComponents.html",
56
- "UPnPNATInit": "https://libp2p.github.io/js-libp2p/interfaces/upnp_nat.UPnPNATInit.html",
57
- "uPnPNATService": "https://libp2p.github.io/js-libp2p/functions/upnp_nat.uPnPNATService.html"
58
- }