libp2p 2.9.0 → 2.10.0-a02cb0461

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/dist/index.min.js +13 -17
  2. package/dist/index.min.js.map +4 -4
  3. package/dist/src/address-manager/dns-mappings.d.ts.map +1 -1
  4. package/dist/src/address-manager/dns-mappings.js +2 -3
  5. package/dist/src/address-manager/dns-mappings.js.map +1 -1
  6. package/dist/src/address-manager/index.d.ts.map +1 -1
  7. package/dist/src/address-manager/index.js +1 -3
  8. package/dist/src/address-manager/index.js.map +1 -1
  9. package/dist/src/address-manager/ip-mappings.js +1 -1
  10. package/dist/src/address-manager/ip-mappings.js.map +1 -1
  11. package/dist/src/address-manager/observed-addresses.d.ts.map +1 -1
  12. package/dist/src/address-manager/observed-addresses.js +1 -3
  13. package/dist/src/address-manager/observed-addresses.js.map +1 -1
  14. package/dist/src/address-manager/transport-addresses.d.ts.map +1 -1
  15. package/dist/src/address-manager/transport-addresses.js +1 -3
  16. package/dist/src/address-manager/transport-addresses.js.map +1 -1
  17. package/dist/src/config/connection-gater.browser.js +1 -1
  18. package/dist/src/config/connection-gater.browser.js.map +1 -1
  19. package/dist/src/config.js +1 -1
  20. package/dist/src/config.js.map +1 -1
  21. package/dist/src/connection-manager/address-sorter.d.ts.map +1 -1
  22. package/dist/src/connection-manager/address-sorter.js +1 -2
  23. package/dist/src/connection-manager/address-sorter.js.map +1 -1
  24. package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -1
  25. package/dist/src/connection-manager/connection-pruner.js +1 -2
  26. package/dist/src/connection-manager/connection-pruner.js.map +1 -1
  27. package/dist/src/connection-manager/constants.defaults.d.ts +4 -0
  28. package/dist/src/connection-manager/constants.defaults.d.ts.map +1 -1
  29. package/dist/src/connection-manager/constants.defaults.js +4 -0
  30. package/dist/src/connection-manager/constants.defaults.js.map +1 -1
  31. package/dist/src/connection-manager/dial-queue.d.ts +2 -2
  32. package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
  33. package/dist/src/connection-manager/dial-queue.js +11 -23
  34. package/dist/src/connection-manager/dial-queue.js.map +1 -1
  35. package/dist/src/connection-manager/index.d.ts +10 -2
  36. package/dist/src/connection-manager/index.d.ts.map +1 -1
  37. package/dist/src/connection-manager/index.js +29 -19
  38. package/dist/src/connection-manager/index.js.map +1 -1
  39. package/dist/src/connection-manager/reconnect-queue.js +1 -1
  40. package/dist/src/connection-manager/reconnect-queue.js.map +1 -1
  41. package/dist/src/connection-manager/utils.d.ts +28 -0
  42. package/dist/src/connection-manager/utils.d.ts.map +1 -1
  43. package/dist/src/connection-manager/utils.js +78 -0
  44. package/dist/src/connection-manager/utils.js.map +1 -1
  45. package/dist/src/connection-monitor.d.ts +1 -1
  46. package/dist/src/connection-monitor.d.ts.map +1 -1
  47. package/dist/src/connection-monitor.js +2 -3
  48. package/dist/src/connection-monitor.js.map +1 -1
  49. package/dist/src/connection.d.ts +62 -0
  50. package/dist/src/connection.d.ts.map +1 -0
  51. package/dist/src/connection.js +239 -0
  52. package/dist/src/connection.js.map +1 -0
  53. package/dist/src/index.d.ts +2 -2
  54. package/dist/src/index.js +2 -2
  55. package/dist/src/libp2p.d.ts.map +1 -1
  56. package/dist/src/libp2p.js +3 -3
  57. package/dist/src/libp2p.js.map +1 -1
  58. package/dist/src/peer-routing.js +1 -1
  59. package/dist/src/peer-routing.js.map +1 -1
  60. package/dist/src/random-walk.d.ts.map +1 -1
  61. package/dist/src/random-walk.js +13 -3
  62. package/dist/src/random-walk.js.map +1 -1
  63. package/dist/src/registrar.d.ts +3 -3
  64. package/dist/src/registrar.d.ts.map +1 -1
  65. package/dist/src/registrar.js +50 -41
  66. package/dist/src/registrar.js.map +1 -1
  67. package/dist/src/transport-manager.js +15 -2
  68. package/dist/src/transport-manager.js.map +1 -1
  69. package/dist/src/upgrader.d.ts +27 -25
  70. package/dist/src/upgrader.d.ts.map +1 -1
  71. package/dist/src/upgrader.js +95 -335
  72. package/dist/src/upgrader.js.map +1 -1
  73. package/dist/src/utils.d.ts +3 -0
  74. package/dist/src/utils.d.ts.map +1 -0
  75. package/dist/src/utils.js +25 -0
  76. package/dist/src/utils.js.map +1 -0
  77. package/dist/src/version.d.ts +1 -1
  78. package/dist/src/version.d.ts.map +1 -1
  79. package/dist/src/version.js +1 -1
  80. package/dist/src/version.js.map +1 -1
  81. package/package.json +26 -30
  82. package/src/address-manager/dns-mappings.ts +2 -3
  83. package/src/address-manager/index.ts +2 -4
  84. package/src/address-manager/ip-mappings.ts +1 -1
  85. package/src/address-manager/observed-addresses.ts +1 -3
  86. package/src/address-manager/transport-addresses.ts +1 -3
  87. package/src/config/connection-gater.browser.ts +1 -1
  88. package/src/config.ts +1 -1
  89. package/src/connection-manager/address-sorter.ts +1 -2
  90. package/src/connection-manager/connection-pruner.ts +1 -2
  91. package/src/connection-manager/constants.defaults.ts +5 -0
  92. package/src/connection-manager/dial-queue.ts +12 -27
  93. package/src/connection-manager/index.ts +44 -21
  94. package/src/connection-manager/reconnect-queue.ts +1 -1
  95. package/src/connection-manager/utils.ts +104 -0
  96. package/src/connection-monitor.ts +3 -4
  97. package/src/connection.ts +316 -0
  98. package/src/index.ts +2 -2
  99. package/src/libp2p.ts +3 -4
  100. package/src/peer-routing.ts +1 -1
  101. package/src/random-walk.ts +13 -3
  102. package/src/registrar.ts +67 -54
  103. package/src/transport-manager.ts +18 -2
  104. package/src/upgrader.ts +141 -420
  105. package/src/utils.ts +31 -0
  106. package/src/version.ts +1 -1
  107. package/dist/src/connection/index.d.ts +0 -84
  108. package/dist/src/connection/index.d.ts.map +0 -1
  109. package/dist/src/connection/index.js +0 -144
  110. package/dist/src/connection/index.js.map +0 -1
  111. package/dist/typedoc-urls.json +0 -24
  112. package/src/connection/index.ts +0 -199
