libp2p 2.9.0 → 2.10.0-8484de8a2
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 +13 -17
- package/dist/index.min.js.map +4 -4
- package/dist/src/address-manager/dns-mappings.d.ts +1 -2
- package/dist/src/address-manager/dns-mappings.d.ts.map +1 -1
- package/dist/src/address-manager/dns-mappings.js +40 -44
- package/dist/src/address-manager/dns-mappings.js.map +1 -1
- package/dist/src/address-manager/index.d.ts.map +1 -1
- package/dist/src/address-manager/index.js +31 -14
- package/dist/src/address-manager/index.js.map +1 -1
- package/dist/src/address-manager/ip-mappings.d.ts +1 -0
- package/dist/src/address-manager/ip-mappings.d.ts.map +1 -1
- package/dist/src/address-manager/ip-mappings.js +51 -40
- package/dist/src/address-manager/ip-mappings.js.map +1 -1
- package/dist/src/address-manager/observed-addresses.d.ts.map +1 -1
- package/dist/src/address-manager/observed-addresses.js +1 -3
- package/dist/src/address-manager/observed-addresses.js.map +1 -1
- package/dist/src/address-manager/transport-addresses.d.ts.map +1 -1
- package/dist/src/address-manager/transport-addresses.js +6 -8
- package/dist/src/address-manager/transport-addresses.js.map +1 -1
- package/dist/src/config/connection-gater.browser.d.ts.map +1 -1
- package/dist/src/config/connection-gater.browser.js +3 -9
- package/dist/src/config/connection-gater.browser.js.map +1 -1
- package/dist/src/config.js +1 -1
- package/dist/src/config.js.map +1 -1
- package/dist/src/connection-manager/address-sorter.d.ts.map +1 -1
- package/dist/src/connection-manager/address-sorter.js +1 -2
- package/dist/src/connection-manager/address-sorter.js.map +1 -1
- package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -1
- package/dist/src/connection-manager/connection-pruner.js +7 -3
- package/dist/src/connection-manager/connection-pruner.js.map +1 -1
- package/dist/src/connection-manager/constants.defaults.d.ts +4 -0
- package/dist/src/connection-manager/constants.defaults.d.ts.map +1 -1
- package/dist/src/connection-manager/constants.defaults.js +4 -0
- package/dist/src/connection-manager/constants.defaults.js.map +1 -1
- package/dist/src/connection-manager/dial-queue.d.ts +2 -2
- package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
- package/dist/src/connection-manager/dial-queue.js +13 -25
- package/dist/src/connection-manager/dial-queue.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +10 -2
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +45 -27
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/connection-manager/reconnect-queue.js +1 -1
- package/dist/src/connection-manager/reconnect-queue.js.map +1 -1
- package/dist/src/connection-manager/utils.d.ts +31 -3
- package/dist/src/connection-manager/utils.d.ts.map +1 -1
- package/dist/src/connection-manager/utils.js +99 -18
- package/dist/src/connection-manager/utils.js.map +1 -1
- package/dist/src/connection-monitor.d.ts +1 -1
- package/dist/src/connection-monitor.d.ts.map +1 -1
- package/dist/src/connection-monitor.js +2 -3
- package/dist/src/connection-monitor.js.map +1 -1
- package/dist/src/connection.d.ts +62 -0
- package/dist/src/connection.d.ts.map +1 -0
- package/dist/src/connection.js +239 -0
- package/dist/src/connection.js.map +1 -0
- package/dist/src/get-peer.js +3 -3
- package/dist/src/get-peer.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +2 -2
- package/dist/src/libp2p.d.ts.map +1 -1
- package/dist/src/libp2p.js +5 -5
- package/dist/src/libp2p.js.map +1 -1
- package/dist/src/peer-routing.js +1 -1
- package/dist/src/peer-routing.js.map +1 -1
- package/dist/src/random-walk.d.ts.map +1 -1
- package/dist/src/random-walk.js +13 -3
- package/dist/src/random-walk.js.map +1 -1
- package/dist/src/registrar.d.ts +3 -3
- package/dist/src/registrar.d.ts.map +1 -1
- package/dist/src/registrar.js +50 -41
- package/dist/src/registrar.js.map +1 -1
- package/dist/src/transport-manager.js +15 -2
- package/dist/src/transport-manager.js.map +1 -1
- package/dist/src/upgrader.d.ts +27 -25
- package/dist/src/upgrader.d.ts.map +1 -1
- package/dist/src/upgrader.js +97 -336
- package/dist/src/upgrader.js.map +1 -1
- package/dist/src/utils.d.ts +3 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +25 -0
- package/dist/src/utils.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 +26 -30
- package/src/address-manager/dns-mappings.ts +51 -51
- package/src/address-manager/index.ts +37 -17
- package/src/address-manager/ip-mappings.ts +64 -44
- package/src/address-manager/observed-addresses.ts +1 -3
- package/src/address-manager/transport-addresses.ts +7 -9
- package/src/config/connection-gater.browser.ts +3 -12
- package/src/config.ts +1 -1
- package/src/connection-manager/address-sorter.ts +1 -2
- package/src/connection-manager/connection-pruner.ts +8 -3
- package/src/connection-manager/constants.defaults.ts +5 -0
- package/src/connection-manager/dial-queue.ts +14 -29
- package/src/connection-manager/index.ts +62 -29
- package/src/connection-manager/reconnect-queue.ts +1 -1
- package/src/connection-manager/utils.ts +129 -21
- package/src/connection-monitor.ts +3 -4
- package/src/connection.ts +316 -0
- package/src/get-peer.ts +3 -3
- package/src/index.ts +2 -2
- package/src/libp2p.ts +5 -6
- package/src/peer-routing.ts +1 -1
- package/src/random-walk.ts +13 -3
- package/src/registrar.ts +67 -54
- package/src/transport-manager.ts +18 -2
- package/src/upgrader.ts +143 -421
- package/src/utils.ts +31 -0
- package/src/version.ts +1 -1
- package/dist/src/connection/index.d.ts +0 -84
- package/dist/src/connection/index.d.ts.map +0 -1
- package/dist/src/connection/index.js +0 -144
- package/dist/src/connection/index.js.map +0 -1
- package/dist/typedoc-urls.json +0 -24
- package/src/connection/index.ts +0 -199
package/src/upgrader.ts
CHANGED
|
@@ -1,37 +1,38 @@
|
|
|
1
|
-
import { InvalidMultiaddrError,
|
|
1
|
+
import { InvalidMultiaddrError, InvalidPeerIdError } from '@libp2p/interface'
|
|
2
2
|
import * as mss from '@libp2p/multistream-select'
|
|
3
3
|
import { peerIdFromString } from '@libp2p/peer-id'
|
|
4
|
-
import { trackedMap } from '@libp2p/utils
|
|
4
|
+
import { trackedMap } from '@libp2p/utils'
|
|
5
|
+
import { CODE_P2P } from '@multiformats/multiaddr'
|
|
5
6
|
import { anySignal } from 'any-signal'
|
|
6
7
|
import { setMaxListeners } from 'main-event'
|
|
7
8
|
import { CustomProgressEvent } from 'progress-events'
|
|
8
9
|
import { raceSignal } from 'race-signal'
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
10
|
+
import { PROTOCOL_NEGOTIATION_TIMEOUT, INBOUND_UPGRADE_TIMEOUT, CONNECTION_CLOSE_TIMEOUT } from './connection-manager/constants.js'
|
|
11
|
+
import { createConnection } from './connection.js'
|
|
11
12
|
import { ConnectionDeniedError, ConnectionInterceptedError, EncryptionFailedError, MuxerUnavailableError } from './errors.js'
|
|
12
|
-
import {
|
|
13
|
-
import type { Libp2pEvents, AbortOptions, ComponentLogger, MultiaddrConnection, Connection, Stream, ConnectionProtector, NewStreamOptions, ConnectionEncrypter, SecuredConnection, ConnectionGater, Metrics, PeerId, PeerStore, StreamMuxer, StreamMuxerFactory, Upgrader as UpgraderInterface, UpgraderOptions, ConnectionLimits, SecureConnectionOptions, CounterGroup, ClearableSignal } from '@libp2p/interface'
|
|
13
|
+
import type { Libp2pEvents, AbortOptions, ComponentLogger, MultiaddrConnection, Connection, ConnectionProtector, ConnectionEncrypter, ConnectionGater, Metrics, PeerId, PeerStore, StreamMuxerFactory, Upgrader as UpgraderInterface, UpgraderOptions, ConnectionLimits, CounterGroup, ClearableSignal, MessageStream, SecuredConnection, StreamMuxer, UpgraderWithoutEncryptionOptions, SecureConnectionOptions } from '@libp2p/interface'
|
|
14
14
|
import type { ConnectionManager, Registrar } from '@libp2p/interface-internal'
|
|
15
15
|
import type { TypedEventTarget } from 'main-event'
|
|
16
16
|
|
|
17
17
|
interface CreateConnectionOptions {
|
|
18
|
+
id: string
|
|
18
19
|
cryptoProtocol: string
|
|
19
20
|
direction: 'inbound' | 'outbound'
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The raw underlying connection
|
|
24
|
+
*/
|
|
20
25
|
maConn: MultiaddrConnection
|
|
21
|
-
upgradedConn: MultiaddrConnection
|
|
22
|
-
remotePeer: PeerId
|
|
23
|
-
muxerFactory?: StreamMuxerFactory
|
|
24
|
-
limits?: ConnectionLimits
|
|
25
|
-
}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
27
|
+
/**
|
|
28
|
+
* The encrypted, multiplexed connection
|
|
29
|
+
*/
|
|
30
|
+
stream: MessageStream
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
remotePeer: PeerId
|
|
33
|
+
muxer?: StreamMuxer
|
|
34
|
+
limits?: ConnectionLimits
|
|
35
|
+
closeTimeout?: number
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
export interface UpgraderInit {
|
|
@@ -60,48 +61,13 @@ export interface UpgraderInit {
|
|
|
60
61
|
* @default 2000
|
|
61
62
|
*/
|
|
62
63
|
outboundStreamProtocolNegotiationTimeout?: number
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function findIncomingStreamLimit (protocol: string, registrar: Registrar): number | undefined {
|
|
66
|
-
try {
|
|
67
|
-
const { options } = registrar.getHandler(protocol)
|
|
68
|
-
|
|
69
|
-
return options.maxInboundStreams
|
|
70
|
-
} catch (err: any) {
|
|
71
|
-
if (err.name !== 'UnhandledProtocolError') {
|
|
72
|
-
throw err
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
64
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (options.maxOutboundStreams != null) {
|
|
84
|
-
return options.maxOutboundStreams
|
|
85
|
-
}
|
|
86
|
-
} catch (err: any) {
|
|
87
|
-
if (err.name !== 'UnhandledProtocolError') {
|
|
88
|
-
throw err
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return options.maxOutboundStreams ?? DEFAULT_MAX_OUTBOUND_STREAMS
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function countStreams (protocol: string, direction: 'inbound' | 'outbound', connection: Connection): number {
|
|
96
|
-
let streamCount = 0
|
|
97
|
-
|
|
98
|
-
connection.streams.forEach(stream => {
|
|
99
|
-
if (stream.direction === direction && stream.protocol === protocol) {
|
|
100
|
-
streamCount++
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
return streamCount
|
|
65
|
+
/**
|
|
66
|
+
* How long to wait before closing a connection
|
|
67
|
+
*
|
|
68
|
+
* @default 1_000
|
|
69
|
+
*/
|
|
70
|
+
connectionCloseTimeout?: number
|
|
105
71
|
}
|
|
106
72
|
|
|
107
73
|
export interface UpgraderComponents {
|
|
@@ -116,6 +82,10 @@ export interface UpgraderComponents {
|
|
|
116
82
|
logger: ComponentLogger
|
|
117
83
|
}
|
|
118
84
|
|
|
85
|
+
interface EncryptedConnection extends SecuredConnection {
|
|
86
|
+
protocol: string
|
|
87
|
+
}
|
|
88
|
+
|
|
119
89
|
type ConnectionDeniedType = keyof Pick<ConnectionGater, 'denyOutboundConnection' | 'denyInboundEncryptedConnection' | 'denyOutboundEncryptedConnection' | 'denyInboundUpgradedConnection' | 'denyOutboundUpgradedConnection'>
|
|
120
90
|
|
|
121
91
|
export class Upgrader implements UpgraderInterface {
|
|
@@ -133,6 +103,8 @@ export class Upgrader implements UpgraderInterface {
|
|
|
133
103
|
outboundErrors?: CounterGroup
|
|
134
104
|
}
|
|
135
105
|
|
|
106
|
+
private readonly connectionCloseTimeout?: number
|
|
107
|
+
|
|
136
108
|
constructor (components: UpgraderComponents, init: UpgraderInit) {
|
|
137
109
|
this.components = components
|
|
138
110
|
this.connectionEncrypters = trackedMap({
|
|
@@ -156,6 +128,7 @@ export class Upgrader implements UpgraderInterface {
|
|
|
156
128
|
this.inboundUpgradeTimeout = init.inboundUpgradeTimeout ?? INBOUND_UPGRADE_TIMEOUT
|
|
157
129
|
this.inboundStreamProtocolNegotiationTimeout = init.inboundStreamProtocolNegotiationTimeout ?? PROTOCOL_NEGOTIATION_TIMEOUT
|
|
158
130
|
this.outboundStreamProtocolNegotiationTimeout = init.outboundStreamProtocolNegotiationTimeout ?? PROTOCOL_NEGOTIATION_TIMEOUT
|
|
131
|
+
this.connectionCloseTimeout = init.connectionCloseTimeout ?? CONNECTION_CLOSE_TIMEOUT
|
|
159
132
|
this.events = components.events
|
|
160
133
|
this.metrics = {
|
|
161
134
|
dials: components.metrics?.registerCounterGroup('libp2p_connection_manager_dials_total'),
|
|
@@ -196,7 +169,9 @@ export class Upgrader implements UpgraderInterface {
|
|
|
196
169
|
/**
|
|
197
170
|
* Upgrades an inbound connection
|
|
198
171
|
*/
|
|
199
|
-
async upgradeInbound (maConn: MultiaddrConnection, opts: UpgraderOptions): Promise<void>
|
|
172
|
+
async upgradeInbound (maConn: MultiaddrConnection, opts: UpgraderOptions): Promise<void>
|
|
173
|
+
async upgradeInbound (maConn: MultiaddrConnection, opts: UpgraderWithoutEncryptionOptions): Promise<void>
|
|
174
|
+
async upgradeInbound (maConn: MultiaddrConnection, opts: UpgraderOptions | UpgraderWithoutEncryptionOptions): Promise<void> {
|
|
200
175
|
let accepted = false
|
|
201
176
|
|
|
202
177
|
// always apply upgrade timeout for incoming upgrades
|
|
@@ -207,7 +182,7 @@ export class Upgrader implements UpgraderInterface {
|
|
|
207
182
|
inbound: true
|
|
208
183
|
})
|
|
209
184
|
|
|
210
|
-
accepted =
|
|
185
|
+
accepted = this.components.connectionManager.acceptIncomingConnection(maConn)
|
|
211
186
|
|
|
212
187
|
if (!accepted) {
|
|
213
188
|
throw new ConnectionDeniedError('Connection denied')
|
|
@@ -240,13 +215,15 @@ export class Upgrader implements UpgraderInterface {
|
|
|
240
215
|
/**
|
|
241
216
|
* Upgrades an outbound connection
|
|
242
217
|
*/
|
|
243
|
-
async upgradeOutbound (maConn: MultiaddrConnection, opts: UpgraderOptions): Promise<Connection>
|
|
218
|
+
async upgradeOutbound (maConn: MultiaddrConnection, opts: UpgraderOptions): Promise<Connection>
|
|
219
|
+
async upgradeOutbound (maConn: MultiaddrConnection, opts: UpgraderWithoutEncryptionOptions): Promise<Connection>
|
|
220
|
+
async upgradeOutbound (maConn: MultiaddrConnection, opts: UpgraderOptions | UpgraderWithoutEncryptionOptions): Promise<Connection> {
|
|
244
221
|
try {
|
|
245
222
|
this.metrics.dials?.increment({
|
|
246
223
|
outbound: true
|
|
247
224
|
})
|
|
248
225
|
|
|
249
|
-
const idStr = maConn.remoteAddr.
|
|
226
|
+
const idStr = maConn.remoteAddr.getComponents().findLast(c => c.code === CODE_P2P)?.value
|
|
250
227
|
let remotePeerId: PeerId | undefined
|
|
251
228
|
|
|
252
229
|
if (idStr != null) {
|
|
@@ -274,62 +251,64 @@ export class Upgrader implements UpgraderInterface {
|
|
|
274
251
|
}
|
|
275
252
|
}
|
|
276
253
|
|
|
277
|
-
private async _performUpgrade (maConn: MultiaddrConnection, direction: 'inbound' | 'outbound', opts: UpgraderOptions): Promise<Connection> {
|
|
278
|
-
let
|
|
254
|
+
private async _performUpgrade (maConn: MultiaddrConnection, direction: 'inbound' | 'outbound', opts: UpgraderOptions | UpgraderWithoutEncryptionOptions): Promise<Connection> {
|
|
255
|
+
let stream: MessageStream = maConn
|
|
279
256
|
let remotePeer: PeerId
|
|
280
|
-
let upgradedConn: MultiaddrConnection
|
|
281
257
|
let muxerFactory: StreamMuxerFactory | undefined
|
|
258
|
+
let muxer: StreamMuxer | undefined
|
|
282
259
|
let cryptoProtocol
|
|
283
260
|
|
|
261
|
+
const id = `${(parseInt(String(Math.random() * 1e9))).toString(36)}${Date.now()}`
|
|
262
|
+
maConn.log = maConn.log.newScope(`${direction}:${id}`)
|
|
263
|
+
|
|
284
264
|
this.components.metrics?.trackMultiaddrConnection(maConn)
|
|
285
265
|
|
|
286
266
|
maConn.log.trace('starting the %s connection upgrade', direction)
|
|
287
267
|
|
|
288
268
|
// Protect
|
|
289
|
-
let protectedConn = maConn
|
|
290
|
-
|
|
291
269
|
if (opts?.skipProtection !== true) {
|
|
292
270
|
const protector = this.components.connectionProtector
|
|
293
271
|
|
|
294
272
|
if (protector != null) {
|
|
295
273
|
maConn.log('protecting the %s connection', direction)
|
|
296
|
-
|
|
274
|
+
stream = await protector.protect(stream, opts)
|
|
297
275
|
}
|
|
298
276
|
}
|
|
299
277
|
|
|
300
278
|
try {
|
|
301
279
|
// Encrypt the connection
|
|
302
|
-
|
|
303
|
-
|
|
280
|
+
if (isEncryptionSkipped(opts)) {
|
|
281
|
+
if (opts.remotePeer == null) {
|
|
282
|
+
throw new InvalidMultiaddrError(`${direction} connection that skipped encryption must have a peer id`)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
cryptoProtocol = 'native'
|
|
286
|
+
remotePeer = opts.remotePeer
|
|
287
|
+
} else {
|
|
288
|
+
const peerIdString = maConn.remoteAddr.getComponents().findLast(c => c.code === CODE_P2P)?.value
|
|
289
|
+
let remotePeerFromMultiaddr: PeerId | undefined
|
|
290
|
+
|
|
291
|
+
if (peerIdString != null) {
|
|
292
|
+
remotePeerFromMultiaddr = peerIdFromString(peerIdString)
|
|
293
|
+
}
|
|
294
|
+
|
|
304
295
|
opts?.onProgress?.(new CustomProgressEvent(`upgrader:encrypt-${direction}-connection`));
|
|
305
296
|
|
|
306
297
|
({
|
|
307
|
-
|
|
298
|
+
connection: stream,
|
|
308
299
|
remotePeer,
|
|
309
300
|
protocol: cryptoProtocol,
|
|
310
301
|
streamMuxer: muxerFactory
|
|
311
302
|
} = await (direction === 'inbound'
|
|
312
|
-
? this._encryptInbound(
|
|
313
|
-
|
|
303
|
+
? this._encryptInbound(stream, {
|
|
304
|
+
...opts,
|
|
305
|
+
remotePeer: remotePeerFromMultiaddr
|
|
306
|
+
})
|
|
307
|
+
: this._encryptOutbound(stream, {
|
|
308
|
+
...opts,
|
|
309
|
+
remotePeer: remotePeerFromMultiaddr
|
|
310
|
+
})
|
|
314
311
|
))
|
|
315
|
-
|
|
316
|
-
const maConn: MultiaddrConnection = {
|
|
317
|
-
...protectedConn,
|
|
318
|
-
...encryptedConn
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
await this.shouldBlockConnection(direction === 'inbound' ? 'denyInboundEncryptedConnection' : 'denyOutboundEncryptedConnection', remotePeer, maConn)
|
|
322
|
-
} else {
|
|
323
|
-
const idStr = maConn.remoteAddr.getPeerId()
|
|
324
|
-
|
|
325
|
-
if (idStr == null) {
|
|
326
|
-
throw new InvalidMultiaddrError(`${direction} connection that skipped encryption must have a peer id`)
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
const remotePeerId = peerIdFromString(idStr)
|
|
330
|
-
|
|
331
|
-
cryptoProtocol = 'native'
|
|
332
|
-
remotePeer = remotePeerId
|
|
333
312
|
}
|
|
334
313
|
|
|
335
314
|
// this can happen if we dial a multiaddr without a peer id, we only find
|
|
@@ -340,353 +319,98 @@ export class Upgrader implements UpgraderInterface {
|
|
|
340
319
|
throw err
|
|
341
320
|
}
|
|
342
321
|
|
|
343
|
-
|
|
322
|
+
// stream.pause()
|
|
323
|
+
await this.shouldBlockConnection(direction === 'inbound' ? 'denyInboundEncryptedConnection' : 'denyOutboundEncryptedConnection', remotePeer, maConn)
|
|
324
|
+
// stream.resume()
|
|
325
|
+
|
|
344
326
|
if (opts?.muxerFactory != null) {
|
|
345
327
|
muxerFactory = opts.muxerFactory
|
|
346
328
|
} else if (muxerFactory == null && this.streamMuxers.size > 0) {
|
|
347
329
|
opts?.onProgress?.(new CustomProgressEvent(`upgrader:multiplex-${direction}-connection`))
|
|
348
330
|
|
|
349
331
|
// Multiplex the connection
|
|
350
|
-
|
|
351
|
-
? this._multiplexInbound(
|
|
352
|
-
|
|
353
|
-
...encryptedConn
|
|
354
|
-
}, this.streamMuxers, opts)
|
|
355
|
-
: this._multiplexOutbound({
|
|
356
|
-
...protectedConn,
|
|
357
|
-
...encryptedConn
|
|
358
|
-
}, this.streamMuxers, opts))
|
|
359
|
-
muxerFactory = multiplexed.muxerFactory
|
|
360
|
-
upgradedConn = multiplexed.stream
|
|
332
|
+
muxerFactory = await (direction === 'inbound'
|
|
333
|
+
? this._multiplexInbound(stream, this.streamMuxers, opts)
|
|
334
|
+
: this._multiplexOutbound(stream, this.streamMuxers, opts))
|
|
361
335
|
}
|
|
362
336
|
} catch (err: any) {
|
|
363
|
-
maConn.log.error('failed to upgrade
|
|
337
|
+
maConn.log.error('failed to upgrade %s connection %s %a - %e', direction, direction === 'inbound' ? 'from' : 'to', maConn.remoteAddr, err)
|
|
364
338
|
throw err
|
|
365
339
|
}
|
|
366
340
|
|
|
367
|
-
|
|
341
|
+
// create the connection muxer if one is configured
|
|
342
|
+
if (muxerFactory != null) {
|
|
343
|
+
maConn.log('create muxer %s', muxerFactory.protocol)
|
|
344
|
+
muxer = muxerFactory.createStreamMuxer(stream)
|
|
345
|
+
}
|
|
368
346
|
|
|
369
|
-
|
|
347
|
+
// stream.pause()
|
|
348
|
+
await this.shouldBlockConnection(direction === 'inbound' ? 'denyInboundUpgradedConnection' : 'denyOutboundUpgradedConnection', remotePeer, maConn)
|
|
370
349
|
|
|
371
|
-
|
|
350
|
+
const conn = this._createConnection({
|
|
351
|
+
id,
|
|
372
352
|
cryptoProtocol,
|
|
373
353
|
direction,
|
|
374
354
|
maConn,
|
|
375
|
-
|
|
376
|
-
|
|
355
|
+
stream,
|
|
356
|
+
muxer,
|
|
377
357
|
remotePeer,
|
|
378
|
-
limits: opts?.limits
|
|
358
|
+
limits: opts?.limits,
|
|
359
|
+
closeTimeout: this.connectionCloseTimeout
|
|
379
360
|
})
|
|
361
|
+
|
|
362
|
+
conn.log('successfully upgraded connection')
|
|
363
|
+
|
|
364
|
+
// stream.resume()
|
|
365
|
+
|
|
366
|
+
return conn
|
|
380
367
|
}
|
|
381
368
|
|
|
382
369
|
/**
|
|
383
370
|
* A convenience method for generating a new `Connection`
|
|
384
371
|
*/
|
|
385
372
|
_createConnection (opts: CreateConnectionOptions): Connection {
|
|
386
|
-
const {
|
|
387
|
-
cryptoProtocol,
|
|
388
|
-
direction,
|
|
389
|
-
maConn,
|
|
390
|
-
upgradedConn,
|
|
391
|
-
remotePeer,
|
|
392
|
-
muxerFactory,
|
|
393
|
-
limits
|
|
394
|
-
} = opts
|
|
395
|
-
|
|
396
|
-
let muxer: StreamMuxer | undefined
|
|
397
|
-
let newStream: ((multicodecs: string[], options?: AbortOptions) => Promise<Stream>) | undefined
|
|
398
|
-
let connection: Connection // eslint-disable-line prefer-const
|
|
399
|
-
|
|
400
|
-
if (muxerFactory != null) {
|
|
401
|
-
// Create the muxer
|
|
402
|
-
muxer = muxerFactory.createStreamMuxer({
|
|
403
|
-
direction,
|
|
404
|
-
// Run anytime a remote stream is created
|
|
405
|
-
onIncomingStream: muxedStream => {
|
|
406
|
-
if (connection == null) {
|
|
407
|
-
return
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
const signal = AbortSignal.timeout(this.inboundStreamProtocolNegotiationTimeout)
|
|
411
|
-
setMaxListeners(Infinity, signal)
|
|
412
|
-
|
|
413
|
-
void Promise.resolve()
|
|
414
|
-
.then(async () => {
|
|
415
|
-
const protocols = this.components.registrar.getProtocols()
|
|
416
|
-
|
|
417
|
-
const { stream, protocol } = await mss.handle(muxedStream, protocols, {
|
|
418
|
-
signal,
|
|
419
|
-
log: muxedStream.log,
|
|
420
|
-
yieldBytes: false
|
|
421
|
-
})
|
|
422
|
-
|
|
423
|
-
if (connection == null) {
|
|
424
|
-
return
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
connection.log('incoming stream opened on %s', protocol)
|
|
428
|
-
|
|
429
|
-
const incomingLimit = findIncomingStreamLimit(protocol, this.components.registrar)
|
|
430
|
-
const streamCount = countStreams(protocol, 'inbound', connection)
|
|
431
|
-
|
|
432
|
-
if (streamCount === incomingLimit) {
|
|
433
|
-
const err = new TooManyInboundProtocolStreamsError(`Too many inbound protocol streams for protocol "${protocol}" - limit ${incomingLimit}`)
|
|
434
|
-
muxedStream.abort(err)
|
|
435
|
-
|
|
436
|
-
throw err
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
// after the handshake the returned stream can have early data so override
|
|
440
|
-
// the source/sink
|
|
441
|
-
muxedStream.source = stream.source
|
|
442
|
-
muxedStream.sink = stream.sink
|
|
443
|
-
muxedStream.protocol = protocol
|
|
444
|
-
|
|
445
|
-
// allow closing the write end of a not-yet-negotiated stream
|
|
446
|
-
if (stream.closeWrite != null) {
|
|
447
|
-
muxedStream.closeWrite = stream.closeWrite
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// allow closing the read end of a not-yet-negotiated stream
|
|
451
|
-
if (stream.closeRead != null) {
|
|
452
|
-
muxedStream.closeRead = stream.closeRead
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// make sure we don't try to negotiate a stream we are closing
|
|
456
|
-
if (stream.close != null) {
|
|
457
|
-
muxedStream.close = stream.close
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
// If a protocol stream has been successfully negotiated and is to be passed to the application,
|
|
461
|
-
// the peer store should ensure that the peer is registered with that protocol
|
|
462
|
-
await this.components.peerStore.merge(remotePeer, {
|
|
463
|
-
protocols: [protocol]
|
|
464
|
-
}, {
|
|
465
|
-
signal
|
|
466
|
-
})
|
|
467
|
-
|
|
468
|
-
this.components.metrics?.trackProtocolStream(muxedStream, connection)
|
|
469
|
-
|
|
470
|
-
this._onStream({ connection, stream: muxedStream, protocol })
|
|
471
|
-
})
|
|
472
|
-
.catch(async err => {
|
|
473
|
-
connection.log.error('error handling incoming stream id %s - %e', muxedStream.id, err)
|
|
474
|
-
|
|
475
|
-
if (muxedStream.timeline.close == null) {
|
|
476
|
-
await muxedStream.close({
|
|
477
|
-
signal
|
|
478
|
-
})
|
|
479
|
-
.catch(err => muxedStream.abort(err))
|
|
480
|
-
}
|
|
481
|
-
})
|
|
482
|
-
}
|
|
483
|
-
})
|
|
484
|
-
|
|
485
|
-
newStream = async (protocols: string[], options: NewStreamOptions = {}): Promise<Stream> => {
|
|
486
|
-
if (muxer == null) {
|
|
487
|
-
throw new MuxerUnavailableError('Connection is not multiplexed')
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
connection.log.trace('starting new stream for protocols %s', protocols)
|
|
491
|
-
const muxedStream = await muxer.newStream()
|
|
492
|
-
connection.log.trace('started new stream %s for protocols %s', muxedStream.id, protocols)
|
|
493
|
-
|
|
494
|
-
try {
|
|
495
|
-
if (options.signal == null) {
|
|
496
|
-
muxedStream.log('no abort signal was passed while trying to negotiate protocols %s falling back to default timeout', protocols)
|
|
497
|
-
|
|
498
|
-
const signal = AbortSignal.timeout(this.outboundStreamProtocolNegotiationTimeout)
|
|
499
|
-
setMaxListeners(Infinity, signal)
|
|
500
|
-
|
|
501
|
-
options = {
|
|
502
|
-
...options,
|
|
503
|
-
signal
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
muxedStream.log.trace('selecting protocol from protocols %s', protocols)
|
|
508
|
-
|
|
509
|
-
const {
|
|
510
|
-
stream,
|
|
511
|
-
protocol
|
|
512
|
-
} = await mss.select(muxedStream, protocols, {
|
|
513
|
-
...options,
|
|
514
|
-
log: muxedStream.log,
|
|
515
|
-
yieldBytes: true
|
|
516
|
-
})
|
|
517
|
-
|
|
518
|
-
muxedStream.log.trace('selected protocol %s', protocol)
|
|
519
|
-
|
|
520
|
-
const outgoingLimit = findOutgoingStreamLimit(protocol, this.components.registrar, options)
|
|
521
|
-
const streamCount = countStreams(protocol, 'outbound', connection)
|
|
522
|
-
|
|
523
|
-
if (streamCount >= outgoingLimit) {
|
|
524
|
-
const err = new TooManyOutboundProtocolStreamsError(`Too many outbound protocol streams for protocol "${protocol}" - ${streamCount}/${outgoingLimit}`)
|
|
525
|
-
muxedStream.abort(err)
|
|
526
|
-
|
|
527
|
-
throw err
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// If a protocol stream has been successfully negotiated and is to be passed to the application,
|
|
531
|
-
// the peer store should ensure that the peer is registered with that protocol
|
|
532
|
-
await this.components.peerStore.merge(remotePeer, {
|
|
533
|
-
protocols: [protocol]
|
|
534
|
-
})
|
|
535
|
-
|
|
536
|
-
// after the handshake the returned stream can have early data so override
|
|
537
|
-
// the source/sink
|
|
538
|
-
muxedStream.source = stream.source
|
|
539
|
-
muxedStream.sink = stream.sink
|
|
540
|
-
muxedStream.protocol = protocol
|
|
541
|
-
|
|
542
|
-
// allow closing the write end of a not-yet-negotiated stream
|
|
543
|
-
if (stream.closeWrite != null) {
|
|
544
|
-
muxedStream.closeWrite = stream.closeWrite
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
// allow closing the read end of a not-yet-negotiated stream
|
|
548
|
-
if (stream.closeRead != null) {
|
|
549
|
-
muxedStream.closeRead = stream.closeRead
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
// make sure we don't try to negotiate a stream we are closing
|
|
553
|
-
if (stream.close != null) {
|
|
554
|
-
muxedStream.close = stream.close
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
this.components.metrics?.trackProtocolStream(muxedStream, connection)
|
|
558
|
-
|
|
559
|
-
return muxedStream
|
|
560
|
-
} catch (err: any) {
|
|
561
|
-
connection.log.error('could not create new outbound stream on connection %s %a for protocols %s - %e', direction === 'inbound' ? 'from' : 'to', opts.maConn.remoteAddr, protocols, err)
|
|
562
|
-
|
|
563
|
-
if (muxedStream.timeline.close == null) {
|
|
564
|
-
muxedStream.abort(err)
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
throw err
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
// Pipe all data through the muxer
|
|
572
|
-
void Promise.all([
|
|
573
|
-
muxer.sink(upgradedConn.source),
|
|
574
|
-
upgradedConn.sink(muxer.source)
|
|
575
|
-
]).catch(err => {
|
|
576
|
-
connection.log.error('error piping data through muxer - %e', err)
|
|
577
|
-
})
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
const _timeline = maConn.timeline
|
|
581
|
-
maConn.timeline = new Proxy(_timeline, {
|
|
582
|
-
set: (...args) => {
|
|
583
|
-
if (args[1] === 'close' && args[2] != null && _timeline.close == null) {
|
|
584
|
-
// Wait for close to finish before notifying of the closure
|
|
585
|
-
(async () => {
|
|
586
|
-
try {
|
|
587
|
-
if (connection.status === 'open') {
|
|
588
|
-
await connection.close()
|
|
589
|
-
}
|
|
590
|
-
} catch (err: any) {
|
|
591
|
-
connection.log.error('error closing connection after timeline close %e', err)
|
|
592
|
-
} finally {
|
|
593
|
-
this.events.safeDispatchEvent('connection:close', {
|
|
594
|
-
detail: connection
|
|
595
|
-
})
|
|
596
|
-
}
|
|
597
|
-
})().catch(err => {
|
|
598
|
-
connection.log.error('error thrown while dispatching connection:close event %e', err)
|
|
599
|
-
})
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
return Reflect.set(...args)
|
|
603
|
-
}
|
|
604
|
-
})
|
|
605
|
-
maConn.timeline.upgraded = Date.now()
|
|
606
|
-
|
|
607
|
-
const errConnectionNotMultiplexed = (): any => {
|
|
608
|
-
throw new MuxerUnavailableError('Connection is not multiplexed')
|
|
609
|
-
}
|
|
610
|
-
|
|
611
373
|
// Create the connection
|
|
612
|
-
connection = createConnection({
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
timeline: maConn.timeline,
|
|
618
|
-
multiplexer: muxer?.protocol,
|
|
619
|
-
encryption: cryptoProtocol,
|
|
620
|
-
limits,
|
|
621
|
-
logger: this.components.logger,
|
|
622
|
-
newStream: newStream ?? errConnectionNotMultiplexed,
|
|
623
|
-
getStreams: () => {
|
|
624
|
-
return muxer?.streams ?? []
|
|
625
|
-
},
|
|
626
|
-
close: async (options?: AbortOptions) => {
|
|
627
|
-
// ensure remaining streams are closed gracefully
|
|
628
|
-
await muxer?.close(options)
|
|
629
|
-
|
|
630
|
-
// close the underlying transport
|
|
631
|
-
await maConn.close(options)
|
|
632
|
-
},
|
|
633
|
-
abort: (err) => {
|
|
634
|
-
maConn.abort(err)
|
|
374
|
+
const connection = createConnection(this.components, {
|
|
375
|
+
...opts,
|
|
376
|
+
outboundStreamProtocolNegotiationTimeout: this.outboundStreamProtocolNegotiationTimeout,
|
|
377
|
+
inboundStreamProtocolNegotiationTimeout: this.inboundStreamProtocolNegotiationTimeout
|
|
378
|
+
})
|
|
635
379
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
380
|
+
connection.addEventListener('close', () => {
|
|
381
|
+
this.events.safeDispatchEvent('connection:close', {
|
|
382
|
+
detail: connection
|
|
383
|
+
})
|
|
639
384
|
})
|
|
640
385
|
|
|
641
386
|
this.events.safeDispatchEvent('connection:open', {
|
|
642
387
|
detail: connection
|
|
643
388
|
})
|
|
644
389
|
|
|
645
|
-
// @ts-expect-error nah
|
|
646
|
-
connection.__maConnTimeline = _timeline
|
|
647
|
-
|
|
648
390
|
return connection
|
|
649
391
|
}
|
|
650
392
|
|
|
651
|
-
/**
|
|
652
|
-
* Routes incoming streams to the correct handler
|
|
653
|
-
*/
|
|
654
|
-
_onStream (opts: OnStreamOptions): void {
|
|
655
|
-
const { connection, stream, protocol } = opts
|
|
656
|
-
const { handler, options } = this.components.registrar.getHandler(protocol)
|
|
657
|
-
|
|
658
|
-
if (connection.limits != null && options.runOnLimitedConnection !== true) {
|
|
659
|
-
throw new LimitedConnectionError('Cannot open protocol stream on limited connection')
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
handler({ connection, stream })
|
|
663
|
-
}
|
|
664
|
-
|
|
665
393
|
/**
|
|
666
394
|
* Attempts to encrypt the incoming `connection` with the provided `cryptos`
|
|
667
395
|
*/
|
|
668
|
-
async _encryptInbound (connection:
|
|
396
|
+
async _encryptInbound (connection: MessageStream, options?: SecureConnectionOptions): Promise<EncryptedConnection> {
|
|
669
397
|
const protocols = Array.from(this.connectionEncrypters.keys())
|
|
670
398
|
|
|
671
399
|
try {
|
|
672
|
-
const
|
|
673
|
-
...options,
|
|
674
|
-
log: connection.log
|
|
675
|
-
})
|
|
400
|
+
const protocol = await mss.handle(connection, protocols, options)
|
|
676
401
|
const encrypter = this.connectionEncrypters.get(protocol)
|
|
677
402
|
|
|
678
403
|
if (encrypter == null) {
|
|
679
404
|
throw new EncryptionFailedError(`no crypto module found for ${protocol}`)
|
|
680
405
|
}
|
|
681
406
|
|
|
682
|
-
connection.log('encrypting inbound connection
|
|
407
|
+
connection.log('encrypting inbound connection using %s', protocol)
|
|
683
408
|
|
|
684
409
|
return {
|
|
685
|
-
...await encrypter.secureInbound(
|
|
410
|
+
...await encrypter.secureInbound(connection, options),
|
|
686
411
|
protocol
|
|
687
412
|
}
|
|
688
413
|
} catch (err: any) {
|
|
689
|
-
connection.log.error('encrypting inbound connection from %a failed', connection.remoteAddr, err)
|
|
690
414
|
throw new EncryptionFailedError(err.message)
|
|
691
415
|
}
|
|
692
416
|
}
|
|
@@ -695,31 +419,26 @@ export class Upgrader implements UpgraderInterface {
|
|
|
695
419
|
* Attempts to encrypt the given `connection` with the provided connection encrypters.
|
|
696
420
|
* The first `ConnectionEncrypter` module to succeed will be used
|
|
697
421
|
*/
|
|
698
|
-
async _encryptOutbound (connection:
|
|
422
|
+
async _encryptOutbound (connection: MessageStream, options?: SecureConnectionOptions): Promise<EncryptedConnection> {
|
|
699
423
|
const protocols = Array.from(this.connectionEncrypters.keys())
|
|
700
424
|
|
|
701
425
|
try {
|
|
702
426
|
connection.log.trace('selecting encrypter from %s', protocols)
|
|
703
427
|
|
|
704
|
-
const
|
|
705
|
-
...options,
|
|
706
|
-
log: connection.log,
|
|
707
|
-
yieldBytes: true
|
|
708
|
-
})
|
|
428
|
+
const protocol = await mss.select(connection, protocols, options)
|
|
709
429
|
const encrypter = this.connectionEncrypters.get(protocol)
|
|
710
430
|
|
|
711
431
|
if (encrypter == null) {
|
|
712
432
|
throw new EncryptionFailedError(`no crypto module found for ${protocol}`)
|
|
713
433
|
}
|
|
714
434
|
|
|
715
|
-
connection.log('encrypting outbound connection
|
|
435
|
+
connection.log('encrypting outbound connection using %s', protocol)
|
|
716
436
|
|
|
717
437
|
return {
|
|
718
|
-
...await encrypter.secureOutbound(
|
|
438
|
+
...await encrypter.secureOutbound(connection, options),
|
|
719
439
|
protocol
|
|
720
440
|
}
|
|
721
441
|
} catch (err: any) {
|
|
722
|
-
connection.log.error('encrypting outbound connection to %a failed', connection.remoteAddr, err)
|
|
723
442
|
throw new EncryptionFailedError(err.message)
|
|
724
443
|
}
|
|
725
444
|
}
|
|
@@ -728,27 +447,23 @@ export class Upgrader implements UpgraderInterface {
|
|
|
728
447
|
* Selects one of the given muxers via multistream-select. That
|
|
729
448
|
* muxer will be used for all future streams on the connection.
|
|
730
449
|
*/
|
|
731
|
-
async _multiplexOutbound (
|
|
450
|
+
async _multiplexOutbound (maConn: MessageStream, muxers: Map<string, StreamMuxerFactory>, options: AbortOptions): Promise<StreamMuxerFactory> {
|
|
732
451
|
const protocols = Array.from(muxers.keys())
|
|
733
|
-
|
|
734
|
-
try {
|
|
735
|
-
connection.log.trace('selecting stream muxer from %s', protocols)
|
|
452
|
+
maConn.log('outbound selecting muxer %s', protocols)
|
|
736
453
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
} = await mss.select(connection, protocols, {
|
|
741
|
-
...options,
|
|
742
|
-
log: connection.log,
|
|
743
|
-
yieldBytes: true
|
|
744
|
-
})
|
|
745
|
-
|
|
746
|
-
connection.log('selected %s as muxer protocol', protocol)
|
|
454
|
+
try {
|
|
455
|
+
maConn.log.trace('selecting stream muxer from %s', protocols)
|
|
456
|
+
const protocol = await mss.select(maConn, protocols, options)
|
|
747
457
|
const muxerFactory = muxers.get(protocol)
|
|
748
458
|
|
|
749
|
-
|
|
459
|
+
if (muxerFactory == null) {
|
|
460
|
+
throw new MuxerUnavailableError(`No muxer configured for protocol "${protocol}"`)
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
maConn.log('selected %s as muxer protocol', protocol)
|
|
464
|
+
return muxerFactory
|
|
750
465
|
} catch (err: any) {
|
|
751
|
-
|
|
466
|
+
maConn.log.error('error multiplexing outbound connection', err)
|
|
752
467
|
throw new MuxerUnavailableError(String(err))
|
|
753
468
|
}
|
|
754
469
|
}
|
|
@@ -757,20 +472,23 @@ export class Upgrader implements UpgraderInterface {
|
|
|
757
472
|
* Registers support for one of the given muxers via multistream-select. The
|
|
758
473
|
* selected muxer will be used for all future streams on the connection.
|
|
759
474
|
*/
|
|
760
|
-
async _multiplexInbound (
|
|
475
|
+
async _multiplexInbound (maConn: MessageStream, muxers: Map<string, StreamMuxerFactory>, options: AbortOptions): Promise<StreamMuxerFactory> {
|
|
761
476
|
const protocols = Array.from(muxers.keys())
|
|
762
|
-
|
|
477
|
+
maConn.log('inbound handling muxers %s', protocols)
|
|
763
478
|
try {
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
log: connection.log
|
|
767
|
-
})
|
|
479
|
+
maConn.log.trace('selecting stream muxer from %s', protocols)
|
|
480
|
+
const protocol = await mss.handle(maConn, protocols, options)
|
|
768
481
|
const muxerFactory = muxers.get(protocol)
|
|
769
482
|
|
|
770
|
-
|
|
483
|
+
if (muxerFactory == null) {
|
|
484
|
+
throw new MuxerUnavailableError(`No muxer configured for protocol "${protocol}"`)
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
maConn.log('selected %s as muxer protocol', protocol)
|
|
488
|
+
return muxerFactory
|
|
771
489
|
} catch (err: any) {
|
|
772
|
-
|
|
773
|
-
throw
|
|
490
|
+
maConn.log.error('error multiplexing inbound connection', err)
|
|
491
|
+
throw err
|
|
774
492
|
}
|
|
775
493
|
}
|
|
776
494
|
|
|
@@ -782,3 +500,7 @@ export class Upgrader implements UpgraderInterface {
|
|
|
782
500
|
return this.streamMuxers
|
|
783
501
|
}
|
|
784
502
|
}
|
|
503
|
+
|
|
504
|
+
function isEncryptionSkipped (opts?: any): opts is UpgraderWithoutEncryptionOptions {
|
|
505
|
+
return opts.skipEncryption === true
|
|
506
|
+
}
|