libp2p 1.9.3 → 1.9.4-2bbaf4361
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 +17 -18
- package/dist/src/components.d.ts.map +1 -1
- package/dist/src/components.js +4 -3
- package/dist/src/components.js.map +1 -1
- package/dist/src/config.d.ts +1 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +2 -7
- package/dist/src/config.js.map +1 -1
- package/dist/src/connection/index.d.ts +3 -3
- package/dist/src/connection/index.d.ts.map +1 -1
- package/dist/src/connection/index.js +7 -7
- package/dist/src/connection/index.js.map +1 -1
- package/dist/src/connection-manager/connection-pruner.js +1 -1
- package/dist/src/connection-manager/constants.browser.d.ts +0 -8
- package/dist/src/connection-manager/constants.browser.d.ts.map +1 -1
- package/dist/src/connection-manager/constants.browser.js +0 -8
- package/dist/src/connection-manager/constants.browser.js.map +1 -1
- package/dist/src/connection-manager/constants.d.ts +0 -8
- package/dist/src/connection-manager/constants.d.ts.map +1 -1
- package/dist/src/connection-manager/constants.defaults.d.ts +12 -22
- package/dist/src/connection-manager/constants.defaults.d.ts.map +1 -1
- package/dist/src/connection-manager/constants.defaults.js +12 -22
- package/dist/src/connection-manager/constants.defaults.js.map +1 -1
- package/dist/src/connection-manager/constants.js +0 -8
- package/dist/src/connection-manager/constants.js.map +1 -1
- package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
- package/dist/src/connection-manager/dial-queue.js +29 -15
- package/dist/src/connection-manager/dial-queue.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +47 -50
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +23 -57
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/connection-manager/reconnect-queue.d.ts +35 -0
- package/dist/src/connection-manager/reconnect-queue.d.ts.map +1 -0
- package/dist/src/connection-manager/reconnect-queue.js +104 -0
- package/dist/src/connection-manager/reconnect-queue.js.map +1 -0
- package/dist/src/connection-monitor.d.ts +1 -0
- package/dist/src/connection-monitor.d.ts.map +1 -1
- package/dist/src/connection-monitor.js +15 -5
- package/dist/src/connection-monitor.js.map +1 -1
- package/dist/src/content-routing.js +6 -6
- package/dist/src/content-routing.js.map +1 -1
- package/dist/src/errors.d.ts +41 -61
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +84 -63
- package/dist/src/errors.js.map +1 -1
- package/dist/src/get-peer.d.ts.map +1 -1
- package/dist/src/get-peer.js +4 -5
- package/dist/src/get-peer.js.map +1 -1
- package/dist/src/index.d.ts +27 -9
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +10 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/libp2p.d.ts +11 -10
- package/dist/src/libp2p.d.ts.map +1 -1
- package/dist/src/libp2p.js +13 -31
- package/dist/src/libp2p.js.map +1 -1
- package/dist/src/peer-routing.js +8 -8
- package/dist/src/peer-routing.js.map +1 -1
- package/dist/src/registrar.js +7 -7
- package/dist/src/registrar.js.map +1 -1
- package/dist/src/transport-manager.d.ts.map +1 -1
- package/dist/src/transport-manager.js +15 -23
- package/dist/src/transport-manager.js.map +1 -1
- package/dist/src/upgrader.d.ts +8 -8
- package/dist/src/upgrader.d.ts.map +1 -1
- package/dist/src/upgrader.js +51 -51
- package/dist/src/upgrader.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 +20 -20
- package/src/components.ts +4 -3
- package/src/config.ts +4 -10
- package/src/connection/index.ts +9 -9
- package/src/connection-manager/connection-pruner.ts +1 -1
- package/src/connection-manager/constants.browser.ts +0 -10
- package/src/connection-manager/constants.defaults.ts +14 -27
- package/src/connection-manager/constants.ts +0 -10
- package/src/connection-manager/dial-queue.ts +30 -15
- package/src/connection-manager/index.ts +80 -118
- package/src/connection-manager/reconnect-queue.ts +134 -0
- package/src/connection-monitor.ts +15 -6
- package/src/content-routing.ts +6 -6
- package/src/errors.ts +96 -61
- package/src/get-peer.ts +4 -5
- package/src/index.ts +42 -12
- package/src/libp2p.ts +22 -36
- package/src/peer-routing.ts +8 -8
- package/src/registrar.ts +7 -7
- package/src/transport-manager.ts +15 -23
- package/src/upgrader.ts +55 -56
- package/src/version.ts +1 -1
- package/dist/src/connection-manager/auto-dial.d.ts +0 -47
- package/dist/src/connection-manager/auto-dial.d.ts.map +0 -1
- package/dist/src/connection-manager/auto-dial.js +0 -223
- package/dist/src/connection-manager/auto-dial.js.map +0 -1
- package/dist/typedoc-urls.json +0 -14
- package/src/connection-manager/auto-dial.ts +0 -285
package/src/upgrader.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InvalidMultiaddrError, InvalidPeerIdError, TooManyInboundProtocolStreamsError, TooManyOutboundProtocolStreamsError, LimitedConnectionError, TimeoutError, setMaxListeners } from '@libp2p/interface'
|
|
2
2
|
import * as mss from '@libp2p/multistream-select'
|
|
3
3
|
import { peerIdFromString } from '@libp2p/peer-id'
|
|
4
4
|
import { CustomProgressEvent } from 'progress-events'
|
|
5
5
|
import { createConnection } from './connection/index.js'
|
|
6
6
|
import { INBOUND_UPGRADE_TIMEOUT } from './connection-manager/constants.js'
|
|
7
|
-
import {
|
|
7
|
+
import { ConnectionDeniedError, ConnectionInterceptedError, EncryptionFailedError, MuxerUnavailableError } from './errors.js'
|
|
8
8
|
import { DEFAULT_MAX_INBOUND_STREAMS, DEFAULT_MAX_OUTBOUND_STREAMS } from './registrar.js'
|
|
9
|
-
import type { Libp2pEvents, AbortOptions, ComponentLogger, MultiaddrConnection, Connection, Stream, ConnectionProtector, NewStreamOptions, ConnectionEncrypter, SecuredConnection, ConnectionGater, TypedEventTarget, Metrics, PeerId, PeerStore, StreamMuxer, StreamMuxerFactory, Upgrader, UpgraderOptions } from '@libp2p/interface'
|
|
9
|
+
import type { Libp2pEvents, AbortOptions, ComponentLogger, MultiaddrConnection, Connection, Stream, ConnectionProtector, NewStreamOptions, ConnectionEncrypter, SecuredConnection, ConnectionGater, TypedEventTarget, Metrics, PeerId, PeerStore, StreamMuxer, StreamMuxerFactory, Upgrader, UpgraderOptions, ConnectionLimits, SecureConnectionOptions } from '@libp2p/interface'
|
|
10
10
|
import type { ConnectionManager, Registrar } from '@libp2p/interface-internal'
|
|
11
11
|
|
|
12
12
|
const DEFAULT_PROTOCOL_SELECT_TIMEOUT = 30000
|
|
@@ -18,7 +18,7 @@ interface CreateConnectionOptions {
|
|
|
18
18
|
upgradedConn: MultiaddrConnection
|
|
19
19
|
remotePeer: PeerId
|
|
20
20
|
muxerFactory?: StreamMuxerFactory
|
|
21
|
-
|
|
21
|
+
limits?: ConnectionLimits
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
interface OnStreamOptions {
|
|
@@ -32,8 +32,8 @@ export interface CryptoResult extends SecuredConnection<MultiaddrConnection> {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
export interface UpgraderInit {
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
connectionEncrypters: ConnectionEncrypter[]
|
|
36
|
+
streamMuxers: StreamMuxerFactory[]
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* An amount of ms by which an inbound connection upgrade
|
|
@@ -48,7 +48,7 @@ function findIncomingStreamLimit (protocol: string, registrar: Registrar): numbe
|
|
|
48
48
|
|
|
49
49
|
return options.maxInboundStreams
|
|
50
50
|
} catch (err: any) {
|
|
51
|
-
if (err.
|
|
51
|
+
if (err.name !== 'UnhandledProtocolError') {
|
|
52
52
|
throw err
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -64,7 +64,7 @@ function findOutgoingStreamLimit (protocol: string, registrar: Registrar, option
|
|
|
64
64
|
return options.maxOutboundStreams
|
|
65
65
|
}
|
|
66
66
|
} catch (err: any) {
|
|
67
|
-
if (err.
|
|
67
|
+
if (err.name !== 'UnhandledProtocolError') {
|
|
68
68
|
throw err
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -100,23 +100,23 @@ type ConnectionDeniedType = keyof Pick<ConnectionGater, 'denyOutboundConnection'
|
|
|
100
100
|
|
|
101
101
|
export class DefaultUpgrader implements Upgrader {
|
|
102
102
|
private readonly components: DefaultUpgraderComponents
|
|
103
|
-
private readonly
|
|
104
|
-
private readonly
|
|
103
|
+
private readonly connectionEncrypters: Map<string, ConnectionEncrypter>
|
|
104
|
+
private readonly streamMuxers: Map<string, StreamMuxerFactory>
|
|
105
105
|
private readonly inboundUpgradeTimeout: number
|
|
106
106
|
private readonly events: TypedEventTarget<Libp2pEvents>
|
|
107
107
|
|
|
108
108
|
constructor (components: DefaultUpgraderComponents, init: UpgraderInit) {
|
|
109
109
|
this.components = components
|
|
110
|
-
this.
|
|
110
|
+
this.connectionEncrypters = new Map()
|
|
111
111
|
|
|
112
|
-
init.
|
|
113
|
-
this.
|
|
112
|
+
init.connectionEncrypters.forEach(encrypter => {
|
|
113
|
+
this.connectionEncrypters.set(encrypter.protocol, encrypter)
|
|
114
114
|
})
|
|
115
115
|
|
|
116
|
-
this.
|
|
116
|
+
this.streamMuxers = new Map()
|
|
117
117
|
|
|
118
|
-
init.
|
|
119
|
-
this.
|
|
118
|
+
init.streamMuxers.forEach(muxer => {
|
|
119
|
+
this.streamMuxers.set(muxer.protocol, muxer)
|
|
120
120
|
})
|
|
121
121
|
|
|
122
122
|
this.inboundUpgradeTimeout = init.inboundUpgradeTimeout ?? INBOUND_UPGRADE_TIMEOUT
|
|
@@ -130,7 +130,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
130
130
|
|
|
131
131
|
if (connectionGater !== undefined) {
|
|
132
132
|
if (await connectionGater(remotePeer, maConn)) {
|
|
133
|
-
throw new
|
|
133
|
+
throw new ConnectionInterceptedError(`The multiaddr connection is blocked by gater.${connectionType}`)
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
}
|
|
@@ -142,7 +142,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
142
142
|
const accept = await this.components.connectionManager.acceptIncomingConnection(maConn)
|
|
143
143
|
|
|
144
144
|
if (!accept) {
|
|
145
|
-
throw new
|
|
145
|
+
throw new ConnectionDeniedError('connection denied')
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
let encryptedConn: MultiaddrConnection
|
|
@@ -154,7 +154,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
154
154
|
const signal = AbortSignal.timeout(this.inboundUpgradeTimeout)
|
|
155
155
|
|
|
156
156
|
const onAbort = (): void => {
|
|
157
|
-
maConn.abort(new
|
|
157
|
+
maConn.abort(new TimeoutError('inbound upgrade timeout'))
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
signal.addEventListener('abort', onAbort, { once: true })
|
|
@@ -163,7 +163,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
163
163
|
|
|
164
164
|
try {
|
|
165
165
|
if ((await this.components.connectionGater.denyInboundConnection?.(maConn)) === true) {
|
|
166
|
-
throw new
|
|
166
|
+
throw new ConnectionInterceptedError('The multiaddr connection is blocked by gater.acceptConnection')
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
this.components.metrics?.trackMultiaddrConnection(maConn)
|
|
@@ -204,7 +204,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
204
204
|
const idStr = maConn.remoteAddr.getPeerId()
|
|
205
205
|
|
|
206
206
|
if (idStr == null) {
|
|
207
|
-
throw new
|
|
207
|
+
throw new InvalidMultiaddrError('inbound connection that skipped encryption must have a peer id')
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
const remotePeerId = peerIdFromString(idStr)
|
|
@@ -216,14 +216,14 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
216
216
|
upgradedConn = encryptedConn
|
|
217
217
|
if (opts?.muxerFactory != null) {
|
|
218
218
|
muxerFactory = opts.muxerFactory
|
|
219
|
-
} else if (this.
|
|
219
|
+
} else if (this.streamMuxers.size > 0) {
|
|
220
220
|
opts?.onProgress?.(new CustomProgressEvent('upgrader:multiplex-inbound-connection'))
|
|
221
221
|
|
|
222
222
|
// Multiplex the connection
|
|
223
223
|
const multiplexed = await this._multiplexInbound({
|
|
224
224
|
...protectedConn,
|
|
225
225
|
...encryptedConn
|
|
226
|
-
}, this.
|
|
226
|
+
}, this.streamMuxers)
|
|
227
227
|
muxerFactory = multiplexed.muxerFactory
|
|
228
228
|
upgradedConn = multiplexed.stream
|
|
229
229
|
}
|
|
@@ -243,7 +243,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
243
243
|
upgradedConn,
|
|
244
244
|
muxerFactory,
|
|
245
245
|
remotePeer,
|
|
246
|
-
|
|
246
|
+
limits: opts?.limits
|
|
247
247
|
})
|
|
248
248
|
} finally {
|
|
249
249
|
signal.removeEventListener('abort', onAbort)
|
|
@@ -296,7 +296,10 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
296
296
|
conn: encryptedConn,
|
|
297
297
|
remotePeer,
|
|
298
298
|
protocol: cryptoProtocol
|
|
299
|
-
} = await this._encryptOutbound(protectedConn,
|
|
299
|
+
} = await this._encryptOutbound(protectedConn, {
|
|
300
|
+
...opts,
|
|
301
|
+
remotePeer: remotePeerId
|
|
302
|
+
}))
|
|
300
303
|
|
|
301
304
|
const maConn: MultiaddrConnection = {
|
|
302
305
|
...protectedConn,
|
|
@@ -306,7 +309,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
306
309
|
await this.shouldBlockConnection(remotePeer, maConn, 'denyOutboundEncryptedConnection')
|
|
307
310
|
} else {
|
|
308
311
|
if (remotePeerId == null) {
|
|
309
|
-
throw new
|
|
312
|
+
throw new InvalidPeerIdError('Encryption was skipped but no peer id was passed')
|
|
310
313
|
}
|
|
311
314
|
|
|
312
315
|
cryptoProtocol = 'native'
|
|
@@ -316,12 +319,12 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
316
319
|
upgradedConn = encryptedConn
|
|
317
320
|
if (opts?.muxerFactory != null) {
|
|
318
321
|
muxerFactory = opts.muxerFactory
|
|
319
|
-
} else if (this.
|
|
322
|
+
} else if (this.streamMuxers.size > 0) {
|
|
320
323
|
// Multiplex the connection
|
|
321
324
|
const multiplexed = await this._multiplexOutbound({
|
|
322
325
|
...protectedConn,
|
|
323
326
|
...encryptedConn
|
|
324
|
-
}, this.
|
|
327
|
+
}, this.streamMuxers)
|
|
325
328
|
muxerFactory = multiplexed.muxerFactory
|
|
326
329
|
upgradedConn = multiplexed.stream
|
|
327
330
|
}
|
|
@@ -342,7 +345,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
342
345
|
upgradedConn,
|
|
343
346
|
muxerFactory,
|
|
344
347
|
remotePeer,
|
|
345
|
-
|
|
348
|
+
limits: opts?.limits
|
|
346
349
|
})
|
|
347
350
|
}
|
|
348
351
|
|
|
@@ -357,7 +360,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
357
360
|
upgradedConn,
|
|
358
361
|
remotePeer,
|
|
359
362
|
muxerFactory,
|
|
360
|
-
|
|
363
|
+
limits
|
|
361
364
|
} = opts
|
|
362
365
|
|
|
363
366
|
let muxer: StreamMuxer | undefined
|
|
@@ -392,7 +395,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
392
395
|
const streamCount = countStreams(protocol, 'inbound', connection)
|
|
393
396
|
|
|
394
397
|
if (streamCount === incomingLimit) {
|
|
395
|
-
const err = new
|
|
398
|
+
const err = new TooManyInboundProtocolStreamsError(`Too many inbound protocol streams for protocol "${protocol}" - limit ${incomingLimit}`)
|
|
396
399
|
muxedStream.abort(err)
|
|
397
400
|
|
|
398
401
|
throw err
|
|
@@ -441,7 +444,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
441
444
|
|
|
442
445
|
newStream = async (protocols: string[], options: NewStreamOptions = {}): Promise<Stream> => {
|
|
443
446
|
if (muxer == null) {
|
|
444
|
-
throw new
|
|
447
|
+
throw new MuxerUnavailableError('Connection is not multiplexed')
|
|
445
448
|
}
|
|
446
449
|
|
|
447
450
|
connection.log('starting new stream for protocols %s', protocols)
|
|
@@ -478,7 +481,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
478
481
|
const streamCount = countStreams(protocol, 'outbound', connection)
|
|
479
482
|
|
|
480
483
|
if (streamCount >= outgoingLimit) {
|
|
481
|
-
const err = new
|
|
484
|
+
const err = new TooManyOutboundProtocolStreamsError(`Too many outbound protocol streams for protocol "${protocol}" - ${streamCount}/${outgoingLimit}`)
|
|
482
485
|
muxedStream.abort(err)
|
|
483
486
|
|
|
484
487
|
throw err
|
|
@@ -521,11 +524,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
521
524
|
muxedStream.abort(err)
|
|
522
525
|
}
|
|
523
526
|
|
|
524
|
-
|
|
525
|
-
throw err
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
throw new CodeError(String(err), codes.ERR_UNSUPPORTED_PROTOCOL)
|
|
527
|
+
throw err
|
|
529
528
|
}
|
|
530
529
|
}
|
|
531
530
|
|
|
@@ -566,7 +565,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
566
565
|
maConn.timeline.upgraded = Date.now()
|
|
567
566
|
|
|
568
567
|
const errConnectionNotMultiplexed = (): any => {
|
|
569
|
-
throw new
|
|
568
|
+
throw new MuxerUnavailableError('Connection is not multiplexed')
|
|
570
569
|
}
|
|
571
570
|
|
|
572
571
|
// Create the connection
|
|
@@ -578,7 +577,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
578
577
|
timeline: maConn.timeline,
|
|
579
578
|
multiplexer: muxer?.protocol,
|
|
580
579
|
encryption: cryptoProtocol,
|
|
581
|
-
|
|
580
|
+
limits,
|
|
582
581
|
logger: this.components.logger,
|
|
583
582
|
newStream: newStream ?? errConnectionNotMultiplexed,
|
|
584
583
|
getStreams: () => { if (muxer != null) { return muxer.streams } else { return [] } },
|
|
@@ -617,8 +616,8 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
617
616
|
const { connection, stream, protocol } = opts
|
|
618
617
|
const { handler, options } = this.components.registrar.getHandler(protocol)
|
|
619
618
|
|
|
620
|
-
if (connection.
|
|
621
|
-
throw new
|
|
619
|
+
if (connection.limits != null && options.runOnLimitedConnection !== true) {
|
|
620
|
+
throw new LimitedConnectionError('Cannot open protocol stream on limited connection')
|
|
622
621
|
}
|
|
623
622
|
|
|
624
623
|
handler({ connection, stream })
|
|
@@ -627,15 +626,15 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
627
626
|
/**
|
|
628
627
|
* Attempts to encrypt the incoming `connection` with the provided `cryptos`
|
|
629
628
|
*/
|
|
630
|
-
async _encryptInbound (connection: MultiaddrConnection): Promise<CryptoResult> {
|
|
631
|
-
const protocols = Array.from(this.
|
|
629
|
+
async _encryptInbound (connection: MultiaddrConnection, options?: AbortOptions): Promise<CryptoResult> {
|
|
630
|
+
const protocols = Array.from(this.connectionEncrypters.keys())
|
|
632
631
|
connection.log('handling inbound crypto protocol selection', protocols)
|
|
633
632
|
|
|
634
633
|
try {
|
|
635
634
|
const { stream, protocol } = await mss.handle(connection, protocols, {
|
|
636
635
|
log: connection.log
|
|
637
636
|
})
|
|
638
|
-
const encrypter = this.
|
|
637
|
+
const encrypter = this.connectionEncrypters.get(protocol)
|
|
639
638
|
|
|
640
639
|
if (encrypter == null) {
|
|
641
640
|
throw new Error(`no crypto module found for ${protocol}`)
|
|
@@ -644,12 +643,12 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
644
643
|
connection.log('encrypting inbound connection using', protocol)
|
|
645
644
|
|
|
646
645
|
return {
|
|
647
|
-
...await encrypter.secureInbound(
|
|
646
|
+
...await encrypter.secureInbound(stream, options),
|
|
648
647
|
protocol
|
|
649
648
|
}
|
|
650
649
|
} catch (err: any) {
|
|
651
650
|
connection.log.error('encrypting inbound connection failed', err)
|
|
652
|
-
throw new
|
|
651
|
+
throw new EncryptionFailedError(err.message)
|
|
653
652
|
}
|
|
654
653
|
}
|
|
655
654
|
|
|
@@ -657,8 +656,8 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
657
656
|
* Attempts to encrypt the given `connection` with the provided connection encrypters.
|
|
658
657
|
* The first `ConnectionEncrypter` module to succeed will be used
|
|
659
658
|
*/
|
|
660
|
-
async _encryptOutbound (connection: MultiaddrConnection,
|
|
661
|
-
const protocols = Array.from(this.
|
|
659
|
+
async _encryptOutbound (connection: MultiaddrConnection, options?: SecureConnectionOptions): Promise<CryptoResult> {
|
|
660
|
+
const protocols = Array.from(this.connectionEncrypters.keys())
|
|
662
661
|
connection.log('selecting outbound crypto protocol', protocols)
|
|
663
662
|
|
|
664
663
|
try {
|
|
@@ -672,21 +671,21 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
672
671
|
yieldBytes: true
|
|
673
672
|
})
|
|
674
673
|
|
|
675
|
-
const encrypter = this.
|
|
674
|
+
const encrypter = this.connectionEncrypters.get(protocol)
|
|
676
675
|
|
|
677
676
|
if (encrypter == null) {
|
|
678
677
|
throw new Error(`no crypto module found for ${protocol}`)
|
|
679
678
|
}
|
|
680
679
|
|
|
681
|
-
connection.log('encrypting outbound connection to %p using %s',
|
|
680
|
+
connection.log('encrypting outbound connection to %p using %s', options?.remotePeer, encrypter)
|
|
682
681
|
|
|
683
682
|
return {
|
|
684
|
-
...await encrypter.secureOutbound(
|
|
683
|
+
...await encrypter.secureOutbound(stream, options),
|
|
685
684
|
protocol
|
|
686
685
|
}
|
|
687
686
|
} catch (err: any) {
|
|
688
|
-
connection.log.error('encrypting outbound connection to %p failed',
|
|
689
|
-
throw new
|
|
687
|
+
connection.log.error('encrypting outbound connection to %p failed', options?.remotePeer, err)
|
|
688
|
+
throw new EncryptionFailedError(err.message)
|
|
690
689
|
}
|
|
691
690
|
}
|
|
692
691
|
|
|
@@ -714,7 +713,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
714
713
|
return { stream, muxerFactory }
|
|
715
714
|
} catch (err: any) {
|
|
716
715
|
connection.log.error('error multiplexing outbound connection', err)
|
|
717
|
-
throw new
|
|
716
|
+
throw new MuxerUnavailableError(String(err))
|
|
718
717
|
}
|
|
719
718
|
}
|
|
720
719
|
|
|
@@ -734,7 +733,7 @@ export class DefaultUpgrader implements Upgrader {
|
|
|
734
733
|
return { stream, muxerFactory }
|
|
735
734
|
} catch (err: any) {
|
|
736
735
|
connection.log.error('error multiplexing inbound connection', err)
|
|
737
|
-
throw new
|
|
736
|
+
throw new MuxerUnavailableError(String(err))
|
|
738
737
|
}
|
|
739
738
|
}
|
|
740
739
|
}
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = '1.9.
|
|
1
|
+
export const version = '1.9.4-2bbaf4361'
|
|
2
2
|
export const name = 'libp2p'
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { Libp2pEvents, ComponentLogger, TypedEventTarget, PeerStore, Startable, Metrics } from '@libp2p/interface';
|
|
2
|
-
import type { ConnectionManager } from '@libp2p/interface-internal';
|
|
3
|
-
interface AutoDialInit {
|
|
4
|
-
minConnections?: number;
|
|
5
|
-
maxQueueLength?: number;
|
|
6
|
-
autoDialConcurrency?: number;
|
|
7
|
-
autoDialPriority?: number;
|
|
8
|
-
autoDialInterval?: number;
|
|
9
|
-
autoDialPeerRetryThreshold?: number;
|
|
10
|
-
autoDialDiscoveredPeersDebounce?: number;
|
|
11
|
-
}
|
|
12
|
-
interface AutoDialComponents {
|
|
13
|
-
connectionManager: ConnectionManager;
|
|
14
|
-
peerStore: PeerStore;
|
|
15
|
-
events: TypedEventTarget<Libp2pEvents>;
|
|
16
|
-
logger: ComponentLogger;
|
|
17
|
-
metrics?: Metrics;
|
|
18
|
-
}
|
|
19
|
-
export declare class AutoDial implements Startable {
|
|
20
|
-
private readonly connectionManager;
|
|
21
|
-
private readonly peerStore;
|
|
22
|
-
private readonly queue;
|
|
23
|
-
private readonly minConnections;
|
|
24
|
-
private readonly autoDialPriority;
|
|
25
|
-
private readonly autoDialIntervalMs;
|
|
26
|
-
private readonly autoDialMaxQueueLength;
|
|
27
|
-
private readonly autoDialPeerRetryThresholdMs;
|
|
28
|
-
private readonly autoDialDiscoveredPeersDebounce;
|
|
29
|
-
private autoDialInterval?;
|
|
30
|
-
private started;
|
|
31
|
-
private running;
|
|
32
|
-
private readonly log;
|
|
33
|
-
/**
|
|
34
|
-
* Proactively tries to connect to known peers stored in the PeerStore.
|
|
35
|
-
* It will keep the number of connections below the upper limit and sort
|
|
36
|
-
* the peers to connect based on whether we know their keys and protocols.
|
|
37
|
-
*/
|
|
38
|
-
constructor(components: AutoDialComponents, init: AutoDialInit);
|
|
39
|
-
isStarted(): boolean;
|
|
40
|
-
start(): void;
|
|
41
|
-
afterStart(): void;
|
|
42
|
-
stop(): void;
|
|
43
|
-
autoDial(): Promise<void>;
|
|
44
|
-
private sheduleNextAutodial;
|
|
45
|
-
}
|
|
46
|
-
export {};
|
|
47
|
-
//# sourceMappingURL=auto-dial.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auto-dial.d.ts","sourceRoot":"","sources":["../../../src/connection-manager/auto-dial.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAU,eAAe,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAC/H,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAEnE,UAAU,YAAY;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,0BAA0B,CAAC,EAAE,MAAM,CAAA;IACnC,+BAA+B,CAAC,EAAE,MAAM,CAAA;CACzC;AAED,UAAU,kBAAkB;IAC1B,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,SAAS,EAAE,SAAS,CAAA;IACpB,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAA;IACtC,MAAM,EAAE,eAAe,CAAA;IACvB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAYD,qBAAa,QAAS,YAAW,SAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAQ;IACzC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAQ;IAC3C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAQ;IAC/C,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAQ;IACrD,OAAO,CAAC,QAAQ,CAAC,+BAA+B,CAAQ;IACxD,OAAO,CAAC,gBAAgB,CAAC,CAAgC;IACzD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAE5B;;;;OAIG;gBACU,UAAU,EAAE,kBAAkB,EAAE,IAAI,EAAE,YAAY;IA8C/D,SAAS,IAAK,OAAO;IAIrB,KAAK,IAAK,IAAI;IAId,UAAU,IAAK,IAAI;IAOnB,IAAI,IAAK,IAAI;IAQP,QAAQ,IAAK,OAAO,CAAC,IAAI,CAAC;IAoJhC,OAAO,CAAC,mBAAmB;CAY5B"}
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { PeerMap, PeerSet } from '@libp2p/peer-collections';
|
|
2
|
-
import { PeerQueue } from '@libp2p/utils/peer-queue';
|
|
3
|
-
import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
|
|
4
|
-
import { AUTO_DIAL_CONCURRENCY, AUTO_DIAL_DISCOVERED_PEERS_DEBOUNCE, AUTO_DIAL_INTERVAL, AUTO_DIAL_MAX_QUEUE_LENGTH, AUTO_DIAL_PEER_RETRY_THRESHOLD, AUTO_DIAL_PRIORITY, LAST_DIAL_FAILURE_KEY, MIN_CONNECTIONS } from './constants.js';
|
|
5
|
-
const defaultOptions = {
|
|
6
|
-
minConnections: MIN_CONNECTIONS,
|
|
7
|
-
maxQueueLength: AUTO_DIAL_MAX_QUEUE_LENGTH,
|
|
8
|
-
autoDialConcurrency: AUTO_DIAL_CONCURRENCY,
|
|
9
|
-
autoDialPriority: AUTO_DIAL_PRIORITY,
|
|
10
|
-
autoDialInterval: AUTO_DIAL_INTERVAL,
|
|
11
|
-
autoDialPeerRetryThreshold: AUTO_DIAL_PEER_RETRY_THRESHOLD,
|
|
12
|
-
autoDialDiscoveredPeersDebounce: AUTO_DIAL_DISCOVERED_PEERS_DEBOUNCE
|
|
13
|
-
};
|
|
14
|
-
export class AutoDial {
|
|
15
|
-
connectionManager;
|
|
16
|
-
peerStore;
|
|
17
|
-
queue;
|
|
18
|
-
minConnections;
|
|
19
|
-
autoDialPriority;
|
|
20
|
-
autoDialIntervalMs;
|
|
21
|
-
autoDialMaxQueueLength;
|
|
22
|
-
autoDialPeerRetryThresholdMs;
|
|
23
|
-
autoDialDiscoveredPeersDebounce;
|
|
24
|
-
autoDialInterval;
|
|
25
|
-
started;
|
|
26
|
-
running;
|
|
27
|
-
log;
|
|
28
|
-
/**
|
|
29
|
-
* Proactively tries to connect to known peers stored in the PeerStore.
|
|
30
|
-
* It will keep the number of connections below the upper limit and sort
|
|
31
|
-
* the peers to connect based on whether we know their keys and protocols.
|
|
32
|
-
*/
|
|
33
|
-
constructor(components, init) {
|
|
34
|
-
this.connectionManager = components.connectionManager;
|
|
35
|
-
this.peerStore = components.peerStore;
|
|
36
|
-
this.minConnections = init.minConnections ?? defaultOptions.minConnections;
|
|
37
|
-
this.autoDialPriority = init.autoDialPriority ?? defaultOptions.autoDialPriority;
|
|
38
|
-
this.autoDialIntervalMs = init.autoDialInterval ?? defaultOptions.autoDialInterval;
|
|
39
|
-
this.autoDialMaxQueueLength = init.maxQueueLength ?? defaultOptions.maxQueueLength;
|
|
40
|
-
this.autoDialPeerRetryThresholdMs = init.autoDialPeerRetryThreshold ?? defaultOptions.autoDialPeerRetryThreshold;
|
|
41
|
-
this.autoDialDiscoveredPeersDebounce = init.autoDialDiscoveredPeersDebounce ?? defaultOptions.autoDialDiscoveredPeersDebounce;
|
|
42
|
-
this.log = components.logger.forComponent('libp2p:connection-manager:auto-dial');
|
|
43
|
-
this.started = false;
|
|
44
|
-
this.running = false;
|
|
45
|
-
this.queue = new PeerQueue({
|
|
46
|
-
concurrency: init.autoDialConcurrency ?? defaultOptions.autoDialConcurrency,
|
|
47
|
-
metricName: 'libp2p_autodial_queue',
|
|
48
|
-
metrics: components.metrics
|
|
49
|
-
});
|
|
50
|
-
this.queue.addEventListener('error', (evt) => {
|
|
51
|
-
this.log.error('error during auto-dial', evt.detail);
|
|
52
|
-
});
|
|
53
|
-
// check the min connection limit whenever a peer disconnects
|
|
54
|
-
components.events.addEventListener('connection:close', () => {
|
|
55
|
-
this.autoDial()
|
|
56
|
-
.catch(err => {
|
|
57
|
-
this.log.error(err);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
// sometimes peers are discovered in quick succession so add a small
|
|
61
|
-
// debounce to ensure all eligible peers are autodialed
|
|
62
|
-
let debounce;
|
|
63
|
-
// when new peers are discovered, dial them if we don't have
|
|
64
|
-
// enough connections
|
|
65
|
-
components.events.addEventListener('peer:discovery', () => {
|
|
66
|
-
clearTimeout(debounce);
|
|
67
|
-
debounce = setTimeout(() => {
|
|
68
|
-
this.autoDial()
|
|
69
|
-
.catch(err => {
|
|
70
|
-
this.log.error(err);
|
|
71
|
-
});
|
|
72
|
-
}, this.autoDialDiscoveredPeersDebounce);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
isStarted() {
|
|
76
|
-
return this.started;
|
|
77
|
-
}
|
|
78
|
-
start() {
|
|
79
|
-
this.started = true;
|
|
80
|
-
}
|
|
81
|
-
afterStart() {
|
|
82
|
-
this.autoDial()
|
|
83
|
-
.catch(err => {
|
|
84
|
-
this.log.error('error while autodialing', err);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
stop() {
|
|
88
|
-
// clear the queue
|
|
89
|
-
this.queue.clear();
|
|
90
|
-
clearTimeout(this.autoDialInterval);
|
|
91
|
-
this.started = false;
|
|
92
|
-
this.running = false;
|
|
93
|
-
}
|
|
94
|
-
async autoDial() {
|
|
95
|
-
if (!this.started || this.running) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const connections = this.connectionManager.getConnectionsMap();
|
|
99
|
-
const numConnections = connections.size;
|
|
100
|
-
// already have enough connections
|
|
101
|
-
if (numConnections >= this.minConnections) {
|
|
102
|
-
if (this.minConnections > 0) {
|
|
103
|
-
this.log.trace('have enough connections %d/%d', numConnections, this.minConnections);
|
|
104
|
-
}
|
|
105
|
-
// no need to schedule next autodial as it will be run when on
|
|
106
|
-
// connection:close event
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
if (this.queue.size > this.autoDialMaxQueueLength) {
|
|
110
|
-
this.log('not enough connections %d/%d but auto dial queue is full', numConnections, this.minConnections);
|
|
111
|
-
this.sheduleNextAutodial();
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
this.running = true;
|
|
115
|
-
this.log('not enough connections %d/%d - will dial peers to increase the number of connections', numConnections, this.minConnections);
|
|
116
|
-
const dialQueue = new PeerSet(
|
|
117
|
-
// @ts-expect-error boolean filter removes falsy peer IDs
|
|
118
|
-
this.connectionManager.getDialQueue()
|
|
119
|
-
.map(queue => queue.peerId)
|
|
120
|
-
.filter(Boolean));
|
|
121
|
-
// sort peers on whether we know protocols or public keys for them
|
|
122
|
-
const peers = await this.peerStore.all({
|
|
123
|
-
filters: [
|
|
124
|
-
// remove some peers
|
|
125
|
-
(peer) => {
|
|
126
|
-
// remove peers without addresses
|
|
127
|
-
if (peer.addresses.length === 0) {
|
|
128
|
-
this.log.trace('not autodialing %p because they have no addresses', peer.id);
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
// remove peers we are already connected to
|
|
132
|
-
if (connections.has(peer.id)) {
|
|
133
|
-
this.log.trace('not autodialing %p because they are already connected', peer.id);
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
// remove peers we are already dialling
|
|
137
|
-
if (dialQueue.has(peer.id)) {
|
|
138
|
-
this.log.trace('not autodialing %p because they are already being dialed', peer.id);
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
// remove peers already in the autodial queue
|
|
142
|
-
if (this.queue.has(peer.id)) {
|
|
143
|
-
this.log.trace('not autodialing %p because they are already being autodialed', peer.id);
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
148
|
-
]
|
|
149
|
-
});
|
|
150
|
-
// shuffle the peers - this is so peers with the same tag values will be
|
|
151
|
-
// dialled in a different order each time
|
|
152
|
-
const shuffledPeers = peers.sort(() => Math.random() > 0.5 ? 1 : -1);
|
|
153
|
-
// sort shuffled peers by tag value
|
|
154
|
-
const peerValues = new PeerMap();
|
|
155
|
-
for (const peer of shuffledPeers) {
|
|
156
|
-
if (peerValues.has(peer.id)) {
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
// sum all tag values
|
|
160
|
-
peerValues.set(peer.id, [...peer.tags.values()].reduce((acc, curr) => {
|
|
161
|
-
return acc + curr.value;
|
|
162
|
-
}, 0));
|
|
163
|
-
}
|
|
164
|
-
// sort by value, highest to lowest
|
|
165
|
-
const sortedPeers = shuffledPeers.sort((a, b) => {
|
|
166
|
-
const peerAValue = peerValues.get(a.id) ?? 0;
|
|
167
|
-
const peerBValue = peerValues.get(b.id) ?? 0;
|
|
168
|
-
if (peerAValue > peerBValue) {
|
|
169
|
-
return -1;
|
|
170
|
-
}
|
|
171
|
-
if (peerAValue < peerBValue) {
|
|
172
|
-
return 1;
|
|
173
|
-
}
|
|
174
|
-
return 0;
|
|
175
|
-
});
|
|
176
|
-
const peersThatHaveNotFailed = sortedPeers.filter(peer => {
|
|
177
|
-
const lastDialFailure = peer.metadata.get(LAST_DIAL_FAILURE_KEY);
|
|
178
|
-
if (lastDialFailure == null) {
|
|
179
|
-
return true;
|
|
180
|
-
}
|
|
181
|
-
const lastDialFailureTimestamp = parseInt(uint8ArrayToString(lastDialFailure));
|
|
182
|
-
if (isNaN(lastDialFailureTimestamp)) {
|
|
183
|
-
return true;
|
|
184
|
-
}
|
|
185
|
-
// only dial if the time since the last failure is above the retry threshold
|
|
186
|
-
return Date.now() - lastDialFailureTimestamp > this.autoDialPeerRetryThresholdMs;
|
|
187
|
-
});
|
|
188
|
-
this.log('selected %d/%d peers to dial', peersThatHaveNotFailed.length, peers.length);
|
|
189
|
-
for (const peer of peersThatHaveNotFailed) {
|
|
190
|
-
this.queue.add(async () => {
|
|
191
|
-
const numConnections = this.connectionManager.getConnectionsMap().size;
|
|
192
|
-
// Check to see if we still need to auto dial
|
|
193
|
-
if (numConnections >= this.minConnections) {
|
|
194
|
-
this.log('got enough connections now %d/%d', numConnections, this.minConnections);
|
|
195
|
-
this.queue.clear();
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
this.log('connecting to a peerStore stored peer %p', peer.id);
|
|
199
|
-
await this.connectionManager.openConnection(peer.id, {
|
|
200
|
-
priority: this.autoDialPriority
|
|
201
|
-
});
|
|
202
|
-
}, {
|
|
203
|
-
peerId: peer.id
|
|
204
|
-
}).catch(err => {
|
|
205
|
-
this.log.error('could not connect to peerStore stored peer', err);
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
this.running = false;
|
|
209
|
-
this.sheduleNextAutodial();
|
|
210
|
-
}
|
|
211
|
-
sheduleNextAutodial() {
|
|
212
|
-
if (!this.started) {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
this.autoDialInterval = setTimeout(() => {
|
|
216
|
-
this.autoDial()
|
|
217
|
-
.catch(err => {
|
|
218
|
-
this.log.error('error while autodialing', err);
|
|
219
|
-
});
|
|
220
|
-
}, this.autoDialIntervalMs);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
//# sourceMappingURL=auto-dial.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auto-dial.js","sourceRoot":"","sources":["../../../src/connection-manager/auto-dial.ts"],"names":[],"mappings":"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"}
|