libp2p 1.0.12 → 1.1.0-528d73781
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 +34 -34
- package/dist/src/connection-manager/auto-dial.d.ts +2 -1
- package/dist/src/connection-manager/auto-dial.d.ts.map +1 -1
- package/dist/src/connection-manager/auto-dial.js +8 -6
- package/dist/src/connection-manager/auto-dial.js.map +1 -1
- package/dist/src/connection-manager/dial-queue.d.ts +9 -12
- package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
- package/dist/src/connection-manager/dial-queue.js +113 -242
- package/dist/src/connection-manager/dial-queue.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +14 -1
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/connection-manager/utils.d.ts +0 -2
- package/dist/src/connection-manager/utils.d.ts.map +1 -1
- package/dist/src/connection-manager/utils.js +0 -15
- package/dist/src/connection-manager/utils.js.map +1 -1
- 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 +19 -20
- package/src/connection-manager/auto-dial.ts +11 -8
- package/src/connection-manager/dial-queue.ts +128 -275
- package/src/connection-manager/index.ts +17 -2
- package/src/connection-manager/utils.ts +0 -20
- package/src/version.ts +1 -1
- package/dist/typedoc-urls.json +0 -10
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable max-depth */
|
|
2
|
+
import { CodeError, AggregateCodeError, ERR_TIMEOUT, setMaxListeners } from '@libp2p/interface'
|
|
2
3
|
import { PeerMap } from '@libp2p/peer-collections'
|
|
3
4
|
import { defaultAddressSort } from '@libp2p/utils/address-sort'
|
|
4
|
-
import {
|
|
5
|
+
import { Queue, type QueueAddOptions } from '@libp2p/utils/queue'
|
|
6
|
+
import { type Multiaddr, type Resolver, resolvers, multiaddr } from '@multiformats/multiaddr'
|
|
5
7
|
import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers'
|
|
6
8
|
import { type ClearableSignal, anySignal } from 'any-signal'
|
|
7
|
-
import pDefer from 'p-defer'
|
|
8
|
-
import PQueue from 'p-queue'
|
|
9
9
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
10
10
|
import { codes } from '../errors.js'
|
|
11
11
|
import { getPeerAddress } from '../get-peer.js'
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
MAX_PEER_ADDRS_TO_DIAL,
|
|
16
16
|
LAST_DIAL_FAILURE_KEY
|
|
17
17
|
} from './constants.js'
|
|
18
|
-
import {
|
|
19
|
-
import type { AddressSorter, AbortOptions,
|
|
18
|
+
import { resolveMultiaddrs } from './utils.js'
|
|
19
|
+
import type { AddressSorter, AbortOptions, ComponentLogger, Logger, Connection, ConnectionGater, Metrics, PeerId, Address, PeerStore } from '@libp2p/interface'
|
|
20
20
|
import type { TransportManager } from '@libp2p/interface-internal'
|
|
21
21
|
|
|
22
22
|
export interface PendingDialTarget {
|
|
@@ -29,8 +29,9 @@ export interface DialOptions extends AbortOptions {
|
|
|
29
29
|
force?: boolean
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
interface
|
|
33
|
-
|
|
32
|
+
interface DialQueueJobOptions extends QueueAddOptions {
|
|
33
|
+
peerId?: PeerId
|
|
34
|
+
multiaddrs: Set<string>
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
interface DialerInit {
|
|
@@ -62,8 +63,7 @@ interface DialQueueComponents {
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
export class DialQueue {
|
|
65
|
-
public
|
|
66
|
-
public queue: PQueue
|
|
66
|
+
public queue: Queue<Connection, DialQueueJobOptions>
|
|
67
67
|
private readonly peerId: PeerId
|
|
68
68
|
private readonly peerStore: PeerStore
|
|
69
69
|
private readonly connectionGater: ConnectionGater
|
|
@@ -71,8 +71,6 @@ export class DialQueue {
|
|
|
71
71
|
private readonly addressSorter: AddressSorter
|
|
72
72
|
private readonly maxPeerAddrsToDial: number
|
|
73
73
|
private readonly dialTimeout: number
|
|
74
|
-
private readonly inProgressDialCount?: Metric
|
|
75
|
-
private readonly pendingDialCount?: Metric
|
|
76
74
|
private shutDownController: AbortController
|
|
77
75
|
private readonly connections: PeerMap<Connection[]>
|
|
78
76
|
private readonly log: Logger
|
|
@@ -92,49 +90,19 @@ export class DialQueue {
|
|
|
92
90
|
|
|
93
91
|
setMaxListeners(Infinity, this.shutDownController.signal)
|
|
94
92
|
|
|
95
|
-
this.pendingDialCount = components.metrics?.registerMetric('libp2p_dial_queue_pending_dials')
|
|
96
|
-
this.inProgressDialCount = components.metrics?.registerMetric('libp2p_dial_queue_in_progress_dials')
|
|
97
|
-
this.pendingDials = []
|
|
98
|
-
|
|
99
93
|
for (const [key, value] of Object.entries(init.resolvers ?? {})) {
|
|
100
94
|
resolvers.set(key, value)
|
|
101
95
|
}
|
|
102
96
|
|
|
103
97
|
// controls dial concurrency
|
|
104
|
-
this.queue = new
|
|
105
|
-
concurrency: init.maxParallelDials ?? defaultOptions.maxParallelDials
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
// a job was added to the queue
|
|
109
|
-
this.queue.on('add', () => {
|
|
110
|
-
this.pendingDialCount?.update(this.queue.size)
|
|
111
|
-
this.inProgressDialCount?.update(this.queue.pending)
|
|
112
|
-
})
|
|
113
|
-
// a queued job started
|
|
114
|
-
this.queue.on('active', () => {
|
|
115
|
-
this.pendingDialCount?.update(this.queue.size)
|
|
116
|
-
this.inProgressDialCount?.update(this.queue.pending)
|
|
117
|
-
})
|
|
118
|
-
// a started job completed without error
|
|
119
|
-
this.queue.on('completed', () => {
|
|
120
|
-
this.pendingDialCount?.update(this.queue.size)
|
|
121
|
-
this.inProgressDialCount?.update(this.queue.pending)
|
|
98
|
+
this.queue = new Queue({
|
|
99
|
+
concurrency: init.maxParallelDials ?? defaultOptions.maxParallelDials,
|
|
100
|
+
metricName: 'libp2p_dial_queue',
|
|
101
|
+
metrics: components.metrics
|
|
122
102
|
})
|
|
123
103
|
// a started job errored
|
|
124
|
-
this.queue.
|
|
125
|
-
this.log.error('error in dial queue',
|
|
126
|
-
this.pendingDialCount?.update(this.queue.size)
|
|
127
|
-
this.inProgressDialCount?.update(this.queue.pending)
|
|
128
|
-
})
|
|
129
|
-
// all queued jobs have been started
|
|
130
|
-
this.queue.on('empty', () => {
|
|
131
|
-
this.pendingDialCount?.update(this.queue.size)
|
|
132
|
-
this.inProgressDialCount?.update(this.queue.pending)
|
|
133
|
-
})
|
|
134
|
-
// add started jobs have run and the queue is empty
|
|
135
|
-
this.queue.on('idle', () => {
|
|
136
|
-
this.pendingDialCount?.update(this.queue.size)
|
|
137
|
-
this.inProgressDialCount?.update(this.queue.pending)
|
|
104
|
+
this.queue.addEventListener('error', (event) => {
|
|
105
|
+
this.log.error('error in dial queue', event.detail)
|
|
138
106
|
})
|
|
139
107
|
}
|
|
140
108
|
|
|
@@ -147,7 +115,7 @@ export class DialQueue {
|
|
|
147
115
|
*/
|
|
148
116
|
stop (): void {
|
|
149
117
|
this.shutDownController.abort()
|
|
150
|
-
this.queue.
|
|
118
|
+
this.queue.abort()
|
|
151
119
|
}
|
|
152
120
|
|
|
153
121
|
/**
|
|
@@ -159,42 +127,25 @@ export class DialQueue {
|
|
|
159
127
|
* Where a list of multiaddrs is passed, if any contain a peer id then all
|
|
160
128
|
* multiaddrs in the list must contain the same peer id.
|
|
161
129
|
*
|
|
162
|
-
* The dial to the first address that is successfully able to upgrade a
|
|
163
|
-
* will be used, all other dials will be aborted when that happens.
|
|
130
|
+
* The dial to the first address that is successfully able to upgrade a
|
|
131
|
+
* connection will be used, all other dials will be aborted when that happens.
|
|
164
132
|
*/
|
|
165
133
|
async dial (peerIdOrMultiaddr: PeerId | Multiaddr | Multiaddr[], options: DialOptions = {}): Promise<Connection> {
|
|
166
134
|
const { peerId, multiaddrs } = getPeerAddress(peerIdOrMultiaddr)
|
|
167
135
|
|
|
168
|
-
const addrs: Address[] = multiaddrs.map(multiaddr => ({
|
|
169
|
-
multiaddr,
|
|
170
|
-
isCertified: false
|
|
171
|
-
}))
|
|
172
|
-
|
|
173
|
-
// create abort conditions - need to do this before `calculateMultiaddrs` as we may be about to
|
|
174
|
-
// resolve a dns addr which can time out
|
|
175
|
-
const signal = this.createDialAbortControllers(options.signal)
|
|
176
|
-
let addrsToDial: Address[]
|
|
177
|
-
|
|
178
|
-
try {
|
|
179
|
-
// load addresses from address book, resolve and dnsaddrs, filter undiallables, add peer IDs, etc
|
|
180
|
-
addrsToDial = await this.calculateMultiaddrs(peerId, addrs, {
|
|
181
|
-
...options,
|
|
182
|
-
signal
|
|
183
|
-
})
|
|
184
|
-
} catch (err) {
|
|
185
|
-
signal.clear()
|
|
186
|
-
throw err
|
|
187
|
-
}
|
|
188
|
-
|
|
189
136
|
// make sure we don't have an existing connection to any of the addresses we
|
|
190
137
|
// are about to dial
|
|
191
|
-
|
|
138
|
+
const existingConnection = Array.from(this.connections.values()).flat().find(conn => {
|
|
192
139
|
if (options.force === true) {
|
|
193
140
|
return false
|
|
194
141
|
}
|
|
195
142
|
|
|
196
|
-
|
|
197
|
-
return
|
|
143
|
+
if (conn.remotePeer.equals(peerId)) {
|
|
144
|
+
return true
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return multiaddrs.find(addr => {
|
|
148
|
+
return addr.equals(conn.remoteAddr)
|
|
198
149
|
})
|
|
199
150
|
})
|
|
200
151
|
|
|
@@ -205,15 +156,22 @@ export class DialQueue {
|
|
|
205
156
|
|
|
206
157
|
// ready to dial, all async work finished - make sure we don't have any
|
|
207
158
|
// pending dials in progress for this peer or set of multiaddrs
|
|
208
|
-
const existingDial = this.
|
|
209
|
-
|
|
210
|
-
if (dial.peerId != null && peerId != null && dial.peerId.equals(peerId)) {
|
|
159
|
+
const existingDial = this.queue.queue.find(job => {
|
|
160
|
+
if (peerId?.equals(job.options.peerId) === true) {
|
|
211
161
|
return true
|
|
212
162
|
}
|
|
213
163
|
|
|
214
|
-
//
|
|
215
|
-
|
|
216
|
-
|
|
164
|
+
// does the dial contain any of the target multiaddrs?
|
|
165
|
+
const addresses = job.options.multiaddrs
|
|
166
|
+
|
|
167
|
+
if (addresses == null) {
|
|
168
|
+
return false
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
for (const multiaddr of multiaddrs) {
|
|
172
|
+
if (addresses.has(multiaddr.toString())) {
|
|
173
|
+
return true
|
|
174
|
+
}
|
|
217
175
|
}
|
|
218
176
|
|
|
219
177
|
return false
|
|
@@ -221,83 +179,104 @@ export class DialQueue {
|
|
|
221
179
|
|
|
222
180
|
if (existingDial != null) {
|
|
223
181
|
this.log('joining existing dial target for %p', peerId)
|
|
224
|
-
signal.clear()
|
|
225
|
-
return existingDial.promise
|
|
226
|
-
}
|
|
227
182
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
multiaddrs: addrsToDial.map(({ multiaddr }) => multiaddr)
|
|
183
|
+
// add all multiaddrs to the dial target
|
|
184
|
+
for (const multiaddr of multiaddrs) {
|
|
185
|
+
existingDial.options.multiaddrs.add(multiaddr.toString())
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return existingDial.join(options)
|
|
235
189
|
}
|
|
236
190
|
|
|
237
|
-
|
|
238
|
-
...options,
|
|
239
|
-
signal
|
|
240
|
-
})
|
|
241
|
-
.finally(() => {
|
|
242
|
-
// remove our pending dial entry
|
|
243
|
-
this.pendingDials = this.pendingDials.filter(p => p.id !== pendingDial.id)
|
|
191
|
+
this.log('creating dial target for %p', peerId, multiaddrs.map(ma => ma.toString()))
|
|
244
192
|
|
|
245
|
-
|
|
193
|
+
return this.queue.add(async (options) => {
|
|
194
|
+
// create abort conditions - need to do this before `calculateMultiaddrs` as
|
|
195
|
+
// we may be about to resolve a dns addr which can time out
|
|
196
|
+
const signal = this.createDialAbortController(options?.signal)
|
|
197
|
+
let addrsToDial: Address[]
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
// load addresses from address book, resolve and dnsaddrs, filter
|
|
201
|
+
// undiallables, add peer IDs, etc
|
|
202
|
+
addrsToDial = await this.calculateMultiaddrs(peerId, options?.multiaddrs, {
|
|
203
|
+
...options,
|
|
204
|
+
signal
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
addrsToDial.map(({ multiaddr }) => multiaddr.toString()).forEach(addr => {
|
|
208
|
+
options?.multiaddrs.add(addr)
|
|
209
|
+
})
|
|
210
|
+
} catch (err) {
|
|
246
211
|
signal.clear()
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
212
|
+
throw err
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
let dialed = 0
|
|
217
|
+
const errors: Error[] = []
|
|
218
|
+
|
|
219
|
+
for (const address of addrsToDial) {
|
|
220
|
+
if (dialed === this.maxPeerAddrsToDial) {
|
|
221
|
+
this.log('dialed %d addresses for %p, not trying any others', dialed, peerId)
|
|
222
|
+
|
|
223
|
+
throw new CodeError('Peer had more than maxPeerAddrsToDial', codes.ERR_TOO_MANY_ADDRESSES)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
dialed++
|
|
250
227
|
|
|
251
|
-
if (peerId != null) {
|
|
252
|
-
// record the last failed dial
|
|
253
228
|
try {
|
|
254
|
-
await this.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
229
|
+
const conn = await this.transportManager.dial(address.multiaddr, {
|
|
230
|
+
...options,
|
|
231
|
+
signal
|
|
258
232
|
})
|
|
233
|
+
|
|
234
|
+
this.log('dial to %a succeeded', address.multiaddr)
|
|
235
|
+
|
|
236
|
+
return conn
|
|
259
237
|
} catch (err: any) {
|
|
260
|
-
this.log.error('
|
|
238
|
+
this.log.error('dial failed to %a', address.multiaddr, err)
|
|
239
|
+
|
|
240
|
+
if (peerId != null) {
|
|
241
|
+
// record the failed dial
|
|
242
|
+
try {
|
|
243
|
+
await this.peerStore.patch(peerId, {
|
|
244
|
+
metadata: {
|
|
245
|
+
[LAST_DIAL_FAILURE_KEY]: uint8ArrayFromString(Date.now().toString())
|
|
246
|
+
}
|
|
247
|
+
})
|
|
248
|
+
} catch (err: any) {
|
|
249
|
+
this.log.error('could not update last dial failure key for %p', peerId, err)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// the user/dial timeout/shutdown controller signal aborted
|
|
254
|
+
if (signal.aborted) {
|
|
255
|
+
throw new CodeError(err.message, ERR_TIMEOUT)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
errors.push(err)
|
|
261
259
|
}
|
|
262
260
|
}
|
|
263
261
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
const error = new CodeError(err.message, ERR_TIMEOUT)
|
|
267
|
-
throw error
|
|
262
|
+
if (errors.length === 1) {
|
|
263
|
+
throw errors[0]
|
|
268
264
|
}
|
|
269
265
|
|
|
270
|
-
throw
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
this.pendingDials.push(pendingDial)
|
|
275
|
-
|
|
276
|
-
const connection = await pendingDial.promise
|
|
277
|
-
|
|
278
|
-
// we may have been dialing a multiaddr without a peer id attached but by
|
|
279
|
-
// this point we have upgraded the connection so the remote peer information
|
|
280
|
-
// should be available - check again that we don't already have a connection
|
|
281
|
-
// to the remote multiaddr
|
|
282
|
-
existingConnection = Array.from(this.connections.values()).flat().find(conn => {
|
|
283
|
-
if (options.force === true) {
|
|
284
|
-
return false
|
|
266
|
+
throw new AggregateCodeError(errors, 'All multiaddr dials failed', codes.ERR_TRANSPORT_DIAL_FAILED)
|
|
267
|
+
} finally {
|
|
268
|
+
// clean up abort signals/controllers
|
|
269
|
+
signal.clear()
|
|
285
270
|
}
|
|
286
|
-
|
|
287
|
-
|
|
271
|
+
}, {
|
|
272
|
+
peerId,
|
|
273
|
+
priority: options.priority,
|
|
274
|
+
multiaddrs: new Set(multiaddrs.map(ma => ma.toString())),
|
|
275
|
+
signal: options.signal
|
|
288
276
|
})
|
|
289
|
-
|
|
290
|
-
if (existingConnection != null) {
|
|
291
|
-
this.log('already connected to %a', existingConnection.remoteAddr)
|
|
292
|
-
await connection.close()
|
|
293
|
-
return existingConnection
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
this.log('connection opened to %a', connection.remoteAddr)
|
|
297
|
-
return connection
|
|
298
277
|
}
|
|
299
278
|
|
|
300
|
-
private
|
|
279
|
+
private createDialAbortController (userSignal?: AbortSignal): ClearableSignal {
|
|
301
280
|
// let any signal abort the dial
|
|
302
281
|
const signal = anySignal([
|
|
303
282
|
AbortSignal.timeout(this.dialTimeout),
|
|
@@ -312,7 +291,12 @@ export class DialQueue {
|
|
|
312
291
|
}
|
|
313
292
|
|
|
314
293
|
// eslint-disable-next-line complexity
|
|
315
|
-
private async calculateMultiaddrs (peerId?: PeerId,
|
|
294
|
+
private async calculateMultiaddrs (peerId?: PeerId, multiaddrs: Set<string> = new Set<string>(), options: DialOptions = {}): Promise<Address[]> {
|
|
295
|
+
const addrs: Address[] = [...multiaddrs].map(ma => ({
|
|
296
|
+
multiaddr: multiaddr(ma),
|
|
297
|
+
isCertified: false
|
|
298
|
+
}))
|
|
299
|
+
|
|
316
300
|
// if a peer id or multiaddr(s) with a peer id, make sure it isn't our peer id and that we are allowed to dial it
|
|
317
301
|
if (peerId != null) {
|
|
318
302
|
if (this.peerId.equals(peerId)) {
|
|
@@ -415,21 +399,11 @@ export class DialQueue {
|
|
|
415
399
|
|
|
416
400
|
const dedupedMultiaddrs = [...dedupedAddrs.values()]
|
|
417
401
|
|
|
418
|
-
if (dedupedMultiaddrs.length === 0 || dedupedMultiaddrs.length > this.maxPeerAddrsToDial) {
|
|
419
|
-
this.log('addresses for %p before filtering', peerId ?? 'unknown peer', resolvedAddresses.map(({ multiaddr }) => multiaddr.toString()))
|
|
420
|
-
this.log('addresses for %p after filtering', peerId ?? 'unknown peer', dedupedMultiaddrs.map(({ multiaddr }) => multiaddr.toString()))
|
|
421
|
-
}
|
|
422
|
-
|
|
423
402
|
// make sure we actually have some addresses to dial
|
|
424
403
|
if (dedupedMultiaddrs.length === 0) {
|
|
425
404
|
throw new CodeError('The dial request has no valid addresses', codes.ERR_NO_VALID_ADDRESSES)
|
|
426
405
|
}
|
|
427
406
|
|
|
428
|
-
// make sure we don't have too many addresses to dial
|
|
429
|
-
if (dedupedMultiaddrs.length > this.maxPeerAddrsToDial) {
|
|
430
|
-
throw new CodeError('dial with more addresses than allowed', codes.ERR_TOO_MANY_ADDRESSES)
|
|
431
|
-
}
|
|
432
|
-
|
|
433
407
|
const gatedAdrs: Address[] = []
|
|
434
408
|
|
|
435
409
|
for (const addr of dedupedMultiaddrs) {
|
|
@@ -447,130 +421,9 @@ export class DialQueue {
|
|
|
447
421
|
throw new CodeError('The connection gater denied all addresses in the dial request', codes.ERR_NO_VALID_ADDRESSES)
|
|
448
422
|
}
|
|
449
423
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
private async performDial (pendingDial: PendingDialInternal, options: DialOptions = {}): Promise<Connection> {
|
|
454
|
-
const dialAbortControllers: Array<(AbortController | undefined)> = pendingDial.multiaddrs.map(() => new AbortController())
|
|
455
|
-
|
|
456
|
-
try {
|
|
457
|
-
// internal peer dial queue - only one dial per peer at a time
|
|
458
|
-
const peerDialQueue = new PQueue({ concurrency: 1 })
|
|
459
|
-
peerDialQueue.on('error', (err) => {
|
|
460
|
-
this.log.error('error dialing %s %o', pendingDial.multiaddrs, err)
|
|
461
|
-
})
|
|
462
|
-
|
|
463
|
-
const conn = await Promise.any(pendingDial.multiaddrs.map(async (addr, i) => {
|
|
464
|
-
const controller = dialAbortControllers[i]
|
|
465
|
-
|
|
466
|
-
if (controller == null) {
|
|
467
|
-
throw new CodeError('dialAction did not come with an AbortController', codes.ERR_INVALID_PARAMETERS)
|
|
468
|
-
}
|
|
424
|
+
this.log.trace('addresses for %p before filtering', peerId ?? 'unknown peer', resolvedAddresses.map(({ multiaddr }) => multiaddr.toString()))
|
|
425
|
+
this.log.trace('addresses for %p after filtering', peerId ?? 'unknown peer', sortedGatedAddrs.map(({ multiaddr }) => multiaddr.toString()))
|
|
469
426
|
|
|
470
|
-
|
|
471
|
-
const signal = combineSignals(controller.signal, options.signal)
|
|
472
|
-
signal.addEventListener('abort', () => {
|
|
473
|
-
this.log('dial to %a aborted', addr)
|
|
474
|
-
})
|
|
475
|
-
const deferred = pDefer<Connection>()
|
|
476
|
-
|
|
477
|
-
await peerDialQueue.add(async () => {
|
|
478
|
-
if (signal.aborted) {
|
|
479
|
-
this.log('dial to %a was aborted before reaching the head of the peer dial queue', addr)
|
|
480
|
-
deferred.reject(new AbortError())
|
|
481
|
-
return
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// add the individual dial to the dial queue so we don't breach maxConcurrentDials
|
|
485
|
-
await this.queue.add(async () => {
|
|
486
|
-
try {
|
|
487
|
-
if (signal.aborted) {
|
|
488
|
-
this.log('dial to %a was aborted before reaching the head of the dial queue', addr)
|
|
489
|
-
deferred.reject(new AbortError())
|
|
490
|
-
return
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
// update dial status
|
|
494
|
-
pendingDial.status = 'active'
|
|
495
|
-
|
|
496
|
-
const conn = await this.transportManager.dial(addr, {
|
|
497
|
-
...options,
|
|
498
|
-
signal
|
|
499
|
-
})
|
|
500
|
-
|
|
501
|
-
if (controller.signal.aborted) {
|
|
502
|
-
// another dial succeeded faster than this one
|
|
503
|
-
this.log('multiple dials succeeded, closing superfluous connection')
|
|
504
|
-
|
|
505
|
-
conn.close().catch(err => {
|
|
506
|
-
this.log.error('error closing superfluous connection', err)
|
|
507
|
-
})
|
|
508
|
-
|
|
509
|
-
deferred.reject(new AbortError())
|
|
510
|
-
return
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// remove the successful AbortController so it is not aborted
|
|
514
|
-
dialAbortControllers[i] = undefined
|
|
515
|
-
|
|
516
|
-
// immediately abort any other dials
|
|
517
|
-
dialAbortControllers.forEach(c => {
|
|
518
|
-
if (c !== undefined) {
|
|
519
|
-
c.abort()
|
|
520
|
-
}
|
|
521
|
-
})
|
|
522
|
-
|
|
523
|
-
this.log('dial to %a succeeded', addr)
|
|
524
|
-
|
|
525
|
-
// resolve the connection promise
|
|
526
|
-
deferred.resolve(conn)
|
|
527
|
-
} catch (err: any) {
|
|
528
|
-
// something only went wrong if our signal was not aborted
|
|
529
|
-
this.log.error('error during dial of %a', addr, err)
|
|
530
|
-
deferred.reject(err)
|
|
531
|
-
}
|
|
532
|
-
}, {
|
|
533
|
-
...options,
|
|
534
|
-
signal
|
|
535
|
-
}).catch(err => {
|
|
536
|
-
deferred.reject(err)
|
|
537
|
-
})
|
|
538
|
-
}, {
|
|
539
|
-
signal
|
|
540
|
-
}).catch(err => {
|
|
541
|
-
deferred.reject(err)
|
|
542
|
-
}).finally(() => {
|
|
543
|
-
signal.clear()
|
|
544
|
-
})
|
|
545
|
-
|
|
546
|
-
return deferred.promise
|
|
547
|
-
}))
|
|
548
|
-
|
|
549
|
-
// dial succeeded or failed
|
|
550
|
-
if (conn == null) {
|
|
551
|
-
throw new CodeError('successful dial led to empty object returned from peer dial queue', codes.ERR_TRANSPORT_DIAL_FAILED)
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
pendingDial.status = 'success'
|
|
555
|
-
|
|
556
|
-
return conn
|
|
557
|
-
} catch (err: any) {
|
|
558
|
-
pendingDial.status = 'error'
|
|
559
|
-
|
|
560
|
-
// if we only dialled one address, unwrap the AggregateError to provide more
|
|
561
|
-
// useful feedback to the user
|
|
562
|
-
if (pendingDial.multiaddrs.length === 1 && err.name === 'AggregateError') {
|
|
563
|
-
throw err.errors[0]
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
throw err
|
|
567
|
-
}
|
|
427
|
+
return sortedGatedAddrs
|
|
568
428
|
}
|
|
569
429
|
}
|
|
570
|
-
|
|
571
|
-
/**
|
|
572
|
-
* Returns a random string
|
|
573
|
-
*/
|
|
574
|
-
function randomId (): string {
|
|
575
|
-
return `${(parseInt(String(Math.random() * 1e9), 10)).toString()}${Date.now()}`
|
|
576
|
-
}
|
|
@@ -10,8 +10,9 @@ import { AutoDial } from './auto-dial.js'
|
|
|
10
10
|
import { ConnectionPruner } from './connection-pruner.js'
|
|
11
11
|
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'
|
|
12
12
|
import { DialQueue } from './dial-queue.js'
|
|
13
|
-
import type { PendingDial, AddressSorter, Libp2pEvents, AbortOptions, ComponentLogger, Logger, Connection, MultiaddrConnection, ConnectionGater, TypedEventTarget, Metrics, PeerId, Peer, PeerStore, Startable } from '@libp2p/interface'
|
|
13
|
+
import type { PendingDial, AddressSorter, Libp2pEvents, AbortOptions, ComponentLogger, Logger, Connection, MultiaddrConnection, ConnectionGater, TypedEventTarget, Metrics, PeerId, Peer, PeerStore, Startable, PendingDialStatus } from '@libp2p/interface'
|
|
14
14
|
import type { ConnectionManager, OpenConnectionOptions, TransportManager } from '@libp2p/interface-internal'
|
|
15
|
+
import type { JobStatus } from '@libp2p/utils/queue'
|
|
15
16
|
|
|
16
17
|
const DEFAULT_DIAL_PRIORITY = 50
|
|
17
18
|
|
|
@@ -599,6 +600,20 @@ export class DefaultConnectionManager implements ConnectionManager, Startable {
|
|
|
599
600
|
}
|
|
600
601
|
|
|
601
602
|
getDialQueue (): PendingDial[] {
|
|
602
|
-
|
|
603
|
+
const statusMap: Record<JobStatus, PendingDialStatus> = {
|
|
604
|
+
queued: 'queued',
|
|
605
|
+
running: 'active',
|
|
606
|
+
errored: 'error',
|
|
607
|
+
complete: 'success'
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
return this.dialQueue.queue.queue.map(job => {
|
|
611
|
+
return {
|
|
612
|
+
id: job.id,
|
|
613
|
+
status: statusMap[job.status],
|
|
614
|
+
peerId: job.options.peerId,
|
|
615
|
+
multiaddrs: [...job.options.multiaddrs].map(ma => multiaddr(ma))
|
|
616
|
+
}
|
|
617
|
+
})
|
|
603
618
|
}
|
|
604
619
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { setMaxListeners } from '@libp2p/interface'
|
|
2
1
|
import { type AbortOptions, multiaddr, type Multiaddr } from '@multiformats/multiaddr'
|
|
3
|
-
import { type ClearableSignal, anySignal } from 'any-signal'
|
|
4
2
|
import type { LoggerOptions } from '@libp2p/interface'
|
|
5
3
|
|
|
6
4
|
/**
|
|
@@ -47,21 +45,3 @@ async function resolveRecord (ma: Multiaddr, options: AbortOptions & LoggerOptio
|
|
|
47
45
|
return []
|
|
48
46
|
}
|
|
49
47
|
}
|
|
50
|
-
|
|
51
|
-
export function combineSignals (...signals: Array<AbortSignal | undefined>): ClearableSignal {
|
|
52
|
-
const sigs: AbortSignal[] = []
|
|
53
|
-
|
|
54
|
-
for (const sig of signals) {
|
|
55
|
-
if (sig != null) {
|
|
56
|
-
setMaxListeners(Infinity, sig)
|
|
57
|
-
sigs.push(sig)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// let any signal abort the dial
|
|
62
|
-
const signal = anySignal(sigs)
|
|
63
|
-
|
|
64
|
-
setMaxListeners(Infinity, signal)
|
|
65
|
-
|
|
66
|
-
return signal
|
|
67
|
-
}
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = '1.0
|
|
1
|
+
export const version = '1.1.0-528d73781'
|
|
2
2
|
export const name = 'libp2p'
|
package/dist/typedoc-urls.json
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"Libp2pInit": "https://libp2p.github.io/js-libp2p/interfaces/libp2p.Libp2pInit.html",
|
|
3
|
-
".:Libp2pInit": "https://libp2p.github.io/js-libp2p/interfaces/libp2p.Libp2pInit.html",
|
|
4
|
-
"Libp2pOptions": "https://libp2p.github.io/js-libp2p/types/libp2p.Libp2pOptions.html",
|
|
5
|
-
".:Libp2pOptions": "https://libp2p.github.io/js-libp2p/types/libp2p.Libp2pOptions.html",
|
|
6
|
-
"ServiceFactoryMap": "https://libp2p.github.io/js-libp2p/types/libp2p.ServiceFactoryMap.html",
|
|
7
|
-
".:ServiceFactoryMap": "https://libp2p.github.io/js-libp2p/types/libp2p.ServiceFactoryMap.html",
|
|
8
|
-
"createLibp2p": "https://libp2p.github.io/js-libp2p/functions/libp2p.createLibp2p.html",
|
|
9
|
-
".:createLibp2p": "https://libp2p.github.io/js-libp2p/functions/libp2p.createLibp2p.html"
|
|
10
|
-
}
|