package/src/upgrader.ts CHANGED
@@ -1,37 +1,37 @@
1
- import { InvalidMultiaddrError, TooManyInboundProtocolStreamsError, TooManyOutboundProtocolStreamsError, LimitedConnectionError, InvalidPeerIdError } from '@libp2p/interface'
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/tracked-map'
4
+ import { trackedMap } from '@libp2p/utils'
5
5
  import { anySignal } from 'any-signal'
6
6
  import { setMaxListeners } from 'main-event'
7
7
  import { CustomProgressEvent } from 'progress-events'
8
8
  import { raceSignal } from 'race-signal'
9
- import { createConnection } from './connection/index.js'
10
- import { PROTOCOL_NEGOTIATION_TIMEOUT, INBOUND_UPGRADE_TIMEOUT } from './connection-manager/constants.js'
9
+ import { PROTOCOL_NEGOTIATION_TIMEOUT, INBOUND_UPGRADE_TIMEOUT, CONNECTION_CLOSE_TIMEOUT } from './connection-manager/constants.js'
10
+ import { createConnection } from './connection.js'
11
11
  import { ConnectionDeniedError, ConnectionInterceptedError, EncryptionFailedError, MuxerUnavailableError } from './errors.js'
12
- import { DEFAULT_MAX_INBOUND_STREAMS, DEFAULT_MAX_OUTBOUND_STREAMS } from './registrar.js'
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'
12
+ 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
13
  import type { ConnectionManager, Registrar } from '@libp2p/interface-internal'
