@libp2p/mplex 9.0.12 → 10.0.0-551622a96

Sign up to get free protection for your applications and to get access to all the features.
package/src/mplex.ts CHANGED
@@ -1,23 +1,20 @@
1
- import { CodeError } from '@libp2p/interface/errors'
2
- import { logger } from '@libp2p/logger'
3
- import { abortableSource } from 'abortable-iterator'
1
+ /* eslint-disable complexity */
2
+
3
+ import { CodeError } from '@libp2p/interface'
4
+ import { closeSource } from '@libp2p/utils/close-source'
4
5
  import { pipe } from 'it-pipe'
5
- import { type PushableV, pushableV } from 'it-pushable'
6
+ import { type Pushable, pushable } from 'it-pushable'
6
7
  import { RateLimiterMemory } from 'rate-limiter-flexible'
7
8
  import { toString as uint8ArrayToString } from 'uint8arrays'
8
9
  import { Decoder } from './decode.js'
9
10
  import { encode } from './encode.js'
10
11
  import { MessageTypes, MessageTypeNames, type Message } from './message-types.js'
11
12
  import { createStream, type MplexStream } from './stream.js'
12
- import type { MplexInit } from './index.js'
13
- import type { AbortOptions } from '@libp2p/interface'
14
- import type { Stream } from '@libp2p/interface/connection'
15
- import type { StreamMuxer, StreamMuxerInit } from '@libp2p/interface/stream-muxer'
13
+ import type { MplexComponents, MplexInit } from './index.js'
14
+ import type { AbortOptions, ComponentLogger, Logger, Stream, StreamMuxer, StreamMuxerInit } from '@libp2p/interface'
16
15
  import type { Sink, Source } from 'it-stream-types'
17
16
  import type { Uint8ArrayList } from 'uint8arraylist'
18
17
 
19
- const log = logger('libp2p:mplex')
20
-
21
18
  const MAX_STREAMS_INBOUND_STREAMS_PER_CONNECTION = 1024
22
19
  const MAX_STREAMS_OUTBOUND_STREAMS_PER_CONNECTION = 1024
23
20
  const MAX_STREAM_BUFFER_SIZE = 1024 * 1024 * 4 // 4MB
