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.
- package/dist/index.min.js +21 -21
- package/dist/src/autonat/index.js +4 -4
- package/dist/src/circuit-relay/transport/discovery.d.ts.map +1 -1
- package/dist/src/circuit-relay/transport/discovery.js +11 -4
- package/dist/src/circuit-relay/transport/discovery.js.map +1 -1
- package/dist/src/circuit-relay/transport/reservation-store.d.ts +5 -0
- package/dist/src/circuit-relay/transport/reservation-store.d.ts.map +1 -1
- package/dist/src/circuit-relay/transport/reservation-store.js +14 -2
- package/dist/src/circuit-relay/transport/reservation-store.js.map +1 -1
- package/dist/src/connection-manager/auto-dial.d.ts +3 -0
- package/dist/src/connection-manager/auto-dial.d.ts.map +1 -1
- package/dist/src/connection-manager/auto-dial.js +64 -27
- package/dist/src/connection-manager/auto-dial.js.map +1 -1
- package/dist/src/connection-manager/constants.d.ts +4 -0
- package/dist/src/connection-manager/constants.d.ts.map +1 -1
- package/dist/src/connection-manager/constants.js +4 -0
- package/dist/src/connection-manager/constants.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +5 -0
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +11 -10
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/identify/identify.d.ts.map +1 -1
- package/dist/src/identify/identify.js +65 -49
- package/dist/src/identify/identify.js.map +1 -1
- package/dist/src/upnp-nat/index.d.ts +1 -1
- package/dist/src/upnp-nat/index.d.ts.map +1 -1
- package/dist/src/upnp-nat/index.js +3 -3
- package/dist/src/upnp-nat/index.js.map +1 -1
- package/dist/src/utils/peer-job-queue.d.ts +33 -0
- package/dist/src/utils/peer-job-queue.d.ts.map +1 -0
- package/dist/src/utils/peer-job-queue.js +82 -0
- package/dist/src/utils/peer-job-queue.js.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.d.ts.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/package.json +7 -6
- package/src/autonat/index.ts +4 -4
- package/src/circuit-relay/transport/discovery.ts +11 -4
- package/src/circuit-relay/transport/reservation-store.ts +22 -3
- package/src/connection-manager/auto-dial.ts +75 -31
- package/src/connection-manager/constants.ts +5 -0
- package/src/connection-manager/index.ts +18 -12
- package/src/identify/identify.ts +68 -49
- package/src/upnp-nat/index.ts +3 -3
- package/src/utils/peer-job-queue.ts +119 -0
- package/src/version.ts +1 -1
- 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
|
|
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:
|
|
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.
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
122
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
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 =
|
|
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:
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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
|
})
|
package/src/identify/identify.ts
CHANGED
|
@@ -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
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
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
|
|
443
|
-
const envelope = await RecordEnvelope.openAndCertify(peerRecordEnvelope, PeerRecord.DOMAIN)
|
|
444
|
-
let peerRecord = PeerRecord.createFromProtobuf(envelope.payload)
|
|
448
|
+
let output: SignedPeerRecord | undefined
|
|
445
449
|
|
|
446
|
-
//
|
|
447
|
-
if (
|
|
448
|
-
|
|
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
|
-
|
|
452
|
-
|
|
453
|
-
|
|
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
|
-
|
|
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
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
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
|
-
|
|
467
|
-
|
|
478
|
+
if (existingPeer != null) {
|
|
479
|
+
// don't lose any existing metadata
|
|
480
|
+
peer.metadata = existingPeer.metadata
|
|
468
481
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
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
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
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(
|
|
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
|
|
package/src/upnp-nat/index.ts
CHANGED
|
@@ -142,7 +142,7 @@ class UPnPNAT implements Startable {
|
|
|
142
142
|
continue
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
const client =
|
|
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
|
-
|
|
176
|
+
_getClient (): NatAPI {
|
|
177
177
|
if (this.client != null) {
|
|
178
178
|
return this.client
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
this.client =
|
|
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.
|
|
1
|
+
export const version = '0.45.5-775f8928'
|
|
2
2
|
export const name = 'libp2p'
|
package/dist/typedoc-urls.json
DELETED
|
@@ -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
|
-
}
|