15
14
  import type { TypedEventTarget } from 'main-event'
16
15
 
17
16
  interface CreateConnectionOptions {
17
+ id: string
18
18
  cryptoProtocol: string
19
19
  direction: 'inbound' | 'outbound'
20
+
21
+ /**
22
+ * The raw underlying connection
23
+ */
20
24
  maConn: MultiaddrConnection
21
- upgradedConn: MultiaddrConnection
22
- remotePeer: PeerId
23
- muxerFactory?: StreamMuxerFactory
24
- limits?: ConnectionLimits
25
- }
26
25
 
27
- interface OnStreamOptions {
28
- connection: Connection
29
- stream: Stream
30
- protocol: string
31
- }
26
+ /**
27
+ * The encrypted, multiplexed connection
28
+ */
29
+ stream: MessageStream
32
30
 
33
- export interface CryptoResult extends SecuredConnection<MultiaddrConnection> {
34
- protocol: string
31
+ remotePeer: PeerId
32
+ muxer?: StreamMuxer
33
+ limits?: ConnectionLimits
34
+ closeTimeout?: number
35
35
  }
36
36
 
37
37
  export interface UpgraderInit {
@@ -60,48 +60,13 @@ export interface UpgraderInit {
60
60
  * @default 2000
61
61
  */
62
62
  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
63
 
76
- return DEFAULT_MAX_INBOUND_STREAMS
77
- }
78
-
79
- function findOutgoingStreamLimit (protocol: string, registrar: Registrar, options: NewStreamOptions = {}): number {
80
- try {
81
- const { options } = registrar.getHandler(protocol)
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
64
+ /**
65
+ * How long to wait before closing a connection
66
+ *
67
+ * @default 1_000
68
+ */
69
+ connectionCloseTimeout?: number
105
70
  }
106
71
 
107
72
  export interface UpgraderComponents {
@@ -116,6 +81,10 @@ export interface UpgraderComponents {
116
81
  logger: ComponentLogger
117
82
  }
118
83
 
84
+ interface EncryptedConnection extends SecuredConnection {
85
+ protocol: string
86
+ }
87
+
119
88
  type ConnectionDeniedType = keyof Pick<ConnectionGater, 'denyOutboundConnection' | 'denyInboundEncryptedConnection' | 'denyOutboundEncryptedConnection' | 'denyInboundUpgradedConnection' | 'denyOutboundUpgradedConnection'>
120
89
 
121
90
  export class Upgrader implements UpgraderInterface {
@@ -133,6 +102,8 @@ export class Upgrader implements UpgraderInterface {
133
102
  outboundErrors?: CounterGroup
134
103
  }
135
104
 
105
+ private readonly connectionCloseTimeout?: number
106
+
136
107
  constructor (components: UpgraderComponents, init: UpgraderInit) {
137
108
  this.components = components
138
109
  this.connectionEncrypters = trackedMap({
@@ -156,6 +127,7 @@ export class Upgrader implements UpgraderInterface {
156
127
  this.inboundUpgradeTimeout = init.inboundUpgradeTimeout ?? INBOUND_UPGRADE_TIMEOUT
157
128
  this.inboundStreamProtocolNegotiationTimeout = init.inboundStreamProtocolNegotiationTimeout ?? PROTOCOL_NEGOTIATION_TIMEOUT
158
129
  this.outboundStreamProtocolNegotiationTimeout = init.outboundStreamProtocolNegotiationTimeout ?? PROTOCOL_NEGOTIATION_TIMEOUT
130
+ this.connectionCloseTimeout = init.connectionCloseTimeout ?? CONNECTION_CLOSE_TIMEOUT
159
131
  this.events = components.events
160
132
  this.metrics = {
161
133
  dials: components.metrics?.registerCounterGroup('libp2p_connection_manager_dials_total'),
@@ -196,7 +168,9 @@ export class Upgrader implements UpgraderInterface {
196
168
  /**
197
169
  * Upgrades an inbound connection
198
170
  */
199
- async upgradeInbound (maConn: MultiaddrConnection, opts: UpgraderOptions): Promise<void> {
171
+ async upgradeInbound (maConn: MultiaddrConnection, opts: UpgraderOptions): Promise<void>
172
+ async upgradeInbound (maConn: MultiaddrConnection, opts: UpgraderWithoutEncryptionOptions): Promise<void>
173
+ async upgradeInbound (maConn: MultiaddrConnection, opts: UpgraderOptions | UpgraderWithoutEncryptionOptions): Promise<void> {
200
174
  let accepted = false
201
175
 
202
176
  // always apply upgrade timeout for incoming upgrades
@@ -207,7 +181,7 @@ export class Upgrader implements UpgraderInterface {
207
181
  inbound: true
208
182
  })
209
183
 
210
- accepted = await raceSignal(this.components.connectionManager.acceptIncomingConnection(maConn), signal)
184
+ accepted = this.components.connectionManager.acceptIncomingConnection(maConn)
211
185
 
212
186
  if (!accepted) {
213
187
  throw new ConnectionDeniedError('Connection denied')
@@ -240,7 +214,9 @@ export class Upgrader implements UpgraderInterface {
240
214
  /**
241
215
  * Upgrades an outbound connection
242
216
  */
243
- async upgradeOutbound (maConn: MultiaddrConnection, opts: UpgraderOptions): Promise<Connection> {
217
+ async upgradeOutbound (maConn: MultiaddrConnection, opts: UpgraderOptions): Promise<Connection>
218
+ async upgradeOutbound (maConn: MultiaddrConnection, opts: UpgraderWithoutEncryptionOptions): Promise<Connection>
219
+ async upgradeOutbound (maConn: MultiaddrConnection, opts: UpgraderOptions | UpgraderWithoutEncryptionOptions): Promise<Connection> {
244
220
  try {
245
221
  this.metrics.dials?.increment({
246
222
  outbound: true
@@ -274,62 +250,64 @@ export class Upgrader implements UpgraderInterface {
274
250
  }
275
251
  }
276
252
 
277
- private async _performUpgrade (maConn: MultiaddrConnection, direction: 'inbound' | 'outbound', opts: UpgraderOptions): Promise<Connection> {
278
- let encryptedConn: MultiaddrConnection
253
+ private async _performUpgrade (maConn: MultiaddrConnection, direction: 'inbound' | 'outbound', opts: UpgraderOptions | UpgraderWithoutEncryptionOptions): Promise<Connection> {
254
+ let stream: MessageStream = maConn
279
255
  let remotePeer: PeerId
280
- let upgradedConn: MultiaddrConnection
281
256
  let muxerFactory: StreamMuxerFactory | undefined
257
+ let muxer: StreamMuxer | undefined
282
258
  let cryptoProtocol
283
259
 
260
+ const id = `${(parseInt(String(Math.random() * 1e9))).toString(36)}${Date.now()}`
261
+ maConn.log = maConn.log.newScope(`${direction}:${id}`)
262
+
284
263
  this.components.metrics?.trackMultiaddrConnection(maConn)
285
264
 
286
265
  maConn.log.trace('starting the %s connection upgrade', direction)
287
266
 
288
267
  // Protect
289
- let protectedConn = maConn
290
-
291
268
  if (opts?.skipProtection !== true) {
292
269
  const protector = this.components.connectionProtector
293
270
 
294
271
  if (protector != null) {
295
272
  maConn.log('protecting the %s connection', direction)
296
- protectedConn = await protector.protect(maConn, opts)
273
+ stream = await protector.protect(stream, opts)
297
274
  }
298
275
  }
299
276
 
300
277
  try {
301
278
  // Encrypt the connection
302
- encryptedConn = protectedConn
303
- if (opts?.skipEncryption !== true) {
279
+ if (isEncryptionSkipped(opts)) {
280
+ if (opts.remotePeer == null) {
281
+ throw new InvalidMultiaddrError(`${direction} connection that skipped encryption must have a peer id`)
282
+ }
283
+
284
+ cryptoProtocol = 'native'
285
+ remotePeer = opts.remotePeer
286
+ } else {
287
+ const peerIdString = maConn.remoteAddr.getPeerId()
288
+ let remotePeerFromMultiaddr: PeerId | undefined
289
+
290
+ if (peerIdString != null) {
291
+ remotePeerFromMultiaddr = peerIdFromString(peerIdString)
292
+ }
293
+
304
294
  opts?.onProgress?.(new CustomProgressEvent(`upgrader:encrypt-${direction}-connection`));
305
295
 
306
296
  ({
307
- conn: encryptedConn,
297
+ connection: stream,
308
298
  remotePeer,
309
299
  protocol: cryptoProtocol,
310
300
  streamMuxer: muxerFactory
311
301
  } = await (direction === 'inbound'
312
- ? this._encryptInbound(protectedConn, opts)
313
- : this._encryptOutbound(protectedConn, opts)
302
+ ? this._encryptInbound(stream, {
303
+ ...opts,
304
+ remotePeer: remotePeerFromMultiaddr
305
+ })
306
+ : this._encryptOutbound(stream, {
307
+ ...opts,
308
+ remotePeer: remotePeerFromMultiaddr
309
+ })
314
310
  ))
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
311
  }
334
312
 
335
313
  // this can happen if we dial a multiaddr without a peer id, we only find
@@ -340,353 +318,98 @@ export class Upgrader implements UpgraderInterface {
340
318
  throw err
341
319
  }
342
320
 
343
- upgradedConn = encryptedConn
321
+ // stream.pause()
322
+ await this.shouldBlockConnection(direction === 'inbound' ? 'denyInboundEncryptedConnection' : 'denyOutboundEncryptedConnection', remotePeer, maConn)
323
+ // stream.resume()
324
+
344
325
  if (opts?.muxerFactory != null) {
345
326
  muxerFactory = opts.muxerFactory
346
327
  } else if (muxerFactory == null && this.streamMuxers.size > 0) {
347
328
  opts?.onProgress?.(new CustomProgressEvent(`upgrader:multiplex-${direction}-connection`))
348
329
 
349
330
  // Multiplex the connection
350
- const multiplexed = await (direction === 'inbound'
351
- ? this._multiplexInbound({
352
- ...protectedConn,
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
331
+ muxerFactory = await (direction === 'inbound'
332
+ ? this._multiplexInbound(stream, this.streamMuxers, opts)
333
+ : this._multiplexOutbound(stream, this.streamMuxers, opts))
361
334
  }
362
335
  } catch (err: any) {
363
- maConn.log.error('failed to upgrade inbound connection %s %a - %e', direction === 'inbound' ? 'from' : 'to', maConn.remoteAddr, err)
336
+ maConn.log.error('failed to upgrade %s connection %s %a - %e', direction, direction === 'inbound' ? 'from' : 'to', maConn.remoteAddr, err)
364
337
  throw err
365
338
  }
366
339
 
367
- await this.shouldBlockConnection(direction === 'inbound' ? 'denyInboundUpgradedConnection' : 'denyOutboundUpgradedConnection', remotePeer, maConn)
340
+ // create the connection muxer if one is configured
341
+ if (muxerFactory != null) {
342
+ maConn.log('create muxer %s', muxerFactory.protocol)
343
+ muxer = muxerFactory.createStreamMuxer(stream)
344
+ }
368
345
 
369
- maConn.log('successfully upgraded %s connection', direction)
346
+ // stream.pause()
347
+ await this.shouldBlockConnection(direction === 'inbound' ? 'denyInboundUpgradedConnection' : 'denyOutboundUpgradedConnection', remotePeer, maConn)
370
348
 
371
- return this._createConnection({
349
+ const conn = this._createConnection({
350
+ id,
372
351
  cryptoProtocol,
373
352
  direction,
374
353
  maConn,
375
- upgradedConn,
376
- muxerFactory,
354
+ stream,
355
+ muxer,
377
356
  remotePeer,
378
- limits: opts?.limits
357
+ limits: opts?.limits,
358
+ closeTimeout: this.connectionCloseTimeout
379
359
  })
360
+
361
+ conn.log('successfully upgraded connection')
362
+
363
+ // stream.resume()
364
+
365
+ return conn
380
366
  }
381
367
 
382
368
  /**
383
369
  * A convenience method for generating a new `Connection`
384
370
  */
385
371
  _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
372
  // Create the connection
612
- connection = createConnection({
613
- remoteAddr: maConn.remoteAddr,
614
- remotePeer,
615
- status: 'open',
616
- direction,
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)
373
+ const connection = createConnection(this.components, {
374
+ ...opts,
375
+ outboundStreamProtocolNegotiationTimeout: this.outboundStreamProtocolNegotiationTimeout,
376
+ inboundStreamProtocolNegotiationTimeout: this.inboundStreamProtocolNegotiationTimeout
377
+ })
635
378
 
636
- // ensure remaining streams are aborted
637
- muxer?.abort(err)
638
- }
379
+ connection.addEventListener('close', () => {
380
+ this.events.safeDispatchEvent('connection:close', {
381
+ detail: connection
382
+ })
639
383
  })
640
384
 
641
385
  this.events.safeDispatchEvent('connection:open', {
642
386
  detail: connection
643
387
  })
644
388
 
645
- // @ts-expect-error nah
646
- connection.__maConnTimeline = _timeline
647
-
648
389
  return connection
649
390
  }
650
391
 
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
392
  /**
666
393
  * Attempts to encrypt the incoming `connection` with the provided `cryptos`
667
394
  */
668
- async _encryptInbound (connection: MultiaddrConnection, options?: AbortOptions): Promise<CryptoResult> {
395
+ async _encryptInbound (connection: MessageStream, options?: SecureConnectionOptions): Promise<EncryptedConnection> {
669
396
  const protocols = Array.from(this.connectionEncrypters.keys())
670
397
 
671
398
  try {
672
- const { stream, protocol } = await mss.handle(connection, protocols, {
673
- ...options,
674
- log: connection.log
675
- })
399
+ const protocol = await mss.handle(connection, protocols, options)
676
400
  const encrypter = this.connectionEncrypters.get(protocol)
677
401
 
678
402
  if (encrypter == null) {
679
403
  throw new EncryptionFailedError(`no crypto module found for ${protocol}`)
680
404
  }
681
405
 
682
- connection.log('encrypting inbound connection to %a using %s', connection.remoteAddr, protocol)
406
+ connection.log('encrypting inbound connection using %s', protocol)
683
407
 
684
408
  return {
685
- ...await encrypter.secureInbound(stream, options),
409
+ ...await encrypter.secureInbound(connection, options),
686
410
  protocol
687
411
  }
688
412
  } catch (err: any) {
689
- connection.log.error('encrypting inbound connection from %a failed', connection.remoteAddr, err)
690
413
  throw new EncryptionFailedError(err.message)
691
414
  }
692
415
  }
@@ -695,31 +418,26 @@ export class Upgrader implements UpgraderInterface {
695
418
  * Attempts to encrypt the given `connection` with the provided connection encrypters.
696
419
  * The first `ConnectionEncrypter` module to succeed will be used
697
420
  */
698
- async _encryptOutbound (connection: MultiaddrConnection, options: SecureConnectionOptions): Promise<CryptoResult> {
421
+ async _encryptOutbound (connection: MessageStream, options?: SecureConnectionOptions): Promise<EncryptedConnection> {
699
422
  const protocols = Array.from(this.connectionEncrypters.keys())
700
423
 
701
424
  try {
702
425
  connection.log.trace('selecting encrypter from %s', protocols)
703
426
 
704
- const { stream, protocol } = await mss.select(connection, protocols, {
705
- ...options,
706
- log: connection.log,
707
- yieldBytes: true
708
- })
427
+ const protocol = await mss.select(connection, protocols, options)
709
428
  const encrypter = this.connectionEncrypters.get(protocol)
710
429
 
711
430
  if (encrypter == null) {
712
431
  throw new EncryptionFailedError(`no crypto module found for ${protocol}`)
713
432
  }
714
433
 
715
- connection.log('encrypting outbound connection to %a using %s', connection.remoteAddr, protocol)
434
+ connection.log('encrypting outbound connection using %s', protocol)
716
435
 
717
436
  return {
718
- ...await encrypter.secureOutbound(stream, options),
437
+ ...await encrypter.secureOutbound(connection, options),
719
438
  protocol
720
439
  }
721
440
  } catch (err: any) {
722
- connection.log.error('encrypting outbound connection to %a failed', connection.remoteAddr, err)
723
441
  throw new EncryptionFailedError(err.message)
724
442
  }
725
443
  }
@@ -728,27 +446,23 @@ export class Upgrader implements UpgraderInterface {
728
446
  * Selects one of the given muxers via multistream-select. That
729
447
  * muxer will be used for all future streams on the connection.
730
448
  */
731
- async _multiplexOutbound (connection: MultiaddrConnection, muxers: Map<string, StreamMuxerFactory>, options: AbortOptions): Promise<{ stream: MultiaddrConnection, muxerFactory?: StreamMuxerFactory }> {
449
+ async _multiplexOutbound (maConn: MessageStream, muxers: Map<string, StreamMuxerFactory>, options: AbortOptions): Promise<StreamMuxerFactory> {
732
450
  const protocols = Array.from(muxers.keys())
733
- connection.log('outbound selecting muxer %s', protocols)
734
- try {
735
- connection.log.trace('selecting stream muxer from %s', protocols)
451
+ maConn.log('outbound selecting muxer %s', protocols)
736
452
 
737
- const {
738
- stream,
739
- protocol
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)
453
+ try {
454
+ maConn.log.trace('selecting stream muxer from %s', protocols)
455
+ const protocol = await mss.select(maConn, protocols, options)
747
456
  const muxerFactory = muxers.get(protocol)
748
457
 
749
- return { stream, muxerFactory }
458
+ if (muxerFactory == null) {
459
+ throw new MuxerUnavailableError(`No muxer configured for protocol "${protocol}"`)
460
+ }
461
+
462
+ maConn.log('selected %s as muxer protocol', protocol)
463
+ return muxerFactory
750
464
  } catch (err: any) {
751
- connection.log.error('error multiplexing outbound connection', err)
465
+ maConn.log.error('error multiplexing outbound connection', err)
752
466
  throw new MuxerUnavailableError(String(err))
753
467
  }
754
468
  }
@@ -757,20 +471,23 @@ export class Upgrader implements UpgraderInterface {
757
471
  * Registers support for one of the given muxers via multistream-select. The
758
472
  * selected muxer will be used for all future streams on the connection.
759
473
  */
760
- async _multiplexInbound (connection: MultiaddrConnection, muxers: Map<string, StreamMuxerFactory>, options: AbortOptions): Promise<{ stream: MultiaddrConnection, muxerFactory?: StreamMuxerFactory }> {
474
+ async _multiplexInbound (maConn: MessageStream, muxers: Map<string, StreamMuxerFactory>, options: AbortOptions): Promise<StreamMuxerFactory> {
761
475
  const protocols = Array.from(muxers.keys())
762
- connection.log('inbound handling muxers %s', protocols)
476
+ maConn.log('inbound handling muxers %s', protocols)
763
477
  try {
764
- const { stream, protocol } = await mss.handle(connection, protocols, {
765
- ...options,
766
- log: connection.log
767
- })
478
+ maConn.log.trace('selecting stream muxer from %s', protocols)
479
+ const protocol = await mss.handle(maConn, protocols, options)
768
480
  const muxerFactory = muxers.get(protocol)
769
481
 
770
- return { stream, muxerFactory }
482
+ if (muxerFactory == null) {
483
+ throw new MuxerUnavailableError(`No muxer configured for protocol "${protocol}"`)
484
+ }
485
+
486
+ maConn.log('selected %s as muxer protocol', protocol)
487
+ return muxerFactory
771
488
  } catch (err: any) {
772
- connection.log.error('error multiplexing inbound connection', err)
773
- throw new MuxerUnavailableError(String(err))
489
+ maConn.log.error('error multiplexing inbound connection', err)
490
+ throw err
774
491
  }
775
492
  }
776
493
 
@@ -782,3 +499,7 @@ export class Upgrader implements UpgraderInterface {
782
499
  return this.streamMuxers
783
500
  }
784
501
  }
502
+
503
+ function isEncryptionSkipped (opts?: any): opts is UpgraderWithoutEncryptionOptions {
504
+ return opts.skipEncryption === true
505
+ }