libp2p 0.37.0 → 0.37.2

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 (64) hide show
  1. package/dist/src/config.d.ts.map +1 -1
  2. package/dist/src/config.js +13 -4
  3. package/dist/src/config.js.map +1 -1
  4. package/dist/src/connection-manager/dialer/dial-request.d.ts.map +1 -1
  5. package/dist/src/connection-manager/dialer/dial-request.js +28 -4
  6. package/dist/src/connection-manager/dialer/dial-request.js.map +1 -1
  7. package/dist/src/connection-manager/dialer/index.d.ts.map +1 -1
  8. package/dist/src/connection-manager/dialer/index.js +0 -1
  9. package/dist/src/connection-manager/dialer/index.js.map +1 -1
  10. package/dist/src/connection-manager/index.d.ts.map +1 -1
  11. package/dist/src/connection-manager/index.js +8 -2
  12. package/dist/src/connection-manager/index.js.map +1 -1
  13. package/dist/src/errors.d.ts +2 -1
  14. package/dist/src/errors.d.ts.map +1 -1
  15. package/dist/src/errors.js +1 -0
  16. package/dist/src/errors.js.map +1 -1
  17. package/dist/src/fetch/constants.d.ts +2 -1
  18. package/dist/src/fetch/constants.d.ts.map +1 -1
  19. package/dist/src/fetch/constants.js +2 -1
  20. package/dist/src/fetch/constants.js.map +1 -1
  21. package/dist/src/fetch/index.d.ts +5 -4
  22. package/dist/src/fetch/index.d.ts.map +1 -1
  23. package/dist/src/fetch/index.js +12 -6
  24. package/dist/src/fetch/index.js.map +1 -1
  25. package/dist/src/identify/index.d.ts +18 -1
  26. package/dist/src/identify/index.d.ts.map +1 -1
  27. package/dist/src/identify/index.js +75 -19
  28. package/dist/src/identify/index.js.map +1 -1
  29. package/dist/src/index.d.ts +8 -5
  30. package/dist/src/index.d.ts.map +1 -1
  31. package/dist/src/index.js.map +1 -1
  32. package/dist/src/libp2p.d.ts +2 -2
  33. package/dist/src/libp2p.d.ts.map +1 -1
  34. package/dist/src/libp2p.js +9 -12
  35. package/dist/src/libp2p.js.map +1 -1
  36. package/dist/src/nat-manager.d.ts +5 -2
  37. package/dist/src/nat-manager.d.ts.map +1 -1
  38. package/dist/src/nat-manager.js +6 -3
  39. package/dist/src/nat-manager.js.map +1 -1
  40. package/dist/src/peer-routing.d.ts.map +1 -1
  41. package/dist/src/peer-routing.js +0 -1
  42. package/dist/src/peer-routing.js.map +1 -1
  43. package/dist/src/ping/index.d.ts +3 -2
  44. package/dist/src/ping/index.d.ts.map +1 -1
  45. package/dist/src/ping/index.js +19 -8
  46. package/dist/src/ping/index.js.map +1 -1
  47. package/dist/src/upgrader.d.ts.map +1 -1
  48. package/dist/src/upgrader.js +9 -4
  49. package/dist/src/upgrader.js.map +1 -1
  50. package/package.json +8 -12
  51. package/src/config.ts +13 -4
  52. package/src/connection-manager/dialer/dial-request.ts +30 -5
  53. package/src/connection-manager/dialer/index.ts +0 -1
  54. package/src/connection-manager/index.ts +8 -3
  55. package/src/errors.ts +2 -1
  56. package/src/fetch/constants.ts +2 -1
  57. package/src/fetch/index.ts +19 -9
  58. package/src/identify/index.ts +112 -28
  59. package/src/index.ts +8 -5
  60. package/src/libp2p.ts +9 -12
  61. package/src/nat-manager.ts +7 -3
  62. package/src/peer-routing.ts +0 -1
  63. package/src/ping/index.ts +27 -13
  64. package/src/upgrader.ts +13 -5
@@ -2,8 +2,6 @@ import { logger } from '@libp2p/logger'
2
2
  import errCode from 'err-code'
3
3
  import * as lp from 'it-length-prefixed'
4
4
  import { pipe } from 'it-pipe'
5
- import all from 'it-all'
6
- import take from 'it-take'
7
5
  import drain from 'it-drain'
8
6
  import first from 'it-first'
9
7
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
@@ -21,20 +19,47 @@ import {
21
19
  } from './consts.js'
