@libp2p/mplex 9.0.12 → 10.0.0-06e6d235f

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