@@ -52,19 +49,23 @@ export class MplexStreamMuxer implements StreamMuxer {
52
49
  public protocol = '/mplex/6.7.0'
53
50
 
54
51
  public sink: Sink<Source<Uint8ArrayList | Uint8Array>, Promise<void>>
55
- public source: AsyncGenerator<Uint8Array>
52
+ public source: AsyncGenerator<Uint8ArrayList | Uint8Array>
56
53
 
54
+ private readonly log: Logger
57
55
  private _streamId: number
58
56
  private readonly _streams: { initiators: Map<number, MplexStream>, receivers: Map<number, MplexStream> }
59
57
  private readonly _init: MplexStreamMuxerInit
60
- private readonly _source: PushableV<Message>
58
+ private readonly _source: Pushable<Message>
61
59
  private readonly closeController: AbortController
62
60
  private readonly rateLimiter: RateLimiterMemory
63
61
  private readonly closeTimeout: number
62
+ private readonly logger: ComponentLogger
64
63
 
65
- constructor (init?: MplexStreamMuxerInit) {
64
+ constructor (components: MplexComponents, init?: MplexStreamMuxerInit) {
66
65
  init = init ?? {}
67
66
 
67
+ this.log = components.logger.forComponent('libp2p:mplex')
68
+ this.logger = components.logger
68
69
  this._streamId = 0
69
70
  this._streams = {
70
71
  /**
@@ -87,7 +88,7 @@ export class MplexStreamMuxer implements StreamMuxer {
87
88
  /**
88
89
  * An iterable source
89
90
  */
90
- this._source = pushableV<Message>({
91
+ this._source = pushable<Message>({
91
92
  objectMode: true,
92
93
  onEnd: (): void => {
93
94
  // the source has ended, we can't write any more messages to gracefully
@@ -103,7 +104,7 @@ export class MplexStreamMuxer implements StreamMuxer {
103
104
  })
104
105
  this.source = pipe(
105
106
  this._source,
106
- source => encode(source, this._init.minSendBytes)
107
+ source => encode(source)
107
108
  )
108
109
 
109
110
  /**
@@ -199,7 +200,7 @@ export class MplexStreamMuxer implements StreamMuxer {
199
200
  _newStream (options: { id: number, name: string, type: 'initiator' | 'receiver', registry: Map<number, MplexStream> }): MplexStream {
200
201
  const { id, name, type, registry } = options
201
202
 
202
- log('new %s stream %s', type, id)
203
+ this.log('new %s stream %s', type, id)
203
204
 
204
205
  if (type === 'initiator' && this._streams.initiators.size === (this._init.maxOutboundStreams ?? MAX_STREAMS_OUTBOUND_STREAMS_PER_CONNECTION)) {
205
206
  throw new CodeError('Too many outbound streams open', 'ERR_TOO_MANY_OUTBOUND_STREAMS')
@@ -210,15 +211,15 @@ export class MplexStreamMuxer implements StreamMuxer {
210
211
  }
211
212
 
212
213
  const send = async (msg: Message): Promise<void> => {
213
- if (log.enabled) {
214
- log.trace('%s stream %s send', type, id, printMessage(msg))
214
+ if (this.log.enabled) {
215
+ this.log.trace('%s stream %s send', type, id, printMessage(msg))
215
216
  }
216
217
 
217
218
  this._source.push(msg)
218
219
  }
219
220
 
220
221
  const onEnd = (): void => {
221
- log('%s stream with id %s and protocol %s ended', type, id, stream.protocol)
222
+ this.log('%s stream with id %s and protocol %s ended', type, id, stream.protocol)
222
223
  registry.delete(id)
223
224
 
224
225
  if (this._init.onStreamEnd != null) {
@@ -226,7 +227,7 @@ export class MplexStreamMuxer implements StreamMuxer {
226
227
  }
227
228
  }
228
229
 
229
- const stream = createStream({ id, name, send, type, onEnd, maxMsgSize: this._init.maxMsgSize })
230
+ const stream = createStream({ id, name, send, type, onEnd, maxMsgSize: this._init.maxMsgSize, logger: this.logger })
230
231
  registry.set(id, stream)
231
232
  return stream
232
233
  }
@@ -237,11 +238,13 @@ export class MplexStreamMuxer implements StreamMuxer {
237
238
  */
238
239
  _createSink (): Sink<Source<Uint8ArrayList | Uint8Array>, Promise<void>> {
239
240
  const sink: Sink<Source<Uint8ArrayList | Uint8Array>, Promise<void>> = async source => {
240
- try {
241
- source = abortableSource(source, this.closeController.signal, {
242
- returnOnAbort: true
243
- })
241
+ const abortListener = (): void => {
242
+ closeSource(source, this.log)
243
+ }
244
+
245
+ this.closeController.signal.addEventListener('abort', abortListener)
244
246
 
247
+ try {
245
248
  const decoder = new Decoder(this._init.maxMsgSize, this._init.maxUnprocessedMessageQueueSize)
246
249
 
247
250
  for await (const chunk of source) {
@@ -252,8 +255,10 @@ export class MplexStreamMuxer implements StreamMuxer {
252
255
 
253
256
  this._source.end()
254
257
  } catch (err: any) {
255
- log('error in sink', err)
258
+ this.log('error in sink', err)
256
259
  this._source.end(err) // End the source with an error
260
+ } finally {
261
+ this.closeController.signal.removeEventListener('abort', abortListener)
257
262
  }
258
263
  }
259
264
 
@@ -263,14 +268,14 @@ export class MplexStreamMuxer implements StreamMuxer {
263
268
  async _handleIncoming (message: Message): Promise<void> {
264
269
  const { id, type } = message
265
270
 
266
- if (log.enabled) {
267
- log.trace('incoming message', printMessage(message))
271
+ if (this.log.enabled) {
272
+ this.log.trace('incoming message', printMessage(message))
268
273
  }
269
274
 
270
275
  // Create a new stream?
271
276
  if (message.type === MessageTypes.NEW_STREAM) {
272
277
  if (this._streams.receivers.size === (this._init.maxInboundStreams ?? MAX_STREAMS_INBOUND_STREAMS_PER_CONNECTION)) {
273
- log('too many inbound streams open')
278
+ this.log('too many inbound streams open')
274
279
 
275
280
  // not going to allow this stream, send the reset message manually
276
281
  // instead of setting it up just to tear it down
@@ -285,7 +290,7 @@ export class MplexStreamMuxer implements StreamMuxer {
285
290
  try {
286
291
  await this.rateLimiter.consume('new-stream', 1)
287
292
  } catch {
288
- log('rate limit hit when opening too many new streams over the inbound stream limit - closing remote connection')
293
+ this.log('rate limit hit when opening too many new streams over the inbound stream limit - closing remote connection')
289
294
  // since there's no backpressure in mplex, the only thing we can really do to protect ourselves is close the connection
290
295
  this.abort(new Error('Too many open streams'))
291
296
  return
@@ -307,7 +312,7 @@ export class MplexStreamMuxer implements StreamMuxer {
307
312
  const stream = list.get(id)
308
313
 
309
314
  if (stream == null) {
310
- log('missing stream %s for message type %s', id, MessageTypeNames[type])
315
+ this.log('missing stream %s for message type %s', id, MessageTypeNames[type])
311
316
 
312
317
  // if the remote keeps sending us messages for streams that have been
313
318
  // closed or were never opened they may be attacking us so if they do
@@ -315,7 +320,7 @@ export class MplexStreamMuxer implements StreamMuxer {
315
320
  try {
316
321
  await this.rateLimiter.consume('missing-stream', 1)
317
322
  } catch {
318
- log('rate limit hit when receiving messages for streams that do not exist - closing remote connection')
323
+ this.log('rate limit hit when receiving messages for streams that do not exist - closing remote connection')
319
324
  // since there's no backpressure in mplex, the only thing we can really do to protect ourselves is close the connection
320
325
  this.abort(new Error('Too many messages for missing streams'))
321
326
  return
@@ -355,10 +360,10 @@ export class MplexStreamMuxer implements StreamMuxer {
355
360
  stream.reset()
356
361
  break
357
362
  default:
358
- log('unknown message type %s', type)
363
+ this.log('unknown message type %s', type)
359
364
  }
360
365
  } catch (err: any) {
361
- log.error('error while processing message', err)
366
+ this.log.error('error while processing message', err)
362
367
  stream.abort(err)
363
368
  }
364
369
  }
package/src/stream.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { AbstractStream, type AbstractStreamInit } from '@libp2p/interface/stream-muxer/stream'
2
- import { logger } from '@libp2p/logger'
1
+ import { AbstractStream, type AbstractStreamInit } from '@libp2p/utils/abstract-stream'
3
2
  import { Uint8ArrayList } from 'uint8arraylist'
4
3
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
5
4
  import { MAX_MSG_SIZE } from './decode.js'
6
5
  import { InitiatorMessageTypes, ReceiverMessageTypes } from './message-types.js'
7
6
  import type { Message } from './message-types.js'
7
+ import type { ComponentLogger } from '@libp2p/interface'
8
8
 
9
9
  export interface Options {
10
10
  id: number
@@ -13,6 +13,7 @@ export interface Options {
13
13
  onEnd?(err?: Error): void
14
14
  type?: 'initiator' | 'receiver'
15
15
  maxMsgSize?: number
16
+ logger: ComponentLogger
16
17
  }
17
18
 
18
19
  interface MplexStreamInit extends AbstractStreamInit {
@@ -87,6 +88,6 @@ export function createStream (options: Options): MplexStream {
87
88
  maxDataSize: maxMsgSize,
88
89
  onEnd,
89
90
  send,
90
- log: logger(`libp2p:mplex:stream:${type}:${id}`)
91
+ log: options.logger.forComponent(`libp2p:mplex:stream:${type}:${id}`)
91
92
  })
92
93
  }
@@ -1,6 +0,0 @@
1
- {
2
- "MplexInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_mplex.MplexInit.html",
3
- ".:MplexInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_mplex.MplexInit.html",
4
- "mplex": "https://libp2p.github.io/js-libp2p/functions/_libp2p_mplex.mplex.html",
5
- ".:mplex": "https://libp2p.github.io/js-libp2p/functions/_libp2p_mplex.mplex.html"
6
- }