22
20
  import { codes } from '../errors.js'
23
21
  import type { IncomingStreamData } from '@libp2p/interfaces/registrar'
24
- import type { Connection } from '@libp2p/interfaces/connection'
22
+ import type { Connection, Stream } from '@libp2p/interfaces/connection'
25
23
  import type { Startable } from '@libp2p/interfaces/startable'
26
24
  import { peerIdFromKeys } from '@libp2p/peer-id'
27
25
  import type { Components } from '@libp2p/interfaces/components'
26
+ import { TimeoutController } from 'timeout-abort-controller'
27
+ import type { AbortOptions } from '@libp2p/interfaces'
28
+ import { abortableDuplex } from 'abortable-iterator'
29
+ import type { Duplex } from 'it-stream-types'
28
30
 
29
31
  const log = logger('libp2p:identify')
30
32
 
33
+ // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L48
34
+ const IDENTIFY_TIMEOUT = 60000
35
+
36
+ // https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L52
37
+ const MAX_IDENTIFY_MESSAGE_SIZE = 1024 * 8
38
+
31
39
  export interface HostProperties {
32
40
  agentVersion: string
33
41
  }
34
42
 
35
43
  export interface IdentifyServiceInit {
44
+ /**
45
+ * The prefix to use for the protocol (default: 'ipfs')
46
+ */
36
47
  protocolPrefix: string
48
+
49
+ /**
50
+ * What details we should send as part of an identify message
51
+ */
37
52
  host: HostProperties
53
+
54
+ /**
55
+ * How long we should wait for a remote peer to send their identify response
56
+ */
57
+ timeout?: number
58
+
59
+ /**
60
+ * Identify responses larger than this in bytes will be rejected (default: 8192)
61
+ */
62
+ maxIdentifyMessageSize?: number
38
63
  }
39
64
 
