@libp2p/mplex 11.0.47-6059227cb → 11.0.47-87bc8d4fb

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.
@@ -1,7 +1,8 @@
1
1
  import { Uint8ArrayList } from 'uint8arraylist';
2
2
  import type { Message } from './message-types.js';
3
+ import type { Source } from 'it-stream-types';
3
4
  /**
4
5
  * Encode and yield one or more messages
5
6
  */
6
- export declare function encode(message: Message): Uint8ArrayList;
7
+ export declare function encode(source: Source<Message>): AsyncGenerator<Uint8Array | Uint8ArrayList, void, undefined>;
7
8
  //# sourceMappingURL=encode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"encode.d.ts","sourceRoot":"","sources":["../../src/encode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAG/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAkDjD;;GAEG;AACH,wBAAgB,MAAM,CAAE,OAAO,EAAE,OAAO,GAAG,cAAc,CAKxD"}
1
+ {"version":3,"file":"encode.d.ts","sourceRoot":"","sources":["../../src/encode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAG/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAkD7C;;GAEG;AACH,wBAAwB,MAAM,CAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,cAAc,CAAC,UAAU,GAAG,cAAc,EAAE,IAAI,EAAE,SAAS,CAAC,CAMrH"}
@@ -44,9 +44,11 @@ const encoder = new Encoder();
44
44
  /**
45
45
  * Encode and yield one or more messages
46
46
  */
47
- export function encode(message) {
48
- const list = new Uint8ArrayList();
49
- encoder.write(message, list);
50
- return list;
47
+ export async function* encode(source) {
48
+ for await (const message of source) {
49
+ const list = new Uint8ArrayList();
50
+ encoder.write(message, list);
51
+ yield list;
52
+ }
51
53
  }
52
54
  //# sourceMappingURL=encode.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"encode.js","sourceRoot":"","sources":["../../src/encode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGjD,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,CAAA;AAE3B,MAAM,OAAO;IACH,KAAK,CAAY;IACjB,WAAW,CAAQ;IAE3B;QACE,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC,CAAA;QACnC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAA;IACtB,CAAC;IAED;;OAEG;IACH,KAAK,CAAE,GAAY,EAAE,IAAoB;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAA;QACvB,IAAI,MAAM,GAAG,IAAI,CAAC,WAAW,CAAA;QAE7B,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QACnD,MAAM,IAAI,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAA;QAEvD,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,UAAU,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,iBAAiB,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;YAC5J,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;YAC5C,MAAM,IAAI,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAClD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;YAC9B,MAAM,IAAI,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAA;QACpC,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QAEtD,IAAI,SAAS,GAAG,MAAM,GAAG,GAAG,EAAE,CAAC;YAC7B,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC,CAAA;YACnC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAA;QACtB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,WAAW,GAAG,MAAM,CAAA;QAC3B,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QAEnB,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,UAAU,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,iBAAiB,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;YAC5J,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACvB,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B;;GAEG;AACH,MAAM,UAAU,MAAM,CAAE,OAAgB;IACtC,MAAM,IAAI,GAAG,IAAI,cAAc,EAAE,CAAA;IACjC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IAE5B,OAAO,IAAI,CAAA;AACb,CAAC"}
1
+ {"version":3,"file":"encode.js","sourceRoot":"","sources":["../../src/encode.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * This is a [simple stream multiplexer(https://docs.libp2p.io/concepts/multiplex/mplex/) that has been deprecated.
5
5
  *
6
- * Please use [@libp2p/yamux](https://www.npmjs.com/package/@libp2p/yamux) instead.
6
+ * Please use [@chainsafe/libp2p-yamux](https://www.npmjs.com/package/@chainsafe/libp2p-yamux) instead.
7
7
  *
8
8
  * @example
9
9
  *
@@ -30,7 +30,9 @@
30
30
  * pipe([1, 2, 3], stream)
31
31
  * ```
32
32
  */
33
+ import type { MplexComponents } from './mplex.js';
33
34
  import type { StreamMuxerFactory } from '@libp2p/interface';
35
+ export type { MplexComponents };
34
36
  export interface MplexInit {
35
37
  /**
36
38
  * The maximum size of message that can be sent in one go in bytes.
@@ -38,18 +40,42 @@ export interface MplexInit {
38
40
  * messages. If we receive a message larger than this an error will
39
41
  * be thrown and the connection closed.
40
42
  *
41
- * @default 1_048_576
43
+ * @default 1048576
42
44
  */
43
- maxMessageSize?: number;
45
+ maxMsgSize?: number;
44
46
  /**
45
47
  * Constrains the size of the unprocessed message queue buffer.
46
48
  * Before messages are deserialized, the raw bytes are buffered to ensure
47
49
  * we have the complete message to deserialized. If the queue gets longer
48
50
  * than this value an error will be thrown and the connection closed.
49
51
  *
50
- * @default 4_194_304
52
+ * @default 4194304
51
53
  */
52
54
  maxUnprocessedMessageQueueSize?: number;
55
+ /**
56
+ * The maximum number of multiplexed streams that can be open at any
57
+ * one time. A request to open more than this will have a stream
58
+ * reset message sent immediately as a response for the newly opened
59
+ * stream id
60
+ *
61
+ * @default 1024
62
+ */
63
+ maxInboundStreams?: number;
64
+ /**
65
+ * The maximum number of multiplexed streams that can be open at any
66
+ * one time. An attempt to open more than this will throw
67
+ *
68
+ * @default 1024
69
+ */
70
+ maxOutboundStreams?: number;
71
+ /**
72
+ * Incoming stream messages are buffered until processed by the stream
73
+ * handler. If the buffer reaches this size in bytes the stream will
74
+ * be reset
75
+ *
76
+ * @default 4194304
77
+ */
78
+ maxStreamBufferSize?: number;
53
79
  /**
54
80
  * When `maxInboundStreams` is hit, if the remote continues try to open
55
81
  * more than this many new multiplexed streams per second the connection
@@ -62,5 +88,5 @@ export interface MplexInit {
62
88
  /**
63
89
  * @deprecated mplex is deprecated as it has no flow control. Please use yamux instead.
64
90
  */
65
- export declare function mplex(init?: MplexInit): () => StreamMuxerFactory;
91
+ export declare function mplex(init?: MplexInit): (components: MplexComponents) => StreamMuxerFactory;
66
92
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAIH,OAAO,KAAK,EAAoC,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAE7F,MAAM,WAAW,SAAS;IACxB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB;;;;;;;OAOG;IACH,8BAA8B,CAAC,EAAE,MAAM,CAAA;IAEvC;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAuBD;;GAEG;AACH,wBAAgB,KAAK,CAAE,IAAI,GAAE,SAAc,GAAG,MAAM,kBAAkB,CAErE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAe,kBAAkB,EAAmB,MAAM,mBAAmB,CAAA;AAEzF,YAAY,EAAE,eAAe,EAAE,CAAA;AAE/B,MAAM,WAAW,SAAS;IACxB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;;;;;OAOG;IACH,8BAA8B,CAAC,EAAE,MAAM,CAAA;IAEvC;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAE1B;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAE3B;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAE5B;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AA0BD;;GAEG;AACH,wBAAgB,KAAK,CAAE,IAAI,GAAE,SAAc,GAAG,CAAC,UAAU,EAAE,eAAe,KAAK,kBAAkB,CAEhG"}
package/dist/src/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * This is a [simple stream multiplexer(https://docs.libp2p.io/concepts/multiplex/mplex/) that has been deprecated.
5
5
  *
6
- * Please use [@libp2p/yamux](https://www.npmjs.com/package/@libp2p/yamux) instead.
6
+ * Please use [@chainsafe/libp2p-yamux](https://www.npmjs.com/package/@chainsafe/libp2p-yamux) instead.
7
7
  *
8
8
  * @example
9
9
  *
@@ -35,15 +35,18 @@ import { MplexStreamMuxer } from './mplex.js';
35
35
  class Mplex {
36
36
  protocol = '/mplex/6.7.0';
37
37
  _init;
38
- constructor(init = {}) {
38
+ components;
39
+ constructor(components, init = {}) {
40
+ this.components = components;
39
41
  this._init = init;
40
42
  }
41
43
  [Symbol.toStringTag] = '@libp2p/mplex';
42
44
  [serviceCapabilities] = [
43
45
  '@libp2p/stream-multiplexing'
44
46
  ];
45
- createStreamMuxer(maConn) {
46
- return new MplexStreamMuxer(maConn, {
47
+ createStreamMuxer(init) {
48
+ return new MplexStreamMuxer(this.components, {
49
+ ...init,
47
50
  ...this._init
48
51
  });
49
52
  }
@@ -52,6 +55,6 @@ class Mplex {
52
55
  * @deprecated mplex is deprecated as it has no flow control. Please use yamux instead.
53
56
  */
54
57
  export function mplex(init = {}) {
55
- return () => new Mplex(init);
58
+ return (components) => new Mplex(components, init);
56
59
  }
57
60
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAkC7C,MAAM,KAAK;IACF,QAAQ,GAAG,cAAc,CAAA;IACf,KAAK,CAAW;IAEjC,YAAa,OAAkB,EAAE;QAC/B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IACnB,CAAC;IAEQ,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,eAAe,CAAA;IAEtC,CAAC,mBAAmB,CAAC,GAAa;QACzC,6BAA6B;KAC9B,CAAA;IAED,iBAAiB,CAAE,MAA2B;QAC5C,OAAO,IAAI,gBAAgB,CAAC,MAAM,EAAE;YAClC,GAAG,IAAI,CAAC,KAAK;SACd,CAAC,CAAA;IACJ,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAE,OAAkB,EAAE;IACzC,OAAO,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAA;AAC9B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAgE7C,MAAM,KAAK;IACF,QAAQ,GAAG,cAAc,CAAA;IACf,KAAK,CAAW;IAChB,UAAU,CAAiB;IAE5C,YAAa,UAA2B,EAAE,OAAkB,EAAE;QAC5D,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IACnB,CAAC;IAEQ,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,eAAe,CAAA;IAEtC,CAAC,mBAAmB,CAAC,GAAa;QACzC,6BAA6B;KAC9B,CAAA;IAED,iBAAiB,CAAE,IAAqB;QACtC,OAAO,IAAI,gBAAgB,CAAC,IAAI,CAAC,UAAU,EAAE;YAC3C,GAAG,IAAI;YACP,GAAG,IAAI,CAAC,KAAK;SACd,CAAC,CAAA;IACJ,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAE,OAAkB,EAAE;IACzC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;AACpD,CAAC"}
@@ -1,23 +1,65 @@
1
- import { AbstractStreamMuxer } from '@libp2p/utils';
2
1
  import type { MplexInit } from './index.js';
3
2
  import type { Message } from './message-types.js';
4
3
  import type { MplexStream } from './stream.js';
5
- import type { CreateStreamOptions, MultiaddrConnection, MessageStreamDirection } from '@libp2p/interface';
4
+ import type { AbortOptions, ComponentLogger, Stream, StreamMuxer, StreamMuxerInit } from '@libp2p/interface';
5
+ import type { Sink, Source } from 'it-stream-types';
6
6
  import type { Uint8ArrayList } from 'uint8arraylist';
7
- export declare class MplexStreamMuxer extends AbstractStreamMuxer<MplexStream> {
7
+ export interface MplexComponents {
8
+ logger: ComponentLogger;
9
+ }
10
+ interface MplexStreamMuxerInit extends MplexInit, StreamMuxerInit {
11
+ /**
12
+ * The default timeout to use in ms when shutting down the muxer.
13
+ */
14
+ closeTimeout?: number;
15
+ }
16
+ export declare class MplexStreamMuxer implements StreamMuxer {
17
+ protocol: string;
18
+ sink: Sink<Source<Uint8ArrayList | Uint8Array>, Promise<void>>;
19
+ source: AsyncGenerator<Uint8ArrayList | Uint8Array>;
20
+ private readonly log;
8
21
  private _streamId;
22
+ private readonly _streams;
23
+ private readonly _init;
24
+ private readonly _source;
25
+ private readonly closeController;
9
26
  private readonly rateLimiter;
10
- private readonly maxMessageSize;
11
- private readonly maxUnprocessedMessageQueueSize;
12
- private readonly decoder;
13
- constructor(maConn: MultiaddrConnection, init: MplexInit);
14
- onData(data: Uint8Array | Uint8ArrayList): void;
27
+ private readonly closeTimeout;
28
+ private readonly logger;
29
+ constructor(components: MplexComponents, init?: MplexStreamMuxerInit);
30
+ /**
31
+ * Returns a Map of streams and their ids
32
+ */
33
+ get streams(): Stream[];
15
34
  /**
16
35
  * Initiate a new stream with the given name. If no name is
17
36
  * provided, the id of the stream will be used.
18
37
  */
19
- onCreateStream(options: CreateStreamOptions): MplexStream;
20
- _newStream(id: number, direction: MessageStreamDirection, options?: CreateStreamOptions): MplexStream;
21
- handleMessage(message: Message): void;
38
+ newStream(name?: string): Stream;
39
+ /**
40
+ * Close or abort all tracked streams and stop the muxer
41
+ */
42
+ close(options?: AbortOptions): Promise<void>;
43
+ abort(err: Error): void;
44
+ /**
45
+ * Called whenever an inbound stream is created
46
+ */
47
+ _newReceiverStream(options: {
48
+ id: number;
49
+ name: string;
50
+ }): MplexStream;
51
+ _newStream(options: {
52
+ id: number;
53
+ name: string;
54
+ type: 'initiator' | 'receiver';
55
+ registry: Map<number, MplexStream>;
56
+ }): MplexStream;
57
+ /**
58
+ * Creates a sink with an abortable source. Incoming messages will
59
+ * also have their size restricted. All messages will be varint decoded.
60
+ */
61
+ _createSink(): Sink<Source<Uint8ArrayList | Uint8Array>, Promise<void>>;
62
+ _handleIncoming(message: Message): Promise<void>;
22
63
  }
64
+ export {};
23
65
  //# sourceMappingURL=mplex.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mplex.d.ts","sourceRoot":"","sources":["../../src/mplex.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAKhE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AACzG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAqBpD,qBAAa,gBAAiB,SAAQ,mBAAmB,CAAC,WAAW,CAAC;IACpE,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,8BAA8B,CAAQ;IACvD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAEpB,MAAM,EAAE,mBAAmB,EAAE,IAAI,EAAE,SAAS;IAkBzD,MAAM,CAAE,IAAI,EAAE,UAAU,GAAG,cAAc,GAAG,IAAI;IAMhD;;;OAGG;IACH,cAAc,CAAE,OAAO,EAAE,mBAAmB,GAAG,WAAW;IAU1D,UAAU,CAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,sBAAsB,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,WAAW;IAetG,aAAa,CAAE,OAAO,EAAE,OAAO,GAAG,IAAI;CAqEvC"}
1
+ {"version":3,"file":"mplex.d.ts","sourceRoot":"","sources":["../../src/mplex.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAU,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAEpH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAyBpD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,eAAe,CAAA;CACxB;AAED,UAAU,oBAAqB,SAAQ,SAAS,EAAE,eAAe;IAC/D;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,qBAAa,gBAAiB,YAAW,WAAW;IAC3C,QAAQ,SAAiB;IAEzB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,UAAU,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IAC9D,MAAM,EAAE,cAAc,CAAC,cAAc,GAAG,UAAU,CAAC,CAAA;IAE1D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA+E;IACxG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsB;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;gBAE3B,UAAU,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,oBAAoB;IAyDrE;;OAEG;IACH,IAAI,OAAO,IAAK,MAAM,EAAE,CAWvB;IAED;;;OAGG;IACH,SAAS,CAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAUjC;;OAEG;IACG,KAAK,CAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BnD,KAAK,CAAE,GAAG,EAAE,KAAK,GAAG,IAAI;IASxB;;OAEG;IACH,kBAAkB,CAAE,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,WAAW;IAMvE,UAAU,CAAE,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC;QAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;KAAE,GAAG,WAAW;IAmCnI;;;OAGG;IACH,WAAW,IAAK,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,UAAU,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IA6BlE,eAAe,CAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAsGxD"}
package/dist/src/mplex.js CHANGED
@@ -1,101 +1,257 @@
1
- import { MuxerClosedError } from '@libp2p/interface';
2
- import { RateLimiter, AbstractStreamMuxer } from '@libp2p/utils';
1
+ import { TooManyOutboundProtocolStreamsError, MuxerClosedError } from '@libp2p/interface';
2
+ import { closeSource } from '@libp2p/utils/close-source';
3
+ import { RateLimiter } from '@libp2p/utils/rate-limiter';
4
+ import { pipe } from 'it-pipe';
5
+ import { pushable } from 'it-pushable';
3
6
  import { toString as uint8ArrayToString } from 'uint8arrays';
4
- import { Decoder, MAX_MSG_QUEUE_SIZE, MAX_MSG_SIZE } from './decode.js';
7
+ import { Decoder } from './decode.js';
8
+ import { encode } from './encode.js';
9
+ import { StreamInputBufferError } from './errors.js';
5
10
  import { MessageTypes, MessageTypeNames } from './message-types.js';
6
11
  import { createStream } from './stream.js';
12
+ const MAX_STREAMS_INBOUND_STREAMS_PER_CONNECTION = 1024;
13
+ const MAX_STREAMS_OUTBOUND_STREAMS_PER_CONNECTION = 1024;
14
+ const MAX_STREAM_BUFFER_SIZE = 1024 * 1024 * 4; // 4MB
7
15
  const DISCONNECT_THRESHOLD = 5;
16
+ const CLOSE_TIMEOUT = 500;
8
17
  function printMessage(msg) {
9
18
  const output = {
10
19
  ...msg,
11
20
  type: `${MessageTypeNames[msg.type]} (${msg.type})`
12
21
  };
13
22
  if (msg.type === MessageTypes.NEW_STREAM) {
14
- output.data = uint8ArrayToString(msg.data.subarray());
23
+ output.data = uint8ArrayToString(msg.data instanceof Uint8Array ? msg.data : msg.data.subarray());
15
24
  }
16
25
  if (msg.type === MessageTypes.MESSAGE_INITIATOR || msg.type === MessageTypes.MESSAGE_RECEIVER) {
17
- output.data = uint8ArrayToString(msg.data.subarray(), 'base16');
26
+ output.data = uint8ArrayToString(msg.data instanceof Uint8Array ? msg.data : msg.data.subarray(), 'base16');
18
27
  }
19
28
  return output;
20
29
  }
21
- export class MplexStreamMuxer extends AbstractStreamMuxer {
30
+ export class MplexStreamMuxer {
31
+ protocol = '/mplex/6.7.0';
32
+ sink;
33
+ source;
34
+ log;
22
35
  _streamId;
36
+ _streams;
37
+ _init;
38
+ _source;
39
+ closeController;
23
40
  rateLimiter;
24
- maxMessageSize;
25
- maxUnprocessedMessageQueueSize;
26
- decoder;
27
- constructor(maConn, init) {
28
- super(maConn, {
29
- ...init,
30
- protocol: '/mplex/6.7.0',
31
- name: 'mplex'
32
- });
41
+ closeTimeout;
42
+ logger;
43
+ constructor(components, init) {
44
+ init = init ?? {};
45
+ this.log = init.log?.newScope('mplex') ?? components.logger.forComponent('libp2p:mplex');
46
+ this.logger = components.logger;
33
47
  this._streamId = 0;
34
- this.maxMessageSize = init.maxMessageSize ?? MAX_MSG_SIZE;
35
- this.maxUnprocessedMessageQueueSize = init.maxUnprocessedMessageQueueSize ?? MAX_MSG_QUEUE_SIZE;
36
- this.decoder = new Decoder(this.maxMessageSize, this.maxUnprocessedMessageQueueSize);
48
+ this._streams = {
49
+ /**
50
+ * Stream to ids map
51
+ */
52
+ initiators: new Map(),
53
+ /**
54
+ * Stream to ids map
55
+ */
56
+ receivers: new Map()
57
+ };
58
+ this._init = init;
59
+ this.closeTimeout = init.closeTimeout ?? CLOSE_TIMEOUT;
60
+ /**
61
+ * An iterable sink
62
+ */
63
+ this.sink = this._createSink();
64
+ /**
65
+ * An iterable source
66
+ */
67
+ this._source = pushable({
68
+ objectMode: true,
69
+ onEnd: () => {
70
+ // the source has ended, we can't write any more messages to gracefully
71
+ // close streams so all we can do is destroy them
72
+ for (const stream of this._streams.initiators.values()) {
73
+ stream.destroy();
74
+ }
75
+ for (const stream of this._streams.receivers.values()) {
76
+ stream.destroy();
77
+ }
78
+ }
79
+ });
80
+ this.source = pipe(this._source, source => encode(source));
81
+ /**
82
+ * Close controller
83
+ */
84
+ this.closeController = new AbortController();
37
85
  this.rateLimiter = new RateLimiter({
38
86
  points: init.disconnectThreshold ?? DISCONNECT_THRESHOLD,
39
87
  duration: 1
40
88
  });
41
89
  }
42
- onData(data) {
43
- for (const msg of this.decoder.write(data)) {
44
- this.handleMessage(msg);
90
+ /**
91
+ * Returns a Map of streams and their ids
92
+ */
93
+ get streams() {
94
+ // Inbound and Outbound streams may have the same ids, so we need to make those unique
95
+ const streams = [];
96
+ for (const stream of this._streams.initiators.values()) {
97
+ streams.push(stream);
45
98
  }
99
+ for (const stream of this._streams.receivers.values()) {
100
+ streams.push(stream);
101
+ }
102
+ return streams;
46
103
  }
47
104
  /**
48
105
  * Initiate a new stream with the given name. If no name is
49
106
  * provided, the id of the stream will be used.
50
107
  */
51
- onCreateStream(options) {
52
- if (this.status !== 'open') {
108
+ newStream(name) {
109
+ if (this.closeController.signal.aborted) {
53
110
  throw new MuxerClosedError('Muxer already closed');
54
111
  }
55
112
  const id = this._streamId++;
56
- return this._newStream(id, 'outbound', options);
113
+ name = name == null ? id.toString() : name.toString();
114
+ const registry = this._streams.initiators;
115
+ return this._newStream({ id, name, type: 'initiator', registry });
57
116
  }
58
- _newStream(id, direction, options) {
59
- this.log('new %s stream %s', direction, id);
60
- const stream = createStream({
61
- ...options,
62
- id,
63
- direction,
64
- maxMsgSize: this.maxMessageSize,
65
- log: this.log,
66
- muxer: this
67
- });
117
+ /**
118
+ * Close or abort all tracked streams and stop the muxer
119
+ */
120
+ async close(options) {
121
+ if (this.closeController.signal.aborted) {
122
+ return;
123
+ }
124
+ const signal = options?.signal ?? AbortSignal.timeout(this.closeTimeout);
125
+ try {
126
+ // try to gracefully close all streams
127
+ await Promise.all(this.streams.map(async (s) => s.close({
128
+ signal
129
+ })));
130
+ this._source.end();
131
+ // try to gracefully close the muxer
132
+ await this._source.onEmpty({
133
+ signal
134
+ });
135
+ this.closeController.abort();
136
+ }
137
+ catch (err) {
138
+ this.abort(err);
139
+ }
140
+ }
141
+ abort(err) {
142
+ if (this.closeController.signal.aborted) {
143
+ return;
144
+ }
145
+ this.streams.forEach(s => { s.abort(err); });
146
+ this.closeController.abort(err);
147
+ }
148
+ /**
149
+ * Called whenever an inbound stream is created
150
+ */
151
+ _newReceiverStream(options) {
152
+ const { id, name } = options;
153
+ const registry = this._streams.receivers;
154
+ return this._newStream({ id, name, type: 'receiver', registry });
155
+ }
156
+ _newStream(options) {
157
+ const { id, name, type, registry } = options;
158
+ this.log('new %s stream %s', type, id);
159
+ if (type === 'initiator' && this._streams.initiators.size === (this._init.maxOutboundStreams ?? MAX_STREAMS_OUTBOUND_STREAMS_PER_CONNECTION)) {
160
+ throw new TooManyOutboundProtocolStreamsError('Too many outbound streams open');
161
+ }
162
+ if (registry.has(id)) {
163
+ throw new Error(`${type} stream ${id} already exists!`);
164
+ }
165
+ const send = async (msg) => {
166
+ if (this.log.enabled) {
167
+ this.log.trace('%s stream %s send', type, id, printMessage(msg));
168
+ }
169
+ this._source.push(msg);
170
+ };
171
+ const onEnd = () => {
172
+ this.log('%s stream with id %s and protocol %s ended', type, id, stream.protocol);
173
+ registry.delete(id);
174
+ if (this._init.onStreamEnd != null) {
175
+ this._init.onStreamEnd(stream);
176
+ }
177
+ };
178
+ const stream = createStream({ id, name, send, type, onEnd, maxMsgSize: this._init.maxMsgSize, log: this.log });
179
+ registry.set(id, stream);
68
180
  return stream;
69
181
  }
70
- handleMessage(message) {
182
+ /**
183
+ * Creates a sink with an abortable source. Incoming messages will
184
+ * also have their size restricted. All messages will be varint decoded.
185
+ */
186
+ _createSink() {
187
+ const sink = async (source) => {
188
+ const abortListener = () => {
189
+ closeSource(source, this.log);
190
+ };
191
+ this.closeController.signal.addEventListener('abort', abortListener);
192
+ try {
193
+ const decoder = new Decoder(this._init.maxMsgSize, this._init.maxUnprocessedMessageQueueSize);
194
+ for await (const chunk of source) {
195
+ for (const msg of decoder.write(chunk)) {
196
+ await this._handleIncoming(msg);
197
+ }
198
+ }
199
+ this._source.end();
200
+ }
201
+ catch (err) {
202
+ this.log('error in sink', err);
203
+ this._source.end(err); // End the source with an error
204
+ }
205
+ finally {
206
+ this.closeController.signal.removeEventListener('abort', abortListener);
207
+ }
208
+ };
209
+ return sink;
210
+ }
211
+ async _handleIncoming(message) {
212
+ const { id, type } = message;
71
213
  if (this.log.enabled) {
72
214
  this.log.trace('incoming message', printMessage(message));
73
215
  }
74
216
  // Create a new stream?
75
217
  if (message.type === MessageTypes.NEW_STREAM) {
76
- // close the connection if the remote opens too many streams too quickly
77
- try {
78
- this.rateLimiter.consume('new-stream', 1);
79
- }
80
- catch {
81
- this.log('rate limit hit when opening too many new streams over the inbound stream limit - closing remote connection');
82
- // since there's no backpressure in mplex, the only thing we can really do to protect ourselves is close the connection
83
- this.abort(new Error('Too many open streams'));
218
+ if (this._streams.receivers.size === (this._init.maxInboundStreams ?? MAX_STREAMS_INBOUND_STREAMS_PER_CONNECTION)) {
219
+ this.log('too many inbound streams open');
220
+ // not going to allow this stream, send the reset message manually
221
+ // instead of setting it up just to tear it down
222
+ this._source.push({
223
+ id,
224
+ type: MessageTypes.RESET_RECEIVER
225
+ });
226
+ // if we've hit our stream limit, and the remote keeps trying to open
227
+ // more new streams, if they are doing this very quickly maybe they
228
+ // are attacking us and we should close the connection
229
+ try {
230
+ await this.rateLimiter.consume('new-stream', 1);
231
+ }
232
+ catch {
233
+ this.log('rate limit hit when opening too many new streams over the inbound stream limit - closing remote connection');
234
+ // since there's no backpressure in mplex, the only thing we can really do to protect ourselves is close the connection
235
+ this.abort(new Error('Too many open streams'));
236
+ return;
237
+ }
84
238
  return;
85
239
  }
86
- const stream = this._newStream(message.id, 'inbound', this.streamOptions);
87
- this.onRemoteStream(stream);
240
+ const stream = this._newReceiverStream({ id, name: uint8ArrayToString(message.data instanceof Uint8Array ? message.data : message.data.subarray()) });
241
+ if (this._init.onIncomingStream != null) {
242
+ this._init.onIncomingStream(stream);
243
+ }
88
244
  return;
89
245
  }
90
- const id = `${(message.type & 1) === 1 ? 'i' : 'r'}${message.id}`;
91
- const stream = this.streams.find(s => s.id === id);
246
+ const list = (type & 1) === 1 ? this._streams.initiators : this._streams.receivers;
247
+ const stream = list.get(id);
92
248
  if (stream == null) {
93
- this.log('missing stream %s for message type %s', id, MessageTypeNames[message.type]);
249
+ this.log('missing stream %s for message type %s', id, MessageTypeNames[type]);
94
250
  // if the remote keeps sending us messages for streams that have been
95
251
  // closed or were never opened they may be attacking us so if they do
96
252
  // this very quickly all we can do is close the connection
97
253
  try {
98
- this.rateLimiter.consume('missing-stream', 1);
254
+ await this.rateLimiter.consume('missing-stream', 1);
99
255
  }
100
256
  catch {
101
257
  this.log('rate limit hit when receiving messages for streams that do not exist - closing remote connection');
@@ -105,29 +261,39 @@ export class MplexStreamMuxer extends AbstractStreamMuxer {
105
261
  }
106
262
  return;
107
263
  }
264
+ const maxBufferSize = this._init.maxStreamBufferSize ?? MAX_STREAM_BUFFER_SIZE;
108
265
  try {
109
- switch (message.type) {
266
+ switch (type) {
110
267
  case MessageTypes.MESSAGE_INITIATOR:
111
268
  case MessageTypes.MESSAGE_RECEIVER:
269
+ if (stream.sourceReadableLength() > maxBufferSize) {
270
+ // Stream buffer has got too large, reset the stream
271
+ this._source.push({
272
+ id: message.id,
273
+ type: type === MessageTypes.MESSAGE_INITIATOR ? MessageTypes.RESET_RECEIVER : MessageTypes.RESET_INITIATOR
274
+ });
275
+ // Inform the stream consumer they are not fast enough
276
+ throw new StreamInputBufferError('Input buffer full - increase Mplex maxBufferSize to accommodate slow consumers');
277
+ }
112
278
  // We got data from the remote, push it into our local stream
113
- stream.onData(message.data);
279
+ stream.sourcePush(message.data);
114
280
  break;
115
281
  case MessageTypes.CLOSE_INITIATOR:
116
282
  case MessageTypes.CLOSE_RECEIVER:
117
- // The remote has stopped writing
118
- stream.onRemoteCloseWrite();
283
+ // The remote has stopped writing, so we can stop reading
284
+ stream.remoteCloseWrite();
119
285
  break;
120
286
  case MessageTypes.RESET_INITIATOR:
121
287
  case MessageTypes.RESET_RECEIVER:
122
288
  // The remote has errored, stop reading and writing to the stream immediately
123
- stream.onRemoteReset();
289
+ stream.reset();
124
290
  break;
125
291
  default:
126
- this.log('unknown message type');
292
+ this.log('unknown message type %s', type);
127
293
  }
128
294
  }
129
295
  catch (err) {
130
- this.log.error('error while processing message - %e', err);
296
+ this.log.error('error while processing message', err);
131
297
  stream.abort(err);
132
298
  }
133
299
  }