@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/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 +3 -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 +8 -5
- package/dist/src/mplex.d.ts.map +1 -1
- package/dist/src/mplex.js +31 -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 +8 -18
- package/src/mplex.ts +39 -32
- package/src/stream.ts +4 -3
- package/dist/typedoc-urls.json +0 -6
package/src/mplex.ts
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
import { CodeError } from '@libp2p/interface
|
2
|
-
import {
|
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
|
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:
|
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 =
|
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
|
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
|
-
|
241
|
-
|
242
|
-
|
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/
|
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
|
}
|
package/dist/typedoc-urls.json
DELETED
@@ -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
|
-
}
|