40
65
  export class IdentifyService implements Startable {
@@ -46,11 +71,13 @@ export class IdentifyService implements Startable {
46
71
  agentVersion: string
47
72
  }
48
73
 
74
+ private readonly init: IdentifyServiceInit
49
75
  private started: boolean
50
76
 
51
77
  constructor (components: Components, init: IdentifyServiceInit) {
52
78
  this.components = components
53
79
  this.started = false
80
+ this.init = init
54
81
 
55
82
  this.handleMessage = this.handleMessage.bind(this)
56
83
 
@@ -128,8 +155,17 @@ export class IdentifyService implements Startable {
128
155
  const protocols = await this.components.getPeerStore().protoBook.get(this.components.getPeerId())
129
156
 
130
157
  const pushes = connections.map(async connection => {
158
+ const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
159
+ let stream: Stream | undefined
160
+
131
161
  try {
132
- const { stream } = await connection.newStream([this.identifyPushProtocolStr])
162
+ const data = await connection.newStream([this.identifyPushProtocolStr], {
163
+ signal: timeoutController.signal
164
+ })
165
+ stream = data.stream
166
+
167
+ // make stream abortable
168
+ const source: Duplex<Uint8Array> = abortableDuplex(stream, timeoutController.signal)
133
169
 
134
170
  await pipe(
135
171
  [Identify.encode({
@@ -138,12 +174,18 @@ export class IdentifyService implements Startable {
138
174
  protocols
139
175
  })],
140
176
  lp.encode(),
141
- stream,
177
+ source,
142
178
  drain
143
179
  )
144
180
  } catch (err: any) {
145
181
  // Just log errors
146
182
  log.error('could not push identify update to peer', err)
183
+ } finally {
184
+ if (stream != null) {
185
+ stream.close()
186
+ }
187
+
188
+ timeoutController.clear()
147
189
  }
148
190
  })
149
191
 
@@ -175,31 +217,56 @@ export class IdentifyService implements Startable {
175
217
  await this.push(connections)
176
218
  }
177
219
 
220
+ async _identify (connection: Connection, options: AbortOptions = {}): Promise<Identify> {
221
+ const { stream } = await connection.newStream([this.identifyProtocolStr], options)
222
+ let source: Duplex<Uint8Array> = stream
223
+ let timeoutController
224
+ let signal = options.signal
225
+
226
+ // create a timeout if no abort signal passed
227
+ if (signal == null) {
228
+ timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
229
+ signal = timeoutController.signal
230
+ }
231
+
232
+ // make stream abortable if AbortSignal passed
233
+ source = abortableDuplex(stream, signal)
234
+
235
+ try {
236
+ const data = await pipe(
237
+ [],
238
+ source,
239
+ lp.decode({
240
+ maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
241
+ }),
242
+ async (source) => await first(source)
243
+ )
244
+
245
+ if (data == null) {
246
+ throw errCode(new Error('No data could be retrieved'), codes.ERR_CONNECTION_ENDED)
247
+ }
248
+
249
+ try {
250
+ return Identify.decode(data)
251
+ } catch (err: any) {
252
+ throw errCode(err, codes.ERR_INVALID_MESSAGE)
253
+ }
254
+ } finally {
255
+ if (timeoutController != null) {
256
+ timeoutController.clear()
257
+ }
258
+
259
+ stream.close()
260
+ }
261
+ }
262
+
178
263
  /**
179
264
  * Requests the `Identify` message from peer associated with the given `connection`.
180
265
  * If the identified peer does not match the `PeerId` associated with the connection,
181
266
  * an error will be thrown.
182
267
  */
183
- async identify (connection: Connection): Promise<void> {
184
- const { stream } = await connection.newStream([this.identifyProtocolStr])
185
- const [data] = await pipe(
186
- [],
187
- stream,
188
- lp.decode(),
189
- (source) => take(source, 1),
190
- async (source) => await all(source)
191
- )
192
-
193
- if (data == null) {
194
- throw errCode(new Error('No data could be retrieved'), codes.ERR_CONNECTION_ENDED)
195
- }
196
-
197
- let message: Identify
198
- try {
199
- message = Identify.decode(data)
200
- } catch (err: any) {
201
- throw errCode(err, codes.ERR_INVALID_MESSAGE)
202
- }
268
+ async identify (connection: Connection, options: AbortOptions = {}): Promise<void> {
269
+ const message = await this._identify(connection, options)
203
270
 
204
271
  const {
205
272
  publicKey,
@@ -308,6 +375,8 @@ export class IdentifyService implements Startable {
308
375
  */
309
376
  async _handleIdentify (data: IncomingStreamData) {
310
377
  const { connection, stream } = data
378
+ const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
379
+
311
380
  try {
312
381
  const publicKey = this.components.getPeerId().publicKey ?? new Uint8Array(0)
313
382
  const peerData = await this.components.getPeerStore().get(this.components.getPeerId())
@@ -335,14 +404,20 @@ export class IdentifyService implements Startable {
335
404
  protocols: peerData.protocols
336
405
  })
337
406
 
407
+ // make stream abortable
408
+ const source: Duplex<Uint8Array> = abortableDuplex(stream, timeoutController.signal)
409
+
338
410
  await pipe(
339
411
  [message],
340
412
  lp.encode(),
341
- stream,
413
+ source,
342
414
  drain
343
415
  )
344
416
  } catch (err: any) {
345
417
  log.error('could not respond to identify request', err)
418
+ } finally {
419
+ stream.close()
420
+ timeoutController.clear()
346
421
  }
347
422
  }
348
423
 
@@ -351,13 +426,19 @@ export class IdentifyService implements Startable {
351
426
  */
352
427
  async _handlePush (data: IncomingStreamData) {
353
428
  const { connection, stream } = data
429
+ const timeoutController = new TimeoutController(this.init.timeout ?? IDENTIFY_TIMEOUT)
354
430
 
355
431
  let message: Identify | undefined
356
432
  try {
433
+ // make stream abortable
434
+ const source: Duplex<Uint8Array> = abortableDuplex(stream, timeoutController.signal)
435
+
357
436
  const data = await pipe(
358
437
  [],
359
- stream,
360
- lp.decode(),
438
+ source,
439
+ lp.decode({
440
+ maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
441
+ }),
361
442
  async (source) => await first(source)
362
443
  )
363
444
 
@@ -366,6 +447,9 @@ export class IdentifyService implements Startable {
366
447
  }
367
448
  } catch (err: any) {
368
449
  return log.error('received invalid message', err)
450
+ } finally {
451
+ stream.close()
452
+ timeoutController.clear()
369
453
  }
370
454
 
371
455
  if (message == null) {
package/src/index.ts CHANGED
@@ -4,7 +4,7 @@ import type { EventEmitter } from '@libp2p/interfaces/events'
4
4
  import type { Startable } from '@libp2p/interfaces/startable'
5
5
  import type { Multiaddr } from '@multiformats/multiaddr'
6
6
  import type { FaultTolerance } from './transport-manager.js'
7
- import type { HostProperties } from './identify/index.js'
7
+ import type { IdentifyServiceInit } from './identify/index.js'
8
8
  import type { DualDHT } from '@libp2p/interfaces/dht'
9
9
  import type { Datastore } from 'interface-datastore'
10
10
  import type { PeerStore, PeerStoreInit } from '@libp2p/interfaces/peer-store'
@@ -24,6 +24,8 @@ import type { Metrics, MetricsInit } from '@libp2p/interfaces/metrics'
24
24
  import type { PeerInfo } from '@libp2p/interfaces/peer-info'
25
25
  import type { KeyChain } from './keychain/index.js'
26
26
  import type { ConnectionManagerInit } from './connection-manager/index.js'
27
+ import type { PingServiceInit } from './ping/index.js'
28
+ import type { FetchServiceInit } from './fetch/index.js'
27
29
 
28
30
  export interface PersistentPeerStoreOptions {
29
31
  threshold?: number
@@ -95,7 +97,6 @@ export interface RefreshManagerConfig {
95
97
 
96
98
  export interface Libp2pInit {
97
99
  peerId: PeerId
98
- host: HostProperties
99
100
  addresses: AddressesConfig
100
101
  connectionManager: ConnectionManagerInit
101
102
  connectionGater: Partial<ConnectionGater>
@@ -105,9 +106,11 @@ export interface Libp2pInit {
105
106
  peerStore: PeerStoreInit
106
107
  peerRouting: PeerRoutingConfig
107
108
  keychain: KeychainConfig
108
- protocolPrefix: string
109
109
  nat: NatManagerConfig
110
110
  relay: RelayConfig
111
+ identify: IdentifyServiceInit
112
+ ping: PingServiceInit
113
+ fetch: FetchServiceInit
111
114
 
112
115
  transports: Transport[]
113
116
  streamMuxers?: StreamMuxerFactory[]
@@ -195,12 +198,12 @@ export interface Libp2p extends Startable, EventEmitter<Libp2pEvents> {
195
198
  /**
196
199
  * Pings the given peer in order to obtain the operation latency
197
200
  */
198
- ping: (peer: Multiaddr |PeerId) => Promise<number>
201
+ ping: (peer: Multiaddr | PeerId, options?: AbortOptions) => Promise<number>
199
202
 
200
203
  /**
201
204
  * Sends a request to fetch the value associated with the given key from the given peer.
202
205
  */
203
- fetch: (peer: PeerId | Multiaddr | string, key: string) => Promise<Uint8Array | null>
206
+ fetch: (peer: PeerId | Multiaddr | string, key: string, options?: AbortOptions) => Promise<Uint8Array | null>
204
207
 
205
208
  /**
206
209
  * Returns the public key for the passed PeerId. If the PeerId is of the 'RSA' type
package/src/libp2p.ts CHANGED
@@ -166,10 +166,7 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
166
166
  if (init.streamMuxers != null && init.streamMuxers.length > 0) {
167
167
  // Add the identify service since we can multiplex
168
168
  this.identifyService = new IdentifyService(this.components, {
169
- protocolPrefix: init.protocolPrefix,
170
- host: {
171
- agentVersion: init.host.agentVersion
172
- }
169
+ ...init.identify
173
170
  })
174
171
  this.configureComponent(this.identifyService)
175
172
  }
@@ -229,11 +226,11 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
229
226
  }
230
227
 
231
228
  this.fetchService = this.configureComponent(new FetchService(this.components, {
232
- protocolPrefix: init.protocolPrefix
229
+ ...init.fetch
233
230
  }))
234
231
 
235
232
  this.pingService = this.configureComponent(new PingService(this.components, {
236
- protocolPrefix: init.protocolPrefix
233
+ ...init.ping
237
234
  }))
238
235
 
239
236
  const autoDialer = this.configureComponent(new AutoDialer(this.components, {
@@ -419,9 +416,9 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
419
416
  throw errCode(new Error('no protocols were provided to open a stream'), codes.ERR_INVALID_PROTOCOLS_FOR_STREAM)
420
417
  }
421
418
 
422
- const connection = await this.dial(peer)
419
+ const connection = await this.dial(peer, options)
423
420
 
424
- return await connection.newStream(protocols)
421
+ return await connection.newStream(protocols, options)
425
422
  }
426
423
 
427
424
  getMultiaddrs (): Multiaddr[] {
@@ -473,24 +470,24 @@ export class Libp2pNode extends EventEmitter<Libp2pEvents> implements Libp2p {
473
470
  throw errCode(new Error(`Node not responding with its public key: ${peer.toString()}`), codes.ERR_INVALID_RECORD)
474
471
  }
475
472
 
476
- async fetch (peer: PeerId | Multiaddr | string, key: string): Promise<Uint8Array | null> {
473
+ async fetch (peer: PeerId | Multiaddr | string, key: string, options: AbortOptions = {}): Promise<Uint8Array | null> {
477
474
  const { id, multiaddrs } = getPeer(peer)
478
475
 
479
476
  if (multiaddrs != null) {
480
477
  await this.components.getPeerStore().addressBook.add(id, multiaddrs)
481
478
  }
482
479
 
483
- return await this.fetchService.fetch(id, key)
480
+ return await this.fetchService.fetch(id, key, options)
484
481
  }
485
482
 
486
- async ping (peer: PeerId | Multiaddr | string): Promise<number> {
483
+ async ping (peer: PeerId | Multiaddr | string, options: AbortOptions = {}): Promise<number> {
487
484
  const { id, multiaddrs } = getPeer(peer)
488
485
 
489
486
  if (multiaddrs.length > 0) {
490
487
  await this.components.getPeerStore().addressBook.add(id, multiaddrs)
491
488
  }
492
489
 
493
- return await this.pingService.ping(id)
490
+ return await this.pingService.ping(id, options)
494
491
  }
495
492
 
496
493
  async handle (protocols: string | string[], handler: StreamHandler): Promise<void> {
@@ -94,10 +94,14 @@ export class NatManager implements Startable {
94
94
  return this.started
95
95
  }
96
96
 
97
+ start () {}
98
+
97
99
  /**
98
- * Starts the NAT manager
100
+ * Attempt to use uPnP to configure port mapping using the current gateway.
101
+ *
102
+ * Run after start to ensure the transport manager has all addresses configured.
99
103
  */
100
- start () {
104
+ afterStart () {
101
105
  if (isBrowser || !this.enabled || this.started) {
102
106
  return
103
107
  }
@@ -105,7 +109,7 @@ export class NatManager implements Startable {
105
109
  this.started = true
106
110
 
107
111
  // done async to not slow down startup
108
- this._start().catch((err) => {
112
+ void this._start().catch((err) => {
109
113
  // hole punching errors are non-fatal
110
114
  log.error(err)
111
115
  })
@@ -17,7 +17,6 @@ import {
17
17
  clearDelayedInterval
18
18
  // @ts-expect-error module with no types
19
19
  } from 'set-delayed-interval'
20
- // @ts-expect-error setMaxListeners is missing from the node 16 types
21
20
  import { setMaxListeners } from 'events'
22
21
  import type { PeerId } from '@libp2p/interfaces/peer-id'
23
22
  import type { PeerRouting } from '@libp2p/interfaces/peer-routing'
package/src/ping/index.ts CHANGED
@@ -10,6 +10,9 @@ import type { IncomingStreamData } from '@libp2p/interfaces/registrar'
10
10
  import type { PeerId } from '@libp2p/interfaces/peer-id'
11
11
  import type { Startable } from '@libp2p/interfaces/startable'
12
12
  import type { Components } from '@libp2p/interfaces/components'
13
+ import type { AbortOptions } from '@libp2p/interfaces'
14
+ import type { Duplex } from 'it-stream-types'
15
+ import { abortableDuplex } from 'abortable-iterator'
13
16
 
14
17
  const log = logger('libp2p:ping')
15
18
 
@@ -18,8 +21,8 @@ export interface PingServiceInit {
18
21
  }
19
22
 
20
23
  export class PingService implements Startable {
24
+ public readonly protocol: string
21
25
  private readonly components: Components
22
- private readonly protocol: string
23
26
  private started: boolean
24
27
 
25
28
  constructor (components: Components, init: PingServiceInit) {
@@ -60,25 +63,36 @@ export class PingService implements Startable {
60
63
  * @param {PeerId|Multiaddr} peer
61
64
  * @returns {Promise<number>}
62
65
  */
63
- async ping (peer: PeerId): Promise<number> {
66
+ async ping (peer: PeerId, options: AbortOptions = {}): Promise<number> {
64
67
  log('dialing %s to %p', this.protocol, peer)
65
68
 
66
- const connection = await this.components.getConnectionManager().openConnection(peer)
67
- const { stream } = await connection.newStream([this.protocol])
69
+ const connection = await this.components.getConnectionManager().openConnection(peer, options)
70
+ const { stream } = await connection.newStream([this.protocol], options)
68
71
  const start = Date.now()
69
72
  const data = randomBytes(PING_LENGTH)
70
73
 
71
- const result = await pipe(
72
- [data],
73
- stream,
74
- async (source) => await first(source)
75
- )
76
- const end = Date.now()
74
+ let source: Duplex<Uint8Array> = stream
77
75
 
78
- if (result == null || !uint8ArrayEquals(data, result)) {
79
- throw errCode(new Error('Received wrong ping ack'), codes.ERR_WRONG_PING_ACK)
76
+ // make stream abortable if AbortSignal passed
77
+ if (options.signal != null) {
78
+ source = abortableDuplex(stream, options.signal)
80
79
  }
81
80
 
82
- return end - start
81
+ try {
82
+ const result = await pipe(
83
+ [data],
84
+ source,
85
+ async (source) => await first(source)
86
+ )
87
+ const end = Date.now()
88
+
89
+ if (result == null || !uint8ArrayEquals(data, result)) {
90
+ throw errCode(new Error('Received wrong ping ack'), codes.ERR_WRONG_PING_ACK)
91
+ }
92
+
93
+ return end - start
94
+ } finally {
95
+ stream.close()
96
+ }
83
97
  }
84
98
  }
package/src/upgrader.ts CHANGED
@@ -15,6 +15,7 @@ import type { PeerId } from '@libp2p/interfaces/peer-id'
15
15
  import type { MultiaddrConnection, Upgrader, UpgraderEvents } from '@libp2p/interfaces/transport'
16
16
  import type { Duplex } from 'it-stream-types'
17
17
  import type { Components } from '@libp2p/interfaces/components'
18
+ import type { AbortOptions } from '@libp2p/interfaces'
18
19
 
19
20
  const log = logger('libp2p:upgrader')
20
21
 
@@ -266,7 +267,7 @@ export class DefaultUpgrader extends EventEmitter<UpgraderEvents> implements Upg
266
267
  } = opts
267
268
 
268
269
  let muxer: StreamMuxer | undefined
269
- let newStream: ((multicodecs: string[]) => Promise<ProtocolStream>) | undefined
270
+ let newStream: ((multicodecs: string[], options?: AbortOptions) => Promise<ProtocolStream>) | undefined
270
271
  let connection: Connection // eslint-disable-line prefer-const
271
272
 
272
273
  if (muxerFactory != null) {
@@ -308,7 +309,7 @@ export class DefaultUpgrader extends EventEmitter<UpgraderEvents> implements Upg
308
309
  }
309
310
  })
310
311
 
311
- newStream = async (protocols: string[]): Promise<ProtocolStream> => {
312
+ newStream = async (protocols: string[], options: AbortOptions = {}): Promise<ProtocolStream> => {
312
313
  if (muxer == null) {
313
314
  throw errCode(new Error('Stream is not multiplexed'), codes.ERR_MUXER_UNAVAILABLE)
314
315
  }
@@ -319,7 +320,7 @@ export class DefaultUpgrader extends EventEmitter<UpgraderEvents> implements Upg
319
320
  const metrics = this.components.getMetrics()
320
321
 
321
322
  try {
322
- let { stream, protocol } = await mss.select(protocols)
323
+ let { stream, protocol } = await mss.select(protocols, options)
323
324
 
324
325
  if (metrics != null) {
325
326
  stream = metrics.trackStream({ stream, remotePeer, protocol })
@@ -328,6 +329,11 @@ export class DefaultUpgrader extends EventEmitter<UpgraderEvents> implements Upg
328
329
  return { stream: { ...muxedStream, ...stream }, protocol }
329
330
  } catch (err: any) {
330
331
  log.error('could not create new stream', err)
332
+
333
+ if (err.code != null) {
334
+ throw err
335
+ }
336
+
331
337
  throw errCode(err, codes.ERR_UNSUPPORTED_PROTOCOL)
332
338
  }
333
339
  }
@@ -382,9 +388,11 @@ export class DefaultUpgrader extends EventEmitter<UpgraderEvents> implements Upg
382
388
  getStreams: () => muxer != null ? muxer.streams : errConnectionNotMultiplexed(),
383
389
  close: async () => {
384
390
  await maConn.close()
385
- // Ensure remaining streams are aborted
391
+ // Ensure remaining streams are closed
386
392
  if (muxer != null) {
387
- muxer.streams.map(stream => stream.abort())
393
+ await Promise.all(muxer.streams.map(async stream => {
394
+ await stream.close()
395
+ }))
388
396
  }
389
397
  }
390
398
  })