@libp2p/mplex 1.0.5 → 1.1.2
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 +13 -2
- package/dist/src/index.d.ts +14 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/mplex.d.ts +4 -3
- package/dist/src/mplex.d.ts.map +1 -1
- package/dist/src/mplex.js +25 -3
- package/dist/src/mplex.js.map +1 -1
- package/dist/src/stream.d.ts.map +1 -1
- package/dist/src/stream.js +37 -3
- package/dist/src/stream.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +22 -3
- package/src/mplex.ts +31 -8
- package/src/stream.ts +55 -5
package/README.md
CHANGED
@@ -27,7 +27,9 @@ npm install @libp2p/mplex
|
|
27
27
|
import { Mplex } from '@libp2p/mplex'
|
28
28
|
import { pipe } from 'it-pipe'
|
29
29
|
|
30
|
-
const
|
30
|
+
const factory = new Mplex()
|
31
|
+
|
32
|
+
const muxer = factory.createStreamMuxer(components, {
|
31
33
|
onStream: stream => { // Receive a duplex stream from the remote
|
32
34
|
// ...receive data from the remote and optionally send data back
|
33
35
|
},
|
@@ -46,7 +48,16 @@ pipe([1, 2, 3], stream)
|
|
46
48
|
|
47
49
|
## API
|
48
50
|
|
49
|
-
### `const
|
51
|
+
### `const factory = new Mplex([options])`
|
52
|
+
|
53
|
+
Creates a factory that can be used to create new muxers.
|
54
|
+
|
55
|
+
`options` is an optional `Object` that may have the following properties:
|
56
|
+
|
57
|
+
* `maxMsgSize` - a number that defines how large mplex data messages can be in bytes, if messages are larger than this they will be sent as multiple messages (default: 1048576 - e.g. 1MB)
|
58
|
+
* `maxStreamsPerConnection` - a number that defines how many streams are allowed per connection (default: 1024)
|
59
|
+
|
60
|
+
### `const muxer = factory.createStreamMuxer(components, [options])`
|
50
61
|
|
51
62
|
Create a new _duplex_ stream that can be piped together with a connection in order to allow multiplexed communications.
|
52
63
|
|
package/dist/src/index.d.ts
CHANGED
@@ -1,11 +1,23 @@
|
|
1
1
|
import type { Components } from '@libp2p/interfaces/components';
|
2
2
|
import type { StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer';
|
3
3
|
import { MplexStreamMuxer } from './mplex.js';
|
4
|
-
export interface MplexInit
|
4
|
+
export interface MplexInit {
|
5
|
+
/**
|
6
|
+
* The maximum size of message that can be sent in one go in bytes.
|
7
|
+
* Messages larger than this will be split into multiple smaller
|
8
|
+
* messages.
|
9
|
+
*/
|
5
10
|
maxMsgSize?: number;
|
11
|
+
/**
|
12
|
+
* The maximum number of multiplexed streams that can be open at any
|
13
|
+
* one time. An attempt to open more than this will throw.
|
14
|
+
*/
|
15
|
+
maxStreamsPerConnection?: number;
|
6
16
|
}
|
7
17
|
export declare class Mplex implements StreamMuxerFactory {
|
8
18
|
protocol: string;
|
9
|
-
|
19
|
+
private readonly init;
|
20
|
+
constructor(init?: MplexInit);
|
21
|
+
createStreamMuxer(components: Components, init?: StreamMuxerInit): MplexStreamMuxer;
|
10
22
|
}
|
11
23
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE7C,MAAM,WAAW,
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE7C,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAA;CACjC;AAED,qBAAa,KAAM,YAAW,kBAAkB;IACvC,QAAQ,SAAiB;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAW;gBAEnB,IAAI,GAAE,SAAc;IAIjC,iBAAiB,CAAE,UAAU,EAAE,UAAU,EAAE,IAAI,GAAE,eAAoB;CAMtE"}
|
package/dist/src/index.js
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
import { MplexStreamMuxer } from './mplex.js';
|
2
2
|
export class Mplex {
|
3
|
-
constructor() {
|
3
|
+
constructor(init = {}) {
|
4
4
|
this.protocol = '/mplex/6.7.0';
|
5
|
+
this.init = init;
|
5
6
|
}
|
6
|
-
createStreamMuxer(components, init) {
|
7
|
-
return new MplexStreamMuxer(components,
|
7
|
+
createStreamMuxer(components, init = {}) {
|
8
|
+
return new MplexStreamMuxer(components, {
|
9
|
+
...init,
|
10
|
+
...this.init
|
11
|
+
});
|
8
12
|
}
|
9
13
|
}
|
10
14
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAiB7C,MAAM,OAAO,KAAK;IAIhB,YAAa,OAAkB,EAAE;QAH1B,aAAQ,GAAG,cAAc,CAAA;QAI9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAED,iBAAiB,CAAE,UAAsB,EAAE,OAAwB,EAAE;QACnE,OAAO,IAAI,gBAAgB,CAAC,UAAU,EAAE;YACtC,GAAG,IAAI;YACP,GAAG,IAAI,CAAC,IAAI;SACb,CAAC,CAAA;IACJ,CAAC;CACF"}
|
package/dist/src/mplex.d.ts
CHANGED
@@ -4,11 +4,11 @@ import type { Components } from '@libp2p/interfaces/components';
|
|
4
4
|
import type { Sink } from 'it-stream-types';
|
5
5
|
import type { StreamMuxer, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer';
|
6
6
|
import type { Stream } from '@libp2p/interfaces/connection';
|
7
|
+
import type { MplexInit } from './index.js';
|
7
8
|
export interface MplexStream extends Stream {
|
8
9
|
source: Pushable<Uint8Array>;
|
9
10
|
}
|
10
|
-
|
11
|
-
maxMsgSize?: number;
|
11
|
+
interface MplexStreamMuxerInit extends MplexInit, StreamMuxerInit {
|
12
12
|
}
|
13
13
|
export declare class MplexStreamMuxer implements StreamMuxer {
|
14
14
|
protocol: string;
|
@@ -18,7 +18,7 @@ export declare class MplexStreamMuxer implements StreamMuxer {
|
|
18
18
|
private readonly _streams;
|
19
19
|
private readonly _init;
|
20
20
|
private readonly _source;
|
21
|
-
constructor(components: Components, init?:
|
21
|
+
constructor(components: Components, init?: MplexStreamMuxerInit);
|
22
22
|
init(components: Components): void;
|
23
23
|
/**
|
24
24
|
* Returns a Map of streams and their ids
|
@@ -60,4 +60,5 @@ export declare class MplexStreamMuxer implements StreamMuxer {
|
|
60
60
|
};
|
61
61
|
_handleIncoming(message: Message): void;
|
62
62
|
}
|
63
|
+
export {};
|
63
64
|
//# sourceMappingURL=mplex.d.ts.map
|
package/dist/src/mplex.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"mplex.d.ts","sourceRoot":"","sources":["../../src/mplex.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAa,MAAM,aAAa,CAAA;AAKjD,OAAO,EAAkC,OAAO,EAAE,MAAM,oBAAoB,CAAA;
|
1
|
+
{"version":3,"file":"mplex.d.ts","sourceRoot":"","sources":["../../src/mplex.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAa,MAAM,aAAa,CAAA;AAKjD,OAAO,EAAkC,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAM5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AACnF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAA;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAuB3C,MAAM,WAAW,WAAY,SAAQ,MAAM;IACzC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAA;CAC7B;AAED,UAAU,oBAAqB,SAAQ,SAAS,EAAE,eAAe;CAAG;AAEpE,qBAAa,gBAAiB,YAAW,WAAW;IAC3C,QAAQ,SAAiB;IAEzB,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;IACtB,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;IAExC,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,CAA8D;gBAEzE,UAAU,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,oBAAoB;IA6BhE,IAAI,CAAE,UAAU,EAAE,UAAU;IAI5B;;OAEG;IACH,IAAI,OAAO,aAUV;IAED;;;OAGG;IACH,SAAS,CAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAOjC;;OAEG;IACH,kBAAkB,CAAE,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAMzD,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;IA6CrH;;;OAGG;IACH,WAAW;IA4BX;;;OAGG;IACH,aAAa;;;;;;;IA4Bb,eAAe,CAAE,OAAO,EAAE,OAAO;CA+ClC"}
|
package/dist/src/mplex.js
CHANGED
@@ -9,7 +9,9 @@ import { createStream } from './stream.js';
|
|
9
9
|
import { toString as uint8ArrayToString } from 'uint8arrays';
|
10
10
|
import { trackedMap } from '@libp2p/tracked-map';
|
11
11
|
import { logger } from '@libp2p/logger';
|
12
|
+
import errCode from 'err-code';
|
12
13
|
const log = logger('libp2p:mplex');
|
14
|
+
const MAX_STREAMS_PER_CONNECTION = 1024;
|
13
15
|
function printMessage(msg) {
|
14
16
|
const output = {
|
15
17
|
...msg,
|
@@ -85,12 +87,19 @@ export class MplexStreamMuxer {
|
|
85
87
|
return this._newStream({ id, name, type: 'receiver', registry });
|
86
88
|
}
|
87
89
|
_newStream(options) {
|
90
|
+
const maxStreams = this._init.maxStreamsPerConnection ?? MAX_STREAMS_PER_CONNECTION;
|
91
|
+
if ((this._streams.initiators.size + this._streams.receivers.size) === maxStreams) {
|
92
|
+
throw errCode(new Error('To many streams open'), 'ERR_TOO_MANY_STREAMS');
|
93
|
+
}
|
88
94
|
const { id, name, type, registry } = options;
|
89
95
|
log('new %s stream %s %s', type, id, name);
|
90
96
|
if (registry.has(id)) {
|
91
97
|
throw new Error(`${type} stream ${id} already exists!`);
|
92
98
|
}
|
93
99
|
const send = (msg) => {
|
100
|
+
if (!registry.has(id)) {
|
101
|
+
throw errCode(new Error('the stream is not in the muxer registry, it may have already been closed'), 'ERR_STREAM_DOESNT_EXIST');
|
102
|
+
}
|
94
103
|
if (log.enabled) {
|
95
104
|
log.trace('%s stream %s send', type, id, printMessage(msg));
|
96
105
|
}
|
@@ -143,10 +152,20 @@ export class MplexStreamMuxer {
|
|
143
152
|
const { initiators, receivers } = this._streams;
|
144
153
|
// Abort all the things!
|
145
154
|
for (const s of initiators.values()) {
|
146
|
-
|
155
|
+
if (err != null) {
|
156
|
+
s.abort(err);
|
157
|
+
}
|
158
|
+
else {
|
159
|
+
s.close();
|
160
|
+
}
|
147
161
|
}
|
148
162
|
for (const s of receivers.values()) {
|
149
|
-
|
163
|
+
if (err != null) {
|
164
|
+
s.abort(err);
|
165
|
+
}
|
166
|
+
else {
|
167
|
+
s.close();
|
168
|
+
}
|
150
169
|
}
|
151
170
|
};
|
152
171
|
const source = pushableV({ onEnd });
|
@@ -178,14 +197,17 @@ export class MplexStreamMuxer {
|
|
178
197
|
switch (type) {
|
179
198
|
case MessageTypes.MESSAGE_INITIATOR:
|
180
199
|
case MessageTypes.MESSAGE_RECEIVER:
|
200
|
+
// We got data from the remote, push it into our local stream
|
181
201
|
stream.source.push(message.data.slice());
|
182
202
|
break;
|
183
203
|
case MessageTypes.CLOSE_INITIATOR:
|
184
204
|
case MessageTypes.CLOSE_RECEIVER:
|
185
|
-
|
205
|
+
// We should expect no more data from the remote, stop reading
|
206
|
+
stream.closeRead();
|
186
207
|
break;
|
187
208
|
case MessageTypes.RESET_INITIATOR:
|
188
209
|
case MessageTypes.RESET_RECEIVER:
|
210
|
+
// Stop reading and writing to the stream immediately
|
189
211
|
stream.reset();
|
190
212
|
break;
|
191
213
|
default:
|
package/dist/src/mplex.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"mplex.js","sourceRoot":"","sources":["../../src/mplex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAC9B,OAAO,EAAY,SAAS,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAW,MAAM,oBAAoB,CAAA;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;
|
1
|
+
{"version":3,"file":"mplex.js","sourceRoot":"","sources":["../../src/mplex.ts"],"names":[],"mappings":"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"}
|
package/dist/src/stream.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/stream.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAGjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/stream.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAGjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAQ7C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IAC7B,IAAI,CAAC,EAAE,WAAW,GAAG,UAAU,CAAA;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAgB,YAAY,CAAE,OAAO,EAAE,OAAO,GAAG,WAAW,CA0M3D"}
|
package/dist/src/stream.js
CHANGED
@@ -10,10 +10,12 @@ import { logger } from '@libp2p/logger';
|
|
10
10
|
const log = logger('libp2p:mplex:stream');
|
11
11
|
const ERR_MPLEX_STREAM_RESET = 'ERR_MPLEX_STREAM_RESET';
|
12
12
|
const ERR_MPLEX_STREAM_ABORT = 'ERR_MPLEX_STREAM_ABORT';
|
13
|
+
const ERR_MPLEX_SINK_ENDED = 'ERR_MPLEX_SINK_ENDED';
|
13
14
|
export function createStream(options) {
|
14
15
|
const { id, name, send, onEnd, type = 'initiator', maxMsgSize = MAX_MSG_SIZE } = options;
|
15
16
|
const abortController = new AbortController();
|
16
17
|
const resetController = new AbortController();
|
18
|
+
const closeController = new AbortController();
|
17
19
|
const Types = type === 'initiator' ? InitiatorMessageTypes : ReceiverMessageTypes;
|
18
20
|
const externalId = type === 'initiator' ? (`i${id}`) : `r${id}`;
|
19
21
|
const streamName = `${name == null ? id : name}`;
|
@@ -28,7 +30,7 @@ export function createStream(options) {
|
|
28
30
|
return;
|
29
31
|
}
|
30
32
|
sourceEnded = true;
|
31
|
-
log.trace('%s stream %s source end', type, streamName, err);
|
33
|
+
log.trace('%s stream %s source end - err: %o', type, streamName, err);
|
32
34
|
if (err != null && endErr == null) {
|
33
35
|
endErr = err;
|
34
36
|
}
|
@@ -56,10 +58,35 @@ export function createStream(options) {
|
|
56
58
|
}
|
57
59
|
};
|
58
60
|
const stream = {
|
59
|
-
// Close for
|
61
|
+
// Close for both Reading and Writing
|
60
62
|
close: () => {
|
63
|
+
log.trace('%s stream %s close', type, streamName);
|
64
|
+
stream.closeRead();
|
65
|
+
stream.closeWrite();
|
66
|
+
},
|
67
|
+
// Close for reading
|
68
|
+
closeRead: () => {
|
69
|
+
log.trace('%s stream %s closeRead', type, streamName);
|
70
|
+
if (sourceEnded) {
|
71
|
+
return;
|
72
|
+
}
|
61
73
|
stream.source.end();
|
62
74
|
},
|
75
|
+
// Close for writing
|
76
|
+
closeWrite: () => {
|
77
|
+
log.trace('%s stream %s closeWrite', type, streamName);
|
78
|
+
if (sinkEnded) {
|
79
|
+
return;
|
80
|
+
}
|
81
|
+
closeController.abort();
|
82
|
+
try {
|
83
|
+
send({ id, type: Types.CLOSE });
|
84
|
+
}
|
85
|
+
catch (err) {
|
86
|
+
log.trace('%s stream %s error sending close', type, name, err);
|
87
|
+
}
|
88
|
+
onSinkEnd();
|
89
|
+
},
|
63
90
|
// Close for reading and writing (local error)
|
64
91
|
abort: (err) => {
|
65
92
|
log.trace('%s stream %s abort', type, streamName, err);
|
@@ -76,9 +103,13 @@ export function createStream(options) {
|
|
76
103
|
onSinkEnd(err);
|
77
104
|
},
|
78
105
|
sink: async (source) => {
|
106
|
+
if (sinkEnded) {
|
107
|
+
throw errCode(new Error('stream closed for writing'), ERR_MPLEX_SINK_ENDED);
|
108
|
+
}
|
79
109
|
source = abortableSource(source, anySignal([
|
80
110
|
abortController.signal,
|
81
|
-
resetController.signal
|
111
|
+
resetController.signal,
|
112
|
+
closeController.signal
|
82
113
|
]));
|
83
114
|
try {
|
84
115
|
if (type === 'initiator') { // If initiator, open a new stream
|
@@ -101,6 +132,9 @@ export function createStream(options) {
|
|
101
132
|
}
|
102
133
|
catch (err) {
|
103
134
|
if (err.type === 'aborted' && err.message === 'The operation was aborted') {
|
135
|
+
if (closeController.signal.aborted) {
|
136
|
+
return;
|
137
|
+
}
|
104
138
|
if (resetController.signal.aborted) {
|
105
139
|
err.message = 'stream reset';
|
106
140
|
err.code = ERR_MPLEX_STREAM_RESET;
|
package/dist/src/stream.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,OAAO,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAChF,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAMvC,MAAM,GAAG,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAA;AAEzC,MAAM,sBAAsB,GAAG,wBAAwB,CAAA;AACvD,MAAM,sBAAsB,GAAG,wBAAwB,CAAA;
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,OAAO,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAChF,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAMvC,MAAM,GAAG,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAA;AAEzC,MAAM,sBAAsB,GAAG,wBAAwB,CAAA;AACvD,MAAM,sBAAsB,GAAG,wBAAwB,CAAA;AACvD,MAAM,oBAAoB,GAAG,sBAAsB,CAAA;AAWnD,MAAM,UAAU,YAAY,CAAE,OAAgB;IAC5C,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,WAAW,EAAE,UAAU,GAAG,YAAY,EAAE,GAAG,OAAO,CAAA;IAExF,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAA;IAC7C,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAA;IAC7C,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAA;IAC7C,MAAM,KAAK,GAAG,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,oBAAoB,CAAA;IACjF,MAAM,UAAU,GAAG,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAA;IAC/D,MAAM,UAAU,GAAG,GAAG,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAEhD,IAAI,WAAW,GAAG,KAAK,CAAA;IACvB,IAAI,SAAS,GAAG,KAAK,CAAA;IACrB,IAAI,MAAyB,CAAA;IAE7B,MAAM,QAAQ,GAAa;QACzB,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE;KACjB,CAAA;IAED,MAAM,WAAW,GAAG,CAAC,GAAW,EAAE,EAAE;QAClC,IAAI,WAAW,EAAE;YACf,OAAM;SACP;QAED,WAAW,GAAG,IAAI,CAAA;QAClB,GAAG,CAAC,KAAK,CAAC,mCAAmC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,CAAA;QAErE,IAAI,GAAG,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,EAAE;YACjC,MAAM,GAAG,GAAG,CAAA;SACb;QAED,IAAI,SAAS,EAAE;YACb,MAAM,CAAC,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YAElC,IAAI,KAAK,IAAI,IAAI,EAAE;gBACjB,KAAK,CAAC,MAAM,CAAC,CAAA;aACd;SACF;IACH,CAAC,CAAA;IAED,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,EAAE;QAChC,IAAI,SAAS,EAAE;YACb,OAAM;SACP;QAED,SAAS,GAAG,IAAI,CAAA;QAChB,GAAG,CAAC,KAAK,CAAC,iCAAiC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,CAAA;QAEnE,IAAI,GAAG,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,EAAE;YACjC,MAAM,GAAG,GAAG,CAAA;SACb;QAED,IAAI,WAAW,EAAE;YACf,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YAE3B,IAAI,KAAK,IAAI,IAAI,EAAE;gBACjB,KAAK,CAAC,MAAM,CAAC,CAAA;aACd;SACF;IACH,CAAC,CAAA;IAED,MAAM,MAAM,GAAgB;QAC1B,qCAAqC;QACrC,KAAK,EAAE,GAAG,EAAE;YACV,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;YAEjD,MAAM,CAAC,SAAS,EAAE,CAAA;YAClB,MAAM,CAAC,UAAU,EAAE,CAAA;QACrB,CAAC;QAED,oBAAoB;QACpB,SAAS,EAAE,GAAG,EAAE;YACd,GAAG,CAAC,KAAK,CAAC,wBAAwB,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;YAErD,IAAI,WAAW,EAAE;gBACf,OAAM;aACP;YAED,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAA;QACrB,CAAC;QAED,oBAAoB;QACpB,UAAU,EAAE,GAAG,EAAE;YACf,GAAG,CAAC,KAAK,CAAC,yBAAyB,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;YAEtD,IAAI,SAAS,EAAE;gBACb,OAAM;aACP;YAED,eAAe,CAAC,KAAK,EAAE,CAAA;YAEvB,IAAI;gBACF,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;aAChC;YAAC,OAAO,GAAG,EAAE;gBACZ,GAAG,CAAC,KAAK,CAAC,kCAAkC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;aAC/D;YAED,SAAS,EAAE,CAAA;QACb,CAAC;QAED,8CAA8C;QAC9C,KAAK,EAAE,CAAC,GAAU,EAAE,EAAE;YACpB,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,CAAA;YACtD,uCAAuC;YACvC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACtB,eAAe,CAAC,KAAK,EAAE,CAAA;YACvB,SAAS,CAAC,GAAG,CAAC,CAAA;QAChB,CAAC;QAED,2DAA2D;QAC3D,KAAK,EAAE,GAAG,EAAE;YACV,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,KAAK,CAAC,cAAc,CAAC,EAAE,sBAAsB,CAAC,CAAA;YACtE,eAAe,CAAC,KAAK,EAAE,CAAA;YACvB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACtB,SAAS,CAAC,GAAG,CAAC,CAAA;QAChB,CAAC;QAED,IAAI,EAAE,KAAK,EAAE,MAA0B,EAAE,EAAE;YACzC,IAAI,SAAS,EAAE;gBACb,MAAM,OAAO,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,EAAE,oBAAoB,CAAC,CAAA;aAC5E;YAED,MAAM,GAAG,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC;gBACzC,eAAe,CAAC,MAAM;gBACtB,eAAe,CAAC,MAAM;gBACtB,eAAe,CAAC,MAAM;aACvB,CAAC,CAAC,CAAA;YAEH,IAAI;gBACF,IAAI,IAAI,KAAK,WAAW,EAAE,EAAE,kCAAkC;oBAC5D,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,qBAAqB,CAAC,UAAU,EAAE,IAAI,EAAE,oBAAoB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;iBAC7F;gBAED,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAA;gBAE3C,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,EAAE;oBAC/B,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;oBAE3B,OAAO,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE;wBAClC,IAAI,cAAc,CAAC,MAAM,IAAI,UAAU,EAAE;4BACvC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,cAAc,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;4BAClE,cAAc,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA;4BAC7C,MAAK;yBACN;wBAED,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,GAAG,UAAU,CAAA;wBACjD,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,CAAA;wBAC3E,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;qBAC/B;iBACF;aACF;YAAC,OAAO,GAAQ,EAAE;gBACjB,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,OAAO,KAAK,2BAA2B,EAAE;oBACzE,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE;wBAClC,OAAM;qBACP;oBAED,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE;wBAClC,GAAG,CAAC,OAAO,GAAG,cAAc,CAAA;wBAC5B,GAAG,CAAC,IAAI,GAAG,sBAAsB,CAAA;qBAClC;oBAED,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE;wBAClC,GAAG,CAAC,OAAO,GAAG,gBAAgB,CAAA;wBAC9B,GAAG,CAAC,IAAI,GAAG,sBAAsB,CAAA;qBAClC;iBACF;gBAED,sDAAsD;gBACtD,IAAI,GAAG,CAAC,IAAI,KAAK,sBAAsB,EAAE;oBACvC,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;iBAC5C;qBAAM;oBACL,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;oBAChD,IAAI;wBACF,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;qBAChC;oBAAC,OAAO,GAAG,EAAE;wBACZ,GAAG,CAAC,KAAK,CAAC,kCAAkC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;qBAC/D;iBACF;gBAED,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;gBACtB,SAAS,CAAC,GAAG,CAAC,CAAA;gBACd,OAAM;aACP;YAED,IAAI;gBACF,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;aAChC;YAAC,OAAO,GAAG,EAAE;gBACZ,GAAG,CAAC,KAAK,CAAC,kCAAkC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;aAC/D;YAED,SAAS,EAAE,CAAA;QACb,CAAC;QAED,MAAM,EAAE,QAAQ,CAAa;YAC3B,KAAK,EAAE,WAAW;SACnB,CAAC;QAEF,QAAQ;QAER,EAAE,EAAE,UAAU;KACf,CAAA;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@libp2p/mplex",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.1.2",
|
4
4
|
"description": "JavaScript implementation of https://github.com/libp2p/mplex",
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
6
6
|
"homepage": "https://github.com/libp2p/js-libp2p-mplex#readme",
|
@@ -153,8 +153,8 @@
|
|
153
153
|
"varint": "^6.0.0"
|
154
154
|
},
|
155
155
|
"devDependencies": {
|
156
|
-
"@libp2p/interface-compliance-tests": "^
|
157
|
-
"@libp2p/interfaces": "^
|
156
|
+
"@libp2p/interface-compliance-tests": "^2.0.1",
|
157
|
+
"@libp2p/interfaces": "^2.0.1",
|
158
158
|
"@types/varint": "^6.0.0",
|
159
159
|
"aegir": "^37.0.10",
|
160
160
|
"cborg": "^1.8.1",
|
package/src/index.ts
CHANGED
@@ -2,14 +2,33 @@ import type { Components } from '@libp2p/interfaces/components'
|
|
2
2
|
import type { StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer'
|
3
3
|
import { MplexStreamMuxer } from './mplex.js'
|
4
4
|
|
5
|
-
export interface MplexInit
|
5
|
+
export interface MplexInit {
|
6
|
+
/**
|
7
|
+
* The maximum size of message that can be sent in one go in bytes.
|
8
|
+
* Messages larger than this will be split into multiple smaller
|
9
|
+
* messages.
|
10
|
+
*/
|
6
11
|
maxMsgSize?: number
|
12
|
+
|
13
|
+
/**
|
14
|
+
* The maximum number of multiplexed streams that can be open at any
|
15
|
+
* one time. An attempt to open more than this will throw.
|
16
|
+
*/
|
17
|
+
maxStreamsPerConnection?: number
|
7
18
|
}
|
8
19
|
|
9
20
|
export class Mplex implements StreamMuxerFactory {
|
10
21
|
public protocol = '/mplex/6.7.0'
|
22
|
+
private readonly init: MplexInit
|
23
|
+
|
24
|
+
constructor (init: MplexInit = {}) {
|
25
|
+
this.init = init
|
26
|
+
}
|
11
27
|
|
12
|
-
createStreamMuxer (components: Components, init
|
13
|
-
return new MplexStreamMuxer(components,
|
28
|
+
createStreamMuxer (components: Components, init: StreamMuxerInit = {}) {
|
29
|
+
return new MplexStreamMuxer(components, {
|
30
|
+
...init,
|
31
|
+
...this.init
|
32
|
+
})
|
14
33
|
}
|
15
34
|
}
|
package/src/mplex.ts
CHANGED
@@ -9,13 +9,17 @@ import { createStream } from './stream.js'
|
|
9
9
|
import { toString as uint8ArrayToString } from 'uint8arrays'
|
10
10
|
import { trackedMap } from '@libp2p/tracked-map'
|
11
11
|
import { logger } from '@libp2p/logger'
|
12
|
+
import errCode from 'err-code'
|
12
13
|
import type { Components } from '@libp2p/interfaces/components'
|
13
14
|
import type { Sink } from 'it-stream-types'
|
14
15
|
import type { StreamMuxer, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer'
|
15
16
|
import type { Stream } from '@libp2p/interfaces/connection'
|
17
|
+
import type { MplexInit } from './index.js'
|
16
18
|
|
17
19
|
const log = logger('libp2p:mplex')
|
18
20
|
|
21
|
+
const MAX_STREAMS_PER_CONNECTION = 1024
|
22
|
+
|
19
23
|
function printMessage (msg: Message) {
|
20
24
|
const output: any = {
|
21
25
|
...msg,
|
@@ -37,9 +41,7 @@ export interface MplexStream extends Stream {
|
|
37
41
|
source: Pushable<Uint8Array>
|
38
42
|
}
|
39
43
|
|
40
|
-
|
41
|
-
maxMsgSize?: number
|
42
|
-
}
|
44
|
+
interface MplexStreamMuxerInit extends MplexInit, StreamMuxerInit {}
|
43
45
|
|
44
46
|
export class MplexStreamMuxer implements StreamMuxer {
|
45
47
|
public protocol = '/mplex/6.7.0'
|
@@ -49,10 +51,10 @@ export class MplexStreamMuxer implements StreamMuxer {
|
|
49
51
|
|
50
52
|
private _streamId: number
|
51
53
|
private readonly _streams: { initiators: Map<number, MplexStream>, receivers: Map<number, MplexStream> }
|
52
|
-
private readonly _init:
|
54
|
+
private readonly _init: MplexStreamMuxerInit
|
53
55
|
private readonly _source: { push: (val: Message) => void, end: (err?: Error) => void }
|
54
56
|
|
55
|
-
constructor (components: Components, init?:
|
57
|
+
constructor (components: Components, init?: MplexStreamMuxerInit) {
|
56
58
|
init = init ?? {}
|
57
59
|
|
58
60
|
this._streamId = 0
|
@@ -121,6 +123,12 @@ export class MplexStreamMuxer implements StreamMuxer {
|
|
121
123
|
}
|
122
124
|
|
123
125
|
_newStream (options: { id: number, name: string, type: 'initiator' | 'receiver', registry: Map<number, MplexStream> }) {
|
126
|
+
const maxStreams = this._init.maxStreamsPerConnection ?? MAX_STREAMS_PER_CONNECTION
|
127
|
+
|
128
|
+
if ((this._streams.initiators.size + this._streams.receivers.size) === maxStreams) {
|
129
|
+
throw errCode(new Error('To many streams open'), 'ERR_TOO_MANY_STREAMS')
|
130
|
+
}
|
131
|
+
|
124
132
|
const { id, name, type, registry } = options
|
125
133
|
|
126
134
|
log('new %s stream %s %s', type, id, name)
|
@@ -130,6 +138,10 @@ export class MplexStreamMuxer implements StreamMuxer {
|
|
130
138
|
}
|
131
139
|
|
132
140
|
const send = (msg: Message) => {
|
141
|
+
if (!registry.has(id)) {
|
142
|
+
throw errCode(new Error('the stream is not in the muxer registry, it may have already been closed'), 'ERR_STREAM_DOESNT_EXIST')
|
143
|
+
}
|
144
|
+
|
133
145
|
if (log.enabled) {
|
134
146
|
log.trace('%s stream %s send', type, id, printMessage(msg))
|
135
147
|
}
|
@@ -196,10 +208,18 @@ export class MplexStreamMuxer implements StreamMuxer {
|
|
196
208
|
const { initiators, receivers } = this._streams
|
197
209
|
// Abort all the things!
|
198
210
|
for (const s of initiators.values()) {
|
199
|
-
|
211
|
+
if (err != null) {
|
212
|
+
s.abort(err)
|
213
|
+
} else {
|
214
|
+
s.close()
|
215
|
+
}
|
200
216
|
}
|
201
217
|
for (const s of receivers.values()) {
|
202
|
-
|
218
|
+
if (err != null) {
|
219
|
+
s.abort(err)
|
220
|
+
} else {
|
221
|
+
s.close()
|
222
|
+
}
|
203
223
|
}
|
204
224
|
}
|
205
225
|
const source = pushableV<Message>({ onEnd })
|
@@ -241,14 +261,17 @@ export class MplexStreamMuxer implements StreamMuxer {
|
|
241
261
|
switch (type) {
|
242
262
|
case MessageTypes.MESSAGE_INITIATOR:
|
243
263
|
case MessageTypes.MESSAGE_RECEIVER:
|
264
|
+
// We got data from the remote, push it into our local stream
|
244
265
|
stream.source.push(message.data.slice())
|
245
266
|
break
|
246
267
|
case MessageTypes.CLOSE_INITIATOR:
|
247
268
|
case MessageTypes.CLOSE_RECEIVER:
|
248
|
-
|
269
|
+
// We should expect no more data from the remote, stop reading
|
270
|
+
stream.closeRead()
|
249
271
|
break
|
250
272
|
case MessageTypes.RESET_INITIATOR:
|
251
273
|
case MessageTypes.RESET_RECEIVER:
|
274
|
+
// Stop reading and writing to the stream immediately
|
252
275
|
stream.reset()
|
253
276
|
break
|
254
277
|
default:
|
package/src/stream.ts
CHANGED
@@ -16,6 +16,7 @@ const log = logger('libp2p:mplex:stream')
|
|
16
16
|
|
17
17
|
const ERR_MPLEX_STREAM_RESET = 'ERR_MPLEX_STREAM_RESET'
|
18
18
|
const ERR_MPLEX_STREAM_ABORT = 'ERR_MPLEX_STREAM_ABORT'
|
19
|
+
const ERR_MPLEX_SINK_ENDED = 'ERR_MPLEX_SINK_ENDED'
|
19
20
|
|
20
21
|
export interface Options {
|
21
22
|
id: number
|
@@ -31,6 +32,7 @@ export function createStream (options: Options): MplexStream {
|
|
31
32
|
|
32
33
|
const abortController = new AbortController()
|
33
34
|
const resetController = new AbortController()
|
35
|
+
const closeController = new AbortController()
|
34
36
|
const Types = type === 'initiator' ? InitiatorMessageTypes : ReceiverMessageTypes
|
35
37
|
const externalId = type === 'initiator' ? (`i${id}`) : `r${id}`
|
36
38
|
const streamName = `${name == null ? id : name}`
|
@@ -49,7 +51,7 @@ export function createStream (options: Options): MplexStream {
|
|
49
51
|
}
|
50
52
|
|
51
53
|
sourceEnded = true
|
52
|
-
log.trace('%s stream %s source end', type, streamName, err)
|
54
|
+
log.trace('%s stream %s source end - err: %o', type, streamName, err)
|
53
55
|
|
54
56
|
if (err != null && endErr == null) {
|
55
57
|
endErr = err
|
@@ -85,19 +87,54 @@ export function createStream (options: Options): MplexStream {
|
|
85
87
|
}
|
86
88
|
}
|
87
89
|
|
88
|
-
const stream = {
|
89
|
-
// Close for
|
90
|
+
const stream: MplexStream = {
|
91
|
+
// Close for both Reading and Writing
|
90
92
|
close: () => {
|
93
|
+
log.trace('%s stream %s close', type, streamName)
|
94
|
+
|
95
|
+
stream.closeRead()
|
96
|
+
stream.closeWrite()
|
97
|
+
},
|
98
|
+
|
99
|
+
// Close for reading
|
100
|
+
closeRead: () => {
|
101
|
+
log.trace('%s stream %s closeRead', type, streamName)
|
102
|
+
|
103
|
+
if (sourceEnded) {
|
104
|
+
return
|
105
|
+
}
|
106
|
+
|
91
107
|
stream.source.end()
|
92
108
|
},
|
109
|
+
|
110
|
+
// Close for writing
|
111
|
+
closeWrite: () => {
|
112
|
+
log.trace('%s stream %s closeWrite', type, streamName)
|
113
|
+
|
114
|
+
if (sinkEnded) {
|
115
|
+
return
|
116
|
+
}
|
117
|
+
|
118
|
+
closeController.abort()
|
119
|
+
|
120
|
+
try {
|
121
|
+
send({ id, type: Types.CLOSE })
|
122
|
+
} catch (err) {
|
123
|
+
log.trace('%s stream %s error sending close', type, name, err)
|
124
|
+
}
|
125
|
+
|
126
|
+
onSinkEnd()
|
127
|
+
},
|
128
|
+
|
93
129
|
// Close for reading and writing (local error)
|
94
|
-
abort: (err
|
130
|
+
abort: (err: Error) => {
|
95
131
|
log.trace('%s stream %s abort', type, streamName, err)
|
96
132
|
// End the source with the passed error
|
97
133
|
stream.source.end(err)
|
98
134
|
abortController.abort()
|
99
135
|
onSinkEnd(err)
|
100
136
|
},
|
137
|
+
|
101
138
|
// Close immediately for reading and writing (remote error)
|
102
139
|
reset: () => {
|
103
140
|
const err = errCode(new Error('stream reset'), ERR_MPLEX_STREAM_RESET)
|
@@ -105,10 +142,16 @@ export function createStream (options: Options): MplexStream {
|
|
105
142
|
stream.source.end(err)
|
106
143
|
onSinkEnd(err)
|
107
144
|
},
|
145
|
+
|
108
146
|
sink: async (source: Source<Uint8Array>) => {
|
147
|
+
if (sinkEnded) {
|
148
|
+
throw errCode(new Error('stream closed for writing'), ERR_MPLEX_SINK_ENDED)
|
149
|
+
}
|
150
|
+
|
109
151
|
source = abortableSource(source, anySignal([
|
110
152
|
abortController.signal,
|
111
|
-
resetController.signal
|
153
|
+
resetController.signal,
|
154
|
+
closeController.signal
|
112
155
|
]))
|
113
156
|
|
114
157
|
try {
|
@@ -135,6 +178,10 @@ export function createStream (options: Options): MplexStream {
|
|
135
178
|
}
|
136
179
|
} catch (err: any) {
|
137
180
|
if (err.type === 'aborted' && err.message === 'The operation was aborted') {
|
181
|
+
if (closeController.signal.aborted) {
|
182
|
+
return
|
183
|
+
}
|
184
|
+
|
138
185
|
if (resetController.signal.aborted) {
|
139
186
|
err.message = 'stream reset'
|
140
187
|
err.code = ERR_MPLEX_STREAM_RESET
|
@@ -171,10 +218,13 @@ export function createStream (options: Options): MplexStream {
|
|
171
218
|
|
172
219
|
onSinkEnd()
|
173
220
|
},
|
221
|
+
|
174
222
|
source: pushable<Uint8Array>({
|
175
223
|
onEnd: onSourceEnd
|
176
224
|
}),
|
225
|
+
|
177
226
|
timeline,
|
227
|
+
|
178
228
|
id: externalId
|
179
229
|
}
|
180
230
|
|