@libp2p/mplex 9.0.12-effcfaa8e → 10.0.0-551622a96
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/README.md +6 -4
- package/dist/index.min.js +5 -5
- package/dist/src/decode.js.map +1 -1
- package/dist/src/encode.d.ts +2 -1
- package/dist/src/encode.d.ts.map +1 -1
- package/dist/src/encode.js +5 -21
- package/dist/src/encode.js.map +1 -1
- package/dist/src/index.d.ts +5 -13
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/mplex.d.ts +6 -6
- package/dist/src/mplex.d.ts.map +1 -1
- package/dist/src/mplex.js +32 -25
- package/dist/src/mplex.js.map +1 -1
- package/dist/src/stream.d.ts +3 -1
- package/dist/src/stream.d.ts.map +1 -1
- package/dist/src/stream.js +2 -3
- package/dist/src/stream.js.map +1 -1
- package/package.json +14 -11
- package/src/encode.ts +5 -25
- package/src/index.ts +11 -17
- package/src/mplex.ts +38 -33
- package/src/stream.ts +4 -3
package/src/mplex.ts
CHANGED
@@ -1,23 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
import {
|
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
|
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:
|
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 =
|
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
|
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
|
-
|
241
|
-
|
242
|
-
|
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/
|
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
|
}
|