@libp2p/mplex 1.0.1 → 1.0.4
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/dist/src/index.d.ts +7 -59
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -191
- package/dist/src/index.js.map +1 -1
- package/dist/src/mplex.d.ts +63 -0
- package/dist/src/mplex.d.ts.map +1 -0
- package/dist/src/mplex.js +199 -0
- package/dist/src/mplex.js.map +1 -0
- package/dist/src/stream.d.ts +1 -1
- package/dist/src/stream.js +7 -7
- package/dist/src/stream.js.map +1 -1
- package/package.json +21 -21
- package/src/index.ts +8 -250
- package/src/mplex.ts +262 -0
- package/src/stream.ts +8 -8
package/dist/src/index.d.ts
CHANGED
@@ -1,63 +1,11 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
3
|
-
import
|
4
|
-
|
5
|
-
import type { Stream } from '@libp2p/interfaces/connection';
|
6
|
-
import type { ComponentMetricsTracker } from '@libp2p/interfaces/metrics';
|
7
|
-
export interface MplexStream extends Stream {
|
8
|
-
source: Pushable<Uint8Array>;
|
9
|
-
}
|
10
|
-
export interface MplexOptions extends MuxerOptions {
|
1
|
+
import type { Components } from '@libp2p/interfaces/components';
|
2
|
+
import type { StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer';
|
3
|
+
import { MplexStreamMuxer } from './mplex.js';
|
4
|
+
export interface MplexInit extends StreamMuxerInit {
|
11
5
|
maxMsgSize?: number;
|
12
|
-
metrics?: ComponentMetricsTracker;
|
13
6
|
}
|
14
|
-
export declare class Mplex implements
|
15
|
-
|
16
|
-
|
17
|
-
source: AsyncIterable<Uint8Array>;
|
18
|
-
private _streamId;
|
19
|
-
private readonly _streams;
|
20
|
-
private readonly _options;
|
21
|
-
private readonly _source;
|
22
|
-
constructor(options?: MplexOptions);
|
23
|
-
/**
|
24
|
-
* Returns a Map of streams and their ids
|
25
|
-
*/
|
26
|
-
get streams(): Stream[];
|
27
|
-
/**
|
28
|
-
* Initiate a new stream with the given name. If no name is
|
29
|
-
* provided, the id of the stream will be used.
|
30
|
-
*/
|
31
|
-
newStream(name?: string): Stream;
|
32
|
-
/**
|
33
|
-
* Called whenever an inbound stream is created
|
34
|
-
*/
|
35
|
-
_newReceiverStream(options: {
|
36
|
-
id: number;
|
37
|
-
name: string;
|
38
|
-
}): MplexStream;
|
39
|
-
_newStream(options: {
|
40
|
-
id: number;
|
41
|
-
name: string;
|
42
|
-
type: 'initiator' | 'receiver';
|
43
|
-
registry: Map<number, MplexStream>;
|
44
|
-
}): MplexStream;
|
45
|
-
/**
|
46
|
-
* Creates a sink with an abortable source. Incoming messages will
|
47
|
-
* also have their size restricted. All messages will be varint decoded.
|
48
|
-
*/
|
49
|
-
_createSink(): Sink<Uint8Array, Promise<void>>;
|
50
|
-
/**
|
51
|
-
* Creates a source that restricts outgoing message sizes
|
52
|
-
* and varint encodes them
|
53
|
-
*/
|
54
|
-
_createSource(): AsyncGenerator<Uint8Array, void, undefined> & {
|
55
|
-
push: (value: Message) => import("it-pushable").PushableV<Message>;
|
56
|
-
end: (err?: Error | undefined) => import("it-pushable").PushableV<Message>;
|
57
|
-
return: () => {
|
58
|
-
done: boolean;
|
59
|
-
};
|
60
|
-
};
|
61
|
-
_handleIncoming(message: Message): void;
|
7
|
+
export declare class Mplex implements StreamMuxerFactory {
|
8
|
+
protocol: string;
|
9
|
+
createStreamMuxer(components: Components, init?: MplexInit): MplexStreamMuxer;
|
62
10
|
}
|
63
11
|
//# 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":"
|
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,SAAU,SAAQ,eAAe;IAChD,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,qBAAa,KAAM,YAAW,kBAAkB;IACvC,QAAQ,SAAiB;IAEhC,iBAAiB,CAAE,UAAU,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,SAAS;CAG5D"}
|
package/dist/src/index.js
CHANGED
@@ -1,196 +1,10 @@
|
|
1
|
-
import {
|
2
|
-
import { pushableV } from 'it-pushable';
|
3
|
-
import { abortableSource } from 'abortable-iterator';
|
4
|
-
import { encode } from './encode.js';
|
5
|
-
import { decode } from './decode.js';
|
6
|
-
import { restrictSize } from './restrict-size.js';
|
7
|
-
import { MessageTypes, MessageTypeNames } from './message-types.js';
|
8
|
-
import { createStream } from './stream.js';
|
9
|
-
import { toString as uint8ArrayToString } from 'uint8arrays';
|
10
|
-
import { trackedMap } from '@libp2p/tracked-map';
|
11
|
-
import { logger } from '@libp2p/logger';
|
12
|
-
import each from 'it-foreach';
|
13
|
-
const log = logger('libp2p:mplex');
|
14
|
-
function printMessage(msg) {
|
15
|
-
const output = {
|
16
|
-
...msg,
|
17
|
-
type: `${MessageTypeNames[msg.type]} (${msg.type})`
|
18
|
-
};
|
19
|
-
if (msg.type === MessageTypes.NEW_STREAM) {
|
20
|
-
output.data = uint8ArrayToString(msg.data instanceof Uint8Array ? msg.data : msg.data.slice());
|
21
|
-
}
|
22
|
-
if (msg.type === MessageTypes.MESSAGE_INITIATOR || msg.type === MessageTypes.MESSAGE_RECEIVER) {
|
23
|
-
output.data = uint8ArrayToString(msg.data instanceof Uint8Array ? msg.data : msg.data.slice(), 'base16');
|
24
|
-
}
|
25
|
-
return output;
|
26
|
-
}
|
1
|
+
import { MplexStreamMuxer } from './mplex.js';
|
27
2
|
export class Mplex {
|
28
|
-
constructor(
|
29
|
-
|
30
|
-
this._streamId = 0;
|
31
|
-
this._streams = {
|
32
|
-
/**
|
33
|
-
* Stream to ids map
|
34
|
-
*/
|
35
|
-
initiators: trackedMap({ metrics: options.metrics, component: 'mplex', metric: 'initiatorStreams' }),
|
36
|
-
/**
|
37
|
-
* Stream to ids map
|
38
|
-
*/
|
39
|
-
receivers: trackedMap({ metrics: options.metrics, component: 'mplex', metric: 'receiverStreams' })
|
40
|
-
};
|
41
|
-
this._options = options;
|
42
|
-
/**
|
43
|
-
* An iterable sink
|
44
|
-
*/
|
45
|
-
this.sink = this._createSink();
|
46
|
-
/**
|
47
|
-
* An iterable source
|
48
|
-
*/
|
49
|
-
const source = this._createSource();
|
50
|
-
this._source = source;
|
51
|
-
this.source = source;
|
52
|
-
}
|
53
|
-
/**
|
54
|
-
* Returns a Map of streams and their ids
|
55
|
-
*/
|
56
|
-
get streams() {
|
57
|
-
// Inbound and Outbound streams may have the same ids, so we need to make those unique
|
58
|
-
const streams = [];
|
59
|
-
this._streams.initiators.forEach(stream => {
|
60
|
-
streams.push(stream);
|
61
|
-
});
|
62
|
-
this._streams.receivers.forEach(stream => {
|
63
|
-
streams.push(stream);
|
64
|
-
});
|
65
|
-
return streams;
|
66
|
-
}
|
67
|
-
/**
|
68
|
-
* Initiate a new stream with the given name. If no name is
|
69
|
-
* provided, the id of the stream will be used.
|
70
|
-
*/
|
71
|
-
newStream(name) {
|
72
|
-
const id = this._streamId++;
|
73
|
-
name = name == null ? id.toString() : name.toString();
|
74
|
-
const registry = this._streams.initiators;
|
75
|
-
return this._newStream({ id, name, type: 'initiator', registry });
|
76
|
-
}
|
77
|
-
/**
|
78
|
-
* Called whenever an inbound stream is created
|
79
|
-
*/
|
80
|
-
_newReceiverStream(options) {
|
81
|
-
const { id, name } = options;
|
82
|
-
const registry = this._streams.receivers;
|
83
|
-
return this._newStream({ id, name, type: 'receiver', registry });
|
84
|
-
}
|
85
|
-
_newStream(options) {
|
86
|
-
const { id, name, type, registry } = options;
|
87
|
-
log('new %s stream %s %s', type, id, name);
|
88
|
-
if (registry.has(id)) {
|
89
|
-
throw new Error(`${type} stream ${id} already exists!`);
|
90
|
-
}
|
91
|
-
const send = (msg) => {
|
92
|
-
if (log.enabled) {
|
93
|
-
log('%s stream %s send', type, id, printMessage(msg));
|
94
|
-
}
|
95
|
-
if (msg.type === MessageTypes.NEW_STREAM || msg.type === MessageTypes.MESSAGE_INITIATOR || msg.type === MessageTypes.MESSAGE_RECEIVER) {
|
96
|
-
msg.data = msg.data instanceof Uint8Array ? msg.data : msg.data.slice();
|
97
|
-
}
|
98
|
-
this._source.push(msg);
|
99
|
-
};
|
100
|
-
const onEnd = () => {
|
101
|
-
log('%s stream %s %s ended', type, id, name);
|
102
|
-
registry.delete(id);
|
103
|
-
if (this._options.onStreamEnd != null) {
|
104
|
-
this._options.onStreamEnd(stream);
|
105
|
-
}
|
106
|
-
};
|
107
|
-
const stream = createStream({ id, name, send, type, onEnd, maxMsgSize: this._options.maxMsgSize });
|
108
|
-
registry.set(id, stream);
|
109
|
-
return stream;
|
110
|
-
}
|
111
|
-
/**
|
112
|
-
* Creates a sink with an abortable source. Incoming messages will
|
113
|
-
* also have their size restricted. All messages will be varint decoded.
|
114
|
-
*/
|
115
|
-
_createSink() {
|
116
|
-
const sink = async (source) => {
|
117
|
-
if (this._options.signal != null) {
|
118
|
-
source = abortableSource(source, this._options.signal);
|
119
|
-
}
|
120
|
-
try {
|
121
|
-
await pipe(source, source => each(source, (buf) => {
|
122
|
-
// console.info('incoming', uint8ArrayToString(buf, 'base64'))
|
123
|
-
}), decode, restrictSize(this._options.maxMsgSize), async (source) => {
|
124
|
-
for await (const msg of source) {
|
125
|
-
this._handleIncoming(msg);
|
126
|
-
}
|
127
|
-
});
|
128
|
-
this._source.end();
|
129
|
-
}
|
130
|
-
catch (err) {
|
131
|
-
log('error in sink', err);
|
132
|
-
this._source.end(err); // End the source with an error
|
133
|
-
}
|
134
|
-
};
|
135
|
-
return sink;
|
136
|
-
}
|
137
|
-
/**
|
138
|
-
* Creates a source that restricts outgoing message sizes
|
139
|
-
* and varint encodes them
|
140
|
-
*/
|
141
|
-
_createSource() {
|
142
|
-
const onEnd = (err) => {
|
143
|
-
const { initiators, receivers } = this._streams;
|
144
|
-
// Abort all the things!
|
145
|
-
for (const s of initiators.values()) {
|
146
|
-
s.abort(err);
|
147
|
-
}
|
148
|
-
for (const s of receivers.values()) {
|
149
|
-
s.abort(err);
|
150
|
-
}
|
151
|
-
};
|
152
|
-
const source = pushableV({ onEnd });
|
153
|
-
return Object.assign(encode(source), {
|
154
|
-
push: source.push,
|
155
|
-
end: source.end,
|
156
|
-
return: source.return
|
157
|
-
});
|
3
|
+
constructor() {
|
4
|
+
this.protocol = '/mplex/6.7.0';
|
158
5
|
}
|
159
|
-
|
160
|
-
|
161
|
-
if (log.enabled) {
|
162
|
-
log('incoming message', printMessage(message));
|
163
|
-
}
|
164
|
-
// Create a new stream?
|
165
|
-
if (message.type === MessageTypes.NEW_STREAM) {
|
166
|
-
const stream = this._newReceiverStream({ id, name: uint8ArrayToString(message.data instanceof Uint8Array ? message.data : message.data.slice()) });
|
167
|
-
if (this._options.onIncomingStream != null) {
|
168
|
-
this._options.onIncomingStream(stream);
|
169
|
-
}
|
170
|
-
return;
|
171
|
-
}
|
172
|
-
const list = (type & 1) === 1 ? this._streams.initiators : this._streams.receivers;
|
173
|
-
const stream = list.get(id);
|
174
|
-
if (stream == null) {
|
175
|
-
return log('missing stream %s', id);
|
176
|
-
}
|
177
|
-
switch (type) {
|
178
|
-
case MessageTypes.MESSAGE_INITIATOR:
|
179
|
-
case MessageTypes.MESSAGE_RECEIVER:
|
180
|
-
stream.source.push(message.data.slice());
|
181
|
-
break;
|
182
|
-
case MessageTypes.CLOSE_INITIATOR:
|
183
|
-
case MessageTypes.CLOSE_RECEIVER:
|
184
|
-
stream.close();
|
185
|
-
break;
|
186
|
-
case MessageTypes.RESET_INITIATOR:
|
187
|
-
case MessageTypes.RESET_RECEIVER:
|
188
|
-
stream.reset();
|
189
|
-
break;
|
190
|
-
default:
|
191
|
-
log('unknown message type %s', type);
|
192
|
-
}
|
6
|
+
createStreamMuxer(components, init) {
|
7
|
+
return new MplexStreamMuxer(components, init);
|
193
8
|
}
|
194
9
|
}
|
195
|
-
Mplex.multicodec = '/mplex/6.7.0';
|
196
10
|
//# 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":"
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAM7C,MAAM,OAAO,KAAK;IAAlB;QACS,aAAQ,GAAG,cAAc,CAAA;IAKlC,CAAC;IAHC,iBAAiB,CAAE,UAAsB,EAAE,IAAgB;QACzD,OAAO,IAAI,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;IAC/C,CAAC;CACF"}
|
@@ -0,0 +1,63 @@
|
|
1
|
+
import { Pushable } from 'it-pushable';
|
2
|
+
import { Message } from './message-types.js';
|
3
|
+
import type { Components } from '@libp2p/interfaces/components';
|
4
|
+
import type { Sink } from 'it-stream-types';
|
5
|
+
import type { StreamMuxer, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer';
|
6
|
+
import type { Stream } from '@libp2p/interfaces/connection';
|
7
|
+
export interface MplexStream extends Stream {
|
8
|
+
source: Pushable<Uint8Array>;
|
9
|
+
}
|
10
|
+
export interface MplexInit extends StreamMuxerInit {
|
11
|
+
maxMsgSize?: number;
|
12
|
+
}
|
13
|
+
export declare class MplexStreamMuxer implements StreamMuxer {
|
14
|
+
protocol: string;
|
15
|
+
sink: Sink<Uint8Array>;
|
16
|
+
source: AsyncIterable<Uint8Array>;
|
17
|
+
private _streamId;
|
18
|
+
private readonly _streams;
|
19
|
+
private readonly _init;
|
20
|
+
private readonly _source;
|
21
|
+
constructor(components: Components, init?: MplexInit);
|
22
|
+
init(components: Components): void;
|
23
|
+
/**
|
24
|
+
* Returns a Map of streams and their ids
|
25
|
+
*/
|
26
|
+
get streams(): Stream[];
|
27
|
+
/**
|
28
|
+
* Initiate a new stream with the given name. If no name is
|
29
|
+
* provided, the id of the stream will be used.
|
30
|
+
*/
|
31
|
+
newStream(name?: string): Stream;
|
32
|
+
/**
|
33
|
+
* Called whenever an inbound stream is created
|
34
|
+
*/
|
35
|
+
_newReceiverStream(options: {
|
36
|
+
id: number;
|
37
|
+
name: string;
|
38
|
+
}): MplexStream;
|
39
|
+
_newStream(options: {
|
40
|
+
id: number;
|
41
|
+
name: string;
|
42
|
+
type: 'initiator' | 'receiver';
|
43
|
+
registry: Map<number, MplexStream>;
|
44
|
+
}): MplexStream;
|
45
|
+
/**
|
46
|
+
* Creates a sink with an abortable source. Incoming messages will
|
47
|
+
* also have their size restricted. All messages will be varint decoded.
|
48
|
+
*/
|
49
|
+
_createSink(): Sink<Uint8Array, Promise<void>>;
|
50
|
+
/**
|
51
|
+
* Creates a source that restricts outgoing message sizes
|
52
|
+
* and varint encodes them
|
53
|
+
*/
|
54
|
+
_createSource(): AsyncGenerator<Uint8Array, void, undefined> & {
|
55
|
+
push: (value: Message) => import("it-pushable").PushableV<Message>;
|
56
|
+
end: (err?: Error | undefined) => import("it-pushable").PushableV<Message>;
|
57
|
+
return: () => {
|
58
|
+
done: boolean;
|
59
|
+
};
|
60
|
+
};
|
61
|
+
_handleIncoming(message: Message): void;
|
62
|
+
}
|
63
|
+
//# sourceMappingURL=mplex.d.ts.map
|
@@ -0,0 +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,EAA+C,MAAM,oBAAoB,CAAA;AAKzH,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;AAqB3D,MAAM,WAAW,WAAY,SAAQ,MAAM;IACzC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAA;CAC7B;AAED,MAAM,WAAW,SAAU,SAAQ,eAAe;IAChD,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,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,CAAW;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8D;gBAEzE,UAAU,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,SAAS;IA6BrD,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;IAmCrH;;;OAGG;IACH,WAAW;IA4BX;;;OAGG;IACH,aAAa;;;;;;;IAoBb,eAAe,CAAE,OAAO,EAAE,OAAO;CAgDlC"}
|
@@ -0,0 +1,199 @@
|
|
1
|
+
import { pipe } from 'it-pipe';
|
2
|
+
import { pushableV } from 'it-pushable';
|
3
|
+
import { abortableSource } from 'abortable-iterator';
|
4
|
+
import { encode } from './encode.js';
|
5
|
+
import { decode } from './decode.js';
|
6
|
+
import { restrictSize } from './restrict-size.js';
|
7
|
+
import { MessageTypes, MessageTypeNames, ReceiverMessageTypes, InitiatorMessageTypes } from './message-types.js';
|
8
|
+
import { createStream } from './stream.js';
|
9
|
+
import { toString as uint8ArrayToString } from 'uint8arrays';
|
10
|
+
import { trackedMap } from '@libp2p/tracked-map';
|
11
|
+
import { logger } from '@libp2p/logger';
|
12
|
+
const log = logger('libp2p:mplex');
|
13
|
+
function printMessage(msg) {
|
14
|
+
const output = {
|
15
|
+
...msg,
|
16
|
+
type: `${MessageTypeNames[msg.type]} (${msg.type})`
|
17
|
+
};
|
18
|
+
if (msg.type === MessageTypes.NEW_STREAM) {
|
19
|
+
output.data = uint8ArrayToString(msg.data instanceof Uint8Array ? msg.data : msg.data.slice());
|
20
|
+
}
|
21
|
+
if (msg.type === MessageTypes.MESSAGE_INITIATOR || msg.type === MessageTypes.MESSAGE_RECEIVER) {
|
22
|
+
output.data = uint8ArrayToString(msg.data instanceof Uint8Array ? msg.data : msg.data.slice(), 'base16');
|
23
|
+
}
|
24
|
+
return output;
|
25
|
+
}
|
26
|
+
export class MplexStreamMuxer {
|
27
|
+
constructor(components, init) {
|
28
|
+
this.protocol = '/mplex/6.7.0';
|
29
|
+
init = init ?? {};
|
30
|
+
this._streamId = 0;
|
31
|
+
this._streams = {
|
32
|
+
/**
|
33
|
+
* Stream to ids map
|
34
|
+
*/
|
35
|
+
initiators: trackedMap({ metrics: components.getMetrics(), component: 'mplex', metric: 'initiatorStreams' }),
|
36
|
+
/**
|
37
|
+
* Stream to ids map
|
38
|
+
*/
|
39
|
+
receivers: trackedMap({ metrics: components.getMetrics(), component: 'mplex', metric: 'receiverStreams' })
|
40
|
+
};
|
41
|
+
this._init = init;
|
42
|
+
/**
|
43
|
+
* An iterable sink
|
44
|
+
*/
|
45
|
+
this.sink = this._createSink();
|
46
|
+
/**
|
47
|
+
* An iterable source
|
48
|
+
*/
|
49
|
+
const source = this._createSource();
|
50
|
+
this._source = source;
|
51
|
+
this.source = source;
|
52
|
+
}
|
53
|
+
init(components) {
|
54
|
+
}
|
55
|
+
/**
|
56
|
+
* Returns a Map of streams and their ids
|
57
|
+
*/
|
58
|
+
get streams() {
|
59
|
+
// Inbound and Outbound streams may have the same ids, so we need to make those unique
|
60
|
+
const streams = [];
|
61
|
+
this._streams.initiators.forEach(stream => {
|
62
|
+
streams.push(stream);
|
63
|
+
});
|
64
|
+
this._streams.receivers.forEach(stream => {
|
65
|
+
streams.push(stream);
|
66
|
+
});
|
67
|
+
return streams;
|
68
|
+
}
|
69
|
+
/**
|
70
|
+
* Initiate a new stream with the given name. If no name is
|
71
|
+
* provided, the id of the stream will be used.
|
72
|
+
*/
|
73
|
+
newStream(name) {
|
74
|
+
const id = this._streamId++;
|
75
|
+
name = name == null ? id.toString() : name.toString();
|
76
|
+
const registry = this._streams.initiators;
|
77
|
+
return this._newStream({ id, name, type: 'initiator', registry });
|
78
|
+
}
|
79
|
+
/**
|
80
|
+
* Called whenever an inbound stream is created
|
81
|
+
*/
|
82
|
+
_newReceiverStream(options) {
|
83
|
+
const { id, name } = options;
|
84
|
+
const registry = this._streams.receivers;
|
85
|
+
return this._newStream({ id, name, type: 'receiver', registry });
|
86
|
+
}
|
87
|
+
_newStream(options) {
|
88
|
+
const { id, name, type, registry } = options;
|
89
|
+
log('new %s stream %s %s', type, id, name);
|
90
|
+
if (registry.has(id)) {
|
91
|
+
throw new Error(`${type} stream ${id} already exists!`);
|
92
|
+
}
|
93
|
+
const send = (msg) => {
|
94
|
+
if (log.enabled) {
|
95
|
+
log.trace('%s stream %s send', type, id, printMessage(msg));
|
96
|
+
}
|
97
|
+
if (msg.type === MessageTypes.NEW_STREAM || msg.type === MessageTypes.MESSAGE_INITIATOR || msg.type === MessageTypes.MESSAGE_RECEIVER) {
|
98
|
+
msg.data = msg.data instanceof Uint8Array ? msg.data : msg.data.slice();
|
99
|
+
}
|
100
|
+
this._source.push(msg);
|
101
|
+
};
|
102
|
+
const onEnd = () => {
|
103
|
+
log('%s stream %s %s ended', type, id, name);
|
104
|
+
registry.delete(id);
|
105
|
+
if (this._init.onStreamEnd != null) {
|
106
|
+
this._init.onStreamEnd(stream);
|
107
|
+
}
|
108
|
+
};
|
109
|
+
const stream = createStream({ id, name, send, type, onEnd, maxMsgSize: this._init.maxMsgSize });
|
110
|
+
registry.set(id, stream);
|
111
|
+
return stream;
|
112
|
+
}
|
113
|
+
/**
|
114
|
+
* Creates a sink with an abortable source. Incoming messages will
|
115
|
+
* also have their size restricted. All messages will be varint decoded.
|
116
|
+
*/
|
117
|
+
_createSink() {
|
118
|
+
const sink = async (source) => {
|
119
|
+
if (this._init.signal != null) {
|
120
|
+
source = abortableSource(source, this._init.signal);
|
121
|
+
}
|
122
|
+
try {
|
123
|
+
await pipe(source, decode, restrictSize(this._init.maxMsgSize), async (source) => {
|
124
|
+
for await (const msg of source) {
|
125
|
+
this._handleIncoming(msg);
|
126
|
+
}
|
127
|
+
});
|
128
|
+
this._source.end();
|
129
|
+
}
|
130
|
+
catch (err) {
|
131
|
+
log('error in sink', err);
|
132
|
+
this._source.end(err); // End the source with an error
|
133
|
+
}
|
134
|
+
};
|
135
|
+
return sink;
|
136
|
+
}
|
137
|
+
/**
|
138
|
+
* Creates a source that restricts outgoing message sizes
|
139
|
+
* and varint encodes them
|
140
|
+
*/
|
141
|
+
_createSource() {
|
142
|
+
const onEnd = (err) => {
|
143
|
+
const { initiators, receivers } = this._streams;
|
144
|
+
// Abort all the things!
|
145
|
+
for (const s of initiators.values()) {
|
146
|
+
s.abort(err);
|
147
|
+
}
|
148
|
+
for (const s of receivers.values()) {
|
149
|
+
s.abort(err);
|
150
|
+
}
|
151
|
+
};
|
152
|
+
const source = pushableV({ onEnd });
|
153
|
+
return Object.assign(encode(source), {
|
154
|
+
push: source.push,
|
155
|
+
end: source.end,
|
156
|
+
return: source.return
|
157
|
+
});
|
158
|
+
}
|
159
|
+
_handleIncoming(message) {
|
160
|
+
const { id, type } = message;
|
161
|
+
if (log.enabled) {
|
162
|
+
log.trace('incoming message', printMessage(message));
|
163
|
+
}
|
164
|
+
// Create a new stream?
|
165
|
+
if (message.type === MessageTypes.NEW_STREAM) {
|
166
|
+
const stream = this._newReceiverStream({ id, name: uint8ArrayToString(message.data instanceof Uint8Array ? message.data : message.data.slice()) });
|
167
|
+
if (this._init.onIncomingStream != null) {
|
168
|
+
this._init.onIncomingStream(stream);
|
169
|
+
}
|
170
|
+
return;
|
171
|
+
}
|
172
|
+
const list = (type & 1) === 1 ? this._streams.initiators : this._streams.receivers;
|
173
|
+
const stream = list.get(id);
|
174
|
+
if (stream == null) {
|
175
|
+
log('missing stream %s', id);
|
176
|
+
// send a reset
|
177
|
+
this._source.push({ id, type: InitiatorMessageTypes.RESET });
|
178
|
+
this._source.push({ id, type: ReceiverMessageTypes.RESET });
|
179
|
+
return;
|
180
|
+
}
|
181
|
+
switch (type) {
|
182
|
+
case MessageTypes.MESSAGE_INITIATOR:
|
183
|
+
case MessageTypes.MESSAGE_RECEIVER:
|
184
|
+
stream.source.push(message.data.slice());
|
185
|
+
break;
|
186
|
+
case MessageTypes.CLOSE_INITIATOR:
|
187
|
+
case MessageTypes.CLOSE_RECEIVER:
|
188
|
+
stream.close();
|
189
|
+
break;
|
190
|
+
case MessageTypes.RESET_INITIATOR:
|
191
|
+
case MessageTypes.RESET_RECEIVER:
|
192
|
+
stream.reset();
|
193
|
+
break;
|
194
|
+
default:
|
195
|
+
log('unknown message type %s', type);
|
196
|
+
}
|
197
|
+
}
|
198
|
+
}
|
199
|
+
//# sourceMappingURL=mplex.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"mplex.js","sourceRoot":"","sources":["../../src/mplex.ts"],"names":[],"mappings":"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"}
|
package/dist/src/stream.d.ts
CHANGED
package/dist/src/stream.js
CHANGED
@@ -28,7 +28,7 @@ export function createStream(options) {
|
|
28
28
|
return;
|
29
29
|
}
|
30
30
|
sourceEnded = true;
|
31
|
-
log('%s stream %s source end', type, streamName, err);
|
31
|
+
log.trace('%s stream %s source end', type, streamName, err);
|
32
32
|
if (err != null && endErr == null) {
|
33
33
|
endErr = err;
|
34
34
|
}
|
@@ -44,7 +44,7 @@ export function createStream(options) {
|
|
44
44
|
return;
|
45
45
|
}
|
46
46
|
sinkEnded = true;
|
47
|
-
log('%s stream %s sink end - err: %o', type, streamName, err);
|
47
|
+
log.trace('%s stream %s sink end - err: %o', type, streamName, err);
|
48
48
|
if (err != null && endErr == null) {
|
49
49
|
endErr = err;
|
50
50
|
}
|
@@ -62,7 +62,7 @@ export function createStream(options) {
|
|
62
62
|
},
|
63
63
|
// Close for reading and writing (local error)
|
64
64
|
abort: (err) => {
|
65
|
-
log('%s stream %s abort', type, streamName, err);
|
65
|
+
log.trace('%s stream %s abort', type, streamName, err);
|
66
66
|
// End the source with the passed error
|
67
67
|
stream.source.end(err);
|
68
68
|
abortController.abort();
|
@@ -112,15 +112,15 @@ export function createStream(options) {
|
|
112
112
|
}
|
113
113
|
// Send no more data if this stream was remotely reset
|
114
114
|
if (err.code === ERR_MPLEX_STREAM_RESET) {
|
115
|
-
log('%s stream %s reset', type, name);
|
115
|
+
log.trace('%s stream %s reset', type, name);
|
116
116
|
}
|
117
117
|
else {
|
118
|
-
log('%s stream %s error', type, name, err);
|
118
|
+
log.trace('%s stream %s error', type, name, err);
|
119
119
|
try {
|
120
120
|
send({ id, type: Types.RESET });
|
121
121
|
}
|
122
122
|
catch (err) {
|
123
|
-
log('%s stream %s error sending reset', type, name, err);
|
123
|
+
log.trace('%s stream %s error sending reset', type, name, err);
|
124
124
|
}
|
125
125
|
}
|
126
126
|
stream.source.end(err);
|
@@ -131,7 +131,7 @@ export function createStream(options) {
|
|
131
131
|
send({ id, type: Types.CLOSE });
|
132
132
|
}
|
133
133
|
catch (err) {
|
134
|
-
log('%s stream %s error sending close', type, name, err);
|
134
|
+
log.trace('%s stream %s error sending close', type, name, err);
|
135
135
|
}
|
136
136
|
onSinkEnd();
|
137
137
|
},
|
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;AAWvD,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,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,yBAAyB,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,CAAA;
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/stream.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@libp2p/mplex",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.4",
|
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",
|
@@ -126,44 +126,44 @@
|
|
126
126
|
]
|
127
127
|
},
|
128
128
|
"scripts": {
|
129
|
+
"clean": "aegir clean",
|
129
130
|
"lint": "aegir lint",
|
130
131
|
"dep-check": "aegir dep-check",
|
131
|
-
"build": "
|
132
|
-
"
|
133
|
-
"test": "aegir test -
|
134
|
-
"test:chrome": "
|
135
|
-
"test:
|
136
|
-
"test:firefox": "
|
137
|
-
"test:
|
138
|
-
"test:
|
139
|
-
"
|
140
|
-
"release": "semantic-release"
|
132
|
+
"build": "aegir build",
|
133
|
+
"test": "aegir test",
|
134
|
+
"test:chrome": "aegir test -t browser --cov",
|
135
|
+
"test:chrome-webworker": "aegir test -t webworker",
|
136
|
+
"test:firefox": "aegir test -t browser -- --browser firefox",
|
137
|
+
"test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
|
138
|
+
"test:node": "aegir test -t node --cov",
|
139
|
+
"test:electron-main": "aegir test -t electron-main",
|
140
|
+
"release": "aegir release"
|
141
141
|
},
|
142
142
|
"dependencies": {
|
143
|
-
"@libp2p/logger": "^1.
|
144
|
-
"@libp2p/tracked-map": "^1.0.
|
143
|
+
"@libp2p/logger": "^1.1.3",
|
144
|
+
"@libp2p/tracked-map": "^1.0.5",
|
145
145
|
"abortable-iterator": "^4.0.2",
|
146
146
|
"any-signal": "^3.0.0",
|
147
147
|
"err-code": "^3.0.1",
|
148
148
|
"it-pipe": "^2.0.3",
|
149
149
|
"it-pushable": "^2.0.1",
|
150
150
|
"it-stream-types": "^1.0.4",
|
151
|
-
"uint8arraylist": "^1.
|
151
|
+
"uint8arraylist": "^1.4.0",
|
152
|
+
"uint8arrays": "^3.0.0",
|
152
153
|
"varint": "^6.0.0"
|
153
154
|
},
|
154
155
|
"devDependencies": {
|
155
|
-
"@libp2p/interface-compliance-tests": "^1.
|
156
|
-
"@libp2p/interfaces": "^1.
|
156
|
+
"@libp2p/interface-compliance-tests": "^1.1.32",
|
157
|
+
"@libp2p/interfaces": "^1.3.31",
|
157
158
|
"@types/varint": "^6.0.0",
|
158
|
-
"aegir": "^
|
159
|
-
"cborg": "^1.
|
160
|
-
"iso-random-stream": "^2.0.
|
159
|
+
"aegir": "^37.0.10",
|
160
|
+
"cborg": "^1.8.1",
|
161
|
+
"iso-random-stream": "^2.0.2",
|
161
162
|
"it-all": "^1.0.6",
|
162
163
|
"it-drain": "^1.0.5",
|
163
164
|
"it-foreach": "^0.1.1",
|
164
165
|
"it-map": "^1.0.6",
|
165
166
|
"p-defer": "^4.0.0",
|
166
|
-
"random-int": "^3.0.0"
|
167
|
-
"uint8arrays": "^3.0.0"
|
167
|
+
"random-int": "^3.0.0"
|
168
168
|
}
|
169
169
|
}
|
package/src/index.ts
CHANGED
@@ -1,257 +1,15 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
3
|
-
import {
|
4
|
-
import { encode } from './encode.js'
|
5
|
-
import { decode } from './decode.js'
|
6
|
-
import { restrictSize } from './restrict-size.js'
|
7
|
-
import { MessageTypes, MessageTypeNames, Message } from './message-types.js'
|
8
|
-
import { createStream } from './stream.js'
|
9
|
-
import { toString as uint8ArrayToString } from 'uint8arrays'
|
10
|
-
import { trackedMap } from '@libp2p/tracked-map'
|
11
|
-
import { logger } from '@libp2p/logger'
|
12
|
-
import type { Sink } from 'it-stream-types'
|
13
|
-
import type { Muxer, MuxerOptions } from '@libp2p/interfaces/stream-muxer'
|
14
|
-
import type { Stream } from '@libp2p/interfaces/connection'
|
15
|
-
import type { ComponentMetricsTracker } from '@libp2p/interfaces/metrics'
|
16
|
-
import each from 'it-foreach'
|
1
|
+
import type { Components } from '@libp2p/interfaces/components'
|
2
|
+
import type { StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer'
|
3
|
+
import { MplexStreamMuxer } from './mplex.js'
|
17
4
|
|
18
|
-
|
19
|
-
|
20
|
-
function printMessage (msg: Message) {
|
21
|
-
const output: any = {
|
22
|
-
...msg,
|
23
|
-
type: `${MessageTypeNames[msg.type]} (${msg.type})`
|
24
|
-
}
|
25
|
-
|
26
|
-
if (msg.type === MessageTypes.NEW_STREAM) {
|
27
|
-
output.data = uint8ArrayToString(msg.data instanceof Uint8Array ? msg.data : msg.data.slice())
|
28
|
-
}
|
29
|
-
|
30
|
-
if (msg.type === MessageTypes.MESSAGE_INITIATOR || msg.type === MessageTypes.MESSAGE_RECEIVER) {
|
31
|
-
output.data = uint8ArrayToString(msg.data instanceof Uint8Array ? msg.data : msg.data.slice(), 'base16')
|
32
|
-
}
|
33
|
-
|
34
|
-
return output
|
35
|
-
}
|
36
|
-
|
37
|
-
export interface MplexStream extends Stream {
|
38
|
-
source: Pushable<Uint8Array>
|
39
|
-
}
|
40
|
-
|
41
|
-
export interface MplexOptions extends MuxerOptions {
|
5
|
+
export interface MplexInit extends StreamMuxerInit {
|
42
6
|
maxMsgSize?: number
|
43
|
-
metrics?: ComponentMetricsTracker
|
44
7
|
}
|
45
8
|
|
46
|
-
export class Mplex implements
|
47
|
-
|
48
|
-
|
49
|
-
public sink: Sink<Uint8Array>
|
50
|
-
public source: AsyncIterable<Uint8Array>
|
51
|
-
|
52
|
-
private _streamId: number
|
53
|
-
private readonly _streams: { initiators: Map<number, MplexStream>, receivers: Map<number, MplexStream> }
|
54
|
-
private readonly _options: MplexOptions
|
55
|
-
private readonly _source: { push: (val: Message) => void, end: (err?: Error) => void }
|
56
|
-
|
57
|
-
constructor (options?: MplexOptions) {
|
58
|
-
options = options ?? {}
|
59
|
-
|
60
|
-
this._streamId = 0
|
61
|
-
this._streams = {
|
62
|
-
/**
|
63
|
-
* Stream to ids map
|
64
|
-
*/
|
65
|
-
initiators: trackedMap<number, MplexStream>({ metrics: options.metrics, component: 'mplex', metric: 'initiatorStreams' }),
|
66
|
-
/**
|
67
|
-
* Stream to ids map
|
68
|
-
*/
|
69
|
-
receivers: trackedMap<number, MplexStream>({ metrics: options.metrics, component: 'mplex', metric: 'receiverStreams' })
|
70
|
-
}
|
71
|
-
this._options = options
|
72
|
-
|
73
|
-
/**
|
74
|
-
* An iterable sink
|
75
|
-
*/
|
76
|
-
this.sink = this._createSink()
|
77
|
-
|
78
|
-
/**
|
79
|
-
* An iterable source
|
80
|
-
*/
|
81
|
-
const source = this._createSource()
|
82
|
-
this._source = source
|
83
|
-
this.source = source
|
84
|
-
}
|
85
|
-
|
86
|
-
/**
|
87
|
-
* Returns a Map of streams and their ids
|
88
|
-
*/
|
89
|
-
get streams () {
|
90
|
-
// Inbound and Outbound streams may have the same ids, so we need to make those unique
|
91
|
-
const streams: Stream[] = []
|
92
|
-
this._streams.initiators.forEach(stream => {
|
93
|
-
streams.push(stream)
|
94
|
-
})
|
95
|
-
this._streams.receivers.forEach(stream => {
|
96
|
-
streams.push(stream)
|
97
|
-
})
|
98
|
-
return streams
|
99
|
-
}
|
100
|
-
|
101
|
-
/**
|
102
|
-
* Initiate a new stream with the given name. If no name is
|
103
|
-
* provided, the id of the stream will be used.
|
104
|
-
*/
|
105
|
-
newStream (name?: string): Stream {
|
106
|
-
const id = this._streamId++
|
107
|
-
name = name == null ? id.toString() : name.toString()
|
108
|
-
const registry = this._streams.initiators
|
109
|
-
return this._newStream({ id, name, type: 'initiator', registry })
|
110
|
-
}
|
111
|
-
|
112
|
-
/**
|
113
|
-
* Called whenever an inbound stream is created
|
114
|
-
*/
|
115
|
-
_newReceiverStream (options: { id: number, name: string }) {
|
116
|
-
const { id, name } = options
|
117
|
-
const registry = this._streams.receivers
|
118
|
-
return this._newStream({ id, name, type: 'receiver', registry })
|
119
|
-
}
|
120
|
-
|
121
|
-
_newStream (options: { id: number, name: string, type: 'initiator' | 'receiver', registry: Map<number, MplexStream> }) {
|
122
|
-
const { id, name, type, registry } = options
|
123
|
-
|
124
|
-
log('new %s stream %s %s', type, id, name)
|
125
|
-
|
126
|
-
if (registry.has(id)) {
|
127
|
-
throw new Error(`${type} stream ${id} already exists!`)
|
128
|
-
}
|
129
|
-
|
130
|
-
const send = (msg: Message) => {
|
131
|
-
if (log.enabled) {
|
132
|
-
log('%s stream %s send', type, id, printMessage(msg))
|
133
|
-
}
|
134
|
-
|
135
|
-
if (msg.type === MessageTypes.NEW_STREAM || msg.type === MessageTypes.MESSAGE_INITIATOR || msg.type === MessageTypes.MESSAGE_RECEIVER) {
|
136
|
-
msg.data = msg.data instanceof Uint8Array ? msg.data : msg.data.slice()
|
137
|
-
}
|
138
|
-
|
139
|
-
this._source.push(msg)
|
140
|
-
}
|
141
|
-
|
142
|
-
const onEnd = () => {
|
143
|
-
log('%s stream %s %s ended', type, id, name)
|
144
|
-
registry.delete(id)
|
145
|
-
|
146
|
-
if (this._options.onStreamEnd != null) {
|
147
|
-
this._options.onStreamEnd(stream)
|
148
|
-
}
|
149
|
-
}
|
150
|
-
|
151
|
-
const stream = createStream({ id, name, send, type, onEnd, maxMsgSize: this._options.maxMsgSize })
|
152
|
-
registry.set(id, stream)
|
153
|
-
return stream
|
154
|
-
}
|
155
|
-
|
156
|
-
/**
|
157
|
-
* Creates a sink with an abortable source. Incoming messages will
|
158
|
-
* also have their size restricted. All messages will be varint decoded.
|
159
|
-
*/
|
160
|
-
_createSink () {
|
161
|
-
const sink: Sink<Uint8Array> = async source => {
|
162
|
-
if (this._options.signal != null) {
|
163
|
-
source = abortableSource(source, this._options.signal)
|
164
|
-
}
|
165
|
-
|
166
|
-
try {
|
167
|
-
await pipe(
|
168
|
-
source,
|
169
|
-
source => each(source, (buf) => {
|
170
|
-
// console.info('incoming', uint8ArrayToString(buf, 'base64'))
|
171
|
-
}),
|
172
|
-
decode,
|
173
|
-
restrictSize(this._options.maxMsgSize),
|
174
|
-
async source => {
|
175
|
-
for await (const msg of source) {
|
176
|
-
this._handleIncoming(msg)
|
177
|
-
}
|
178
|
-
}
|
179
|
-
)
|
180
|
-
|
181
|
-
this._source.end()
|
182
|
-
} catch (err: any) {
|
183
|
-
log('error in sink', err)
|
184
|
-
this._source.end(err) // End the source with an error
|
185
|
-
}
|
186
|
-
}
|
187
|
-
|
188
|
-
return sink
|
189
|
-
}
|
190
|
-
|
191
|
-
/**
|
192
|
-
* Creates a source that restricts outgoing message sizes
|
193
|
-
* and varint encodes them
|
194
|
-
*/
|
195
|
-
_createSource () {
|
196
|
-
const onEnd = (err?: Error) => {
|
197
|
-
const { initiators, receivers } = this._streams
|
198
|
-
// Abort all the things!
|
199
|
-
for (const s of initiators.values()) {
|
200
|
-
s.abort(err)
|
201
|
-
}
|
202
|
-
for (const s of receivers.values()) {
|
203
|
-
s.abort(err)
|
204
|
-
}
|
205
|
-
}
|
206
|
-
const source = pushableV<Message>({ onEnd })
|
207
|
-
|
208
|
-
return Object.assign(encode(source), {
|
209
|
-
push: source.push,
|
210
|
-
end: source.end,
|
211
|
-
return: source.return
|
212
|
-
})
|
213
|
-
}
|
214
|
-
|
215
|
-
_handleIncoming (message: Message) {
|
216
|
-
const { id, type } = message
|
217
|
-
|
218
|
-
if (log.enabled) {
|
219
|
-
log('incoming message', printMessage(message))
|
220
|
-
}
|
221
|
-
|
222
|
-
// Create a new stream?
|
223
|
-
if (message.type === MessageTypes.NEW_STREAM) {
|
224
|
-
const stream = this._newReceiverStream({ id, name: uint8ArrayToString(message.data instanceof Uint8Array ? message.data : message.data.slice()) })
|
225
|
-
|
226
|
-
if (this._options.onIncomingStream != null) {
|
227
|
-
this._options.onIncomingStream(stream)
|
228
|
-
}
|
229
|
-
|
230
|
-
return
|
231
|
-
}
|
232
|
-
|
233
|
-
const list = (type & 1) === 1 ? this._streams.initiators : this._streams.receivers
|
234
|
-
const stream = list.get(id)
|
235
|
-
|
236
|
-
if (stream == null) {
|
237
|
-
return log('missing stream %s', id)
|
238
|
-
}
|
9
|
+
export class Mplex implements StreamMuxerFactory {
|
10
|
+
public protocol = '/mplex/6.7.0'
|
239
11
|
|
240
|
-
|
241
|
-
|
242
|
-
case MessageTypes.MESSAGE_RECEIVER:
|
243
|
-
stream.source.push(message.data.slice())
|
244
|
-
break
|
245
|
-
case MessageTypes.CLOSE_INITIATOR:
|
246
|
-
case MessageTypes.CLOSE_RECEIVER:
|
247
|
-
stream.close()
|
248
|
-
break
|
249
|
-
case MessageTypes.RESET_INITIATOR:
|
250
|
-
case MessageTypes.RESET_RECEIVER:
|
251
|
-
stream.reset()
|
252
|
-
break
|
253
|
-
default:
|
254
|
-
log('unknown message type %s', type)
|
255
|
-
}
|
12
|
+
createStreamMuxer (components: Components, init?: MplexInit) {
|
13
|
+
return new MplexStreamMuxer(components, init)
|
256
14
|
}
|
257
15
|
}
|
package/src/mplex.ts
ADDED
@@ -0,0 +1,262 @@
|
|
1
|
+
import { pipe } from 'it-pipe'
|
2
|
+
import { Pushable, pushableV } from 'it-pushable'
|
3
|
+
import { abortableSource } from 'abortable-iterator'
|
4
|
+
import { encode } from './encode.js'
|
5
|
+
import { decode } from './decode.js'
|
6
|
+
import { restrictSize } from './restrict-size.js'
|
7
|
+
import { MessageTypes, MessageTypeNames, Message, ReceiverMessageTypes, InitiatorMessageTypes } from './message-types.js'
|
8
|
+
import { createStream } from './stream.js'
|
9
|
+
import { toString as uint8ArrayToString } from 'uint8arrays'
|
10
|
+
import { trackedMap } from '@libp2p/tracked-map'
|
11
|
+
import { logger } from '@libp2p/logger'
|
12
|
+
import type { Components } from '@libp2p/interfaces/components'
|
13
|
+
import type { Sink } from 'it-stream-types'
|
14
|
+
import type { StreamMuxer, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer'
|
15
|
+
import type { Stream } from '@libp2p/interfaces/connection'
|
16
|
+
|
17
|
+
const log = logger('libp2p:mplex')
|
18
|
+
|
19
|
+
function printMessage (msg: Message) {
|
20
|
+
const output: any = {
|
21
|
+
...msg,
|
22
|
+
type: `${MessageTypeNames[msg.type]} (${msg.type})`
|
23
|
+
}
|
24
|
+
|
25
|
+
if (msg.type === MessageTypes.NEW_STREAM) {
|
26
|
+
output.data = uint8ArrayToString(msg.data instanceof Uint8Array ? msg.data : msg.data.slice())
|
27
|
+
}
|
28
|
+
|
29
|
+
if (msg.type === MessageTypes.MESSAGE_INITIATOR || msg.type === MessageTypes.MESSAGE_RECEIVER) {
|
30
|
+
output.data = uint8ArrayToString(msg.data instanceof Uint8Array ? msg.data : msg.data.slice(), 'base16')
|
31
|
+
}
|
32
|
+
|
33
|
+
return output
|
34
|
+
}
|
35
|
+
|
36
|
+
export interface MplexStream extends Stream {
|
37
|
+
source: Pushable<Uint8Array>
|
38
|
+
}
|
39
|
+
|
40
|
+
export interface MplexInit extends StreamMuxerInit {
|
41
|
+
maxMsgSize?: number
|
42
|
+
}
|
43
|
+
|
44
|
+
export class MplexStreamMuxer implements StreamMuxer {
|
45
|
+
public protocol = '/mplex/6.7.0'
|
46
|
+
|
47
|
+
public sink: Sink<Uint8Array>
|
48
|
+
public source: AsyncIterable<Uint8Array>
|
49
|
+
|
50
|
+
private _streamId: number
|
51
|
+
private readonly _streams: { initiators: Map<number, MplexStream>, receivers: Map<number, MplexStream> }
|
52
|
+
private readonly _init: MplexInit
|
53
|
+
private readonly _source: { push: (val: Message) => void, end: (err?: Error) => void }
|
54
|
+
|
55
|
+
constructor (components: Components, init?: MplexInit) {
|
56
|
+
init = init ?? {}
|
57
|
+
|
58
|
+
this._streamId = 0
|
59
|
+
this._streams = {
|
60
|
+
/**
|
61
|
+
* Stream to ids map
|
62
|
+
*/
|
63
|
+
initiators: trackedMap<number, MplexStream>({ metrics: components.getMetrics(), component: 'mplex', metric: 'initiatorStreams' }),
|
64
|
+
/**
|
65
|
+
* Stream to ids map
|
66
|
+
*/
|
67
|
+
receivers: trackedMap<number, MplexStream>({ metrics: components.getMetrics(), component: 'mplex', metric: 'receiverStreams' })
|
68
|
+
}
|
69
|
+
this._init = init
|
70
|
+
|
71
|
+
/**
|
72
|
+
* An iterable sink
|
73
|
+
*/
|
74
|
+
this.sink = this._createSink()
|
75
|
+
|
76
|
+
/**
|
77
|
+
* An iterable source
|
78
|
+
*/
|
79
|
+
const source = this._createSource()
|
80
|
+
this._source = source
|
81
|
+
this.source = source
|
82
|
+
}
|
83
|
+
|
84
|
+
init (components: Components) {
|
85
|
+
|
86
|
+
}
|
87
|
+
|
88
|
+
/**
|
89
|
+
* Returns a Map of streams and their ids
|
90
|
+
*/
|
91
|
+
get streams () {
|
92
|
+
// Inbound and Outbound streams may have the same ids, so we need to make those unique
|
93
|
+
const streams: Stream[] = []
|
94
|
+
this._streams.initiators.forEach(stream => {
|
95
|
+
streams.push(stream)
|
96
|
+
})
|
97
|
+
this._streams.receivers.forEach(stream => {
|
98
|
+
streams.push(stream)
|
99
|
+
})
|
100
|
+
return streams
|
101
|
+
}
|
102
|
+
|
103
|
+
/**
|
104
|
+
* Initiate a new stream with the given name. If no name is
|
105
|
+
* provided, the id of the stream will be used.
|
106
|
+
*/
|
107
|
+
newStream (name?: string): Stream {
|
108
|
+
const id = this._streamId++
|
109
|
+
name = name == null ? id.toString() : name.toString()
|
110
|
+
const registry = this._streams.initiators
|
111
|
+
return this._newStream({ id, name, type: 'initiator', registry })
|
112
|
+
}
|
113
|
+
|
114
|
+
/**
|
115
|
+
* Called whenever an inbound stream is created
|
116
|
+
*/
|
117
|
+
_newReceiverStream (options: { id: number, name: string }) {
|
118
|
+
const { id, name } = options
|
119
|
+
const registry = this._streams.receivers
|
120
|
+
return this._newStream({ id, name, type: 'receiver', registry })
|
121
|
+
}
|
122
|
+
|
123
|
+
_newStream (options: { id: number, name: string, type: 'initiator' | 'receiver', registry: Map<number, MplexStream> }) {
|
124
|
+
const { id, name, type, registry } = options
|
125
|
+
|
126
|
+
log('new %s stream %s %s', type, id, name)
|
127
|
+
|
128
|
+
if (registry.has(id)) {
|
129
|
+
throw new Error(`${type} stream ${id} already exists!`)
|
130
|
+
}
|
131
|
+
|
132
|
+
const send = (msg: Message) => {
|
133
|
+
if (log.enabled) {
|
134
|
+
log.trace('%s stream %s send', type, id, printMessage(msg))
|
135
|
+
}
|
136
|
+
|
137
|
+
if (msg.type === MessageTypes.NEW_STREAM || msg.type === MessageTypes.MESSAGE_INITIATOR || msg.type === MessageTypes.MESSAGE_RECEIVER) {
|
138
|
+
msg.data = msg.data instanceof Uint8Array ? msg.data : msg.data.slice()
|
139
|
+
}
|
140
|
+
|
141
|
+
this._source.push(msg)
|
142
|
+
}
|
143
|
+
|
144
|
+
const onEnd = () => {
|
145
|
+
log('%s stream %s %s ended', type, id, name)
|
146
|
+
registry.delete(id)
|
147
|
+
|
148
|
+
if (this._init.onStreamEnd != null) {
|
149
|
+
this._init.onStreamEnd(stream)
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
const stream = createStream({ id, name, send, type, onEnd, maxMsgSize: this._init.maxMsgSize })
|
154
|
+
registry.set(id, stream)
|
155
|
+
return stream
|
156
|
+
}
|
157
|
+
|
158
|
+
/**
|
159
|
+
* Creates a sink with an abortable source. Incoming messages will
|
160
|
+
* also have their size restricted. All messages will be varint decoded.
|
161
|
+
*/
|
162
|
+
_createSink () {
|
163
|
+
const sink: Sink<Uint8Array> = async source => {
|
164
|
+
if (this._init.signal != null) {
|
165
|
+
source = abortableSource(source, this._init.signal)
|
166
|
+
}
|
167
|
+
|
168
|
+
try {
|
169
|
+
await pipe(
|
170
|
+
source,
|
171
|
+
decode,
|
172
|
+
restrictSize(this._init.maxMsgSize),
|
173
|
+
async source => {
|
174
|
+
for await (const msg of source) {
|
175
|
+
this._handleIncoming(msg)
|
176
|
+
}
|
177
|
+
}
|
178
|
+
)
|
179
|
+
|
180
|
+
this._source.end()
|
181
|
+
} catch (err: any) {
|
182
|
+
log('error in sink', err)
|
183
|
+
this._source.end(err) // End the source with an error
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
return sink
|
188
|
+
}
|
189
|
+
|
190
|
+
/**
|
191
|
+
* Creates a source that restricts outgoing message sizes
|
192
|
+
* and varint encodes them
|
193
|
+
*/
|
194
|
+
_createSource () {
|
195
|
+
const onEnd = (err?: Error) => {
|
196
|
+
const { initiators, receivers } = this._streams
|
197
|
+
// Abort all the things!
|
198
|
+
for (const s of initiators.values()) {
|
199
|
+
s.abort(err)
|
200
|
+
}
|
201
|
+
for (const s of receivers.values()) {
|
202
|
+
s.abort(err)
|
203
|
+
}
|
204
|
+
}
|
205
|
+
const source = pushableV<Message>({ onEnd })
|
206
|
+
|
207
|
+
return Object.assign(encode(source), {
|
208
|
+
push: source.push,
|
209
|
+
end: source.end,
|
210
|
+
return: source.return
|
211
|
+
})
|
212
|
+
}
|
213
|
+
|
214
|
+
_handleIncoming (message: Message) {
|
215
|
+
const { id, type } = message
|
216
|
+
|
217
|
+
if (log.enabled) {
|
218
|
+
log.trace('incoming message', printMessage(message))
|
219
|
+
}
|
220
|
+
|
221
|
+
// Create a new stream?
|
222
|
+
if (message.type === MessageTypes.NEW_STREAM) {
|
223
|
+
const stream = this._newReceiverStream({ id, name: uint8ArrayToString(message.data instanceof Uint8Array ? message.data : message.data.slice()) })
|
224
|
+
|
225
|
+
if (this._init.onIncomingStream != null) {
|
226
|
+
this._init.onIncomingStream(stream)
|
227
|
+
}
|
228
|
+
|
229
|
+
return
|
230
|
+
}
|
231
|
+
|
232
|
+
const list = (type & 1) === 1 ? this._streams.initiators : this._streams.receivers
|
233
|
+
const stream = list.get(id)
|
234
|
+
|
235
|
+
if (stream == null) {
|
236
|
+
log('missing stream %s', id)
|
237
|
+
|
238
|
+
// send a reset
|
239
|
+
this._source.push({ id, type: InitiatorMessageTypes.RESET })
|
240
|
+
this._source.push({ id, type: ReceiverMessageTypes.RESET })
|
241
|
+
|
242
|
+
return
|
243
|
+
}
|
244
|
+
|
245
|
+
switch (type) {
|
246
|
+
case MessageTypes.MESSAGE_INITIATOR:
|
247
|
+
case MessageTypes.MESSAGE_RECEIVER:
|
248
|
+
stream.source.push(message.data.slice())
|
249
|
+
break
|
250
|
+
case MessageTypes.CLOSE_INITIATOR:
|
251
|
+
case MessageTypes.CLOSE_RECEIVER:
|
252
|
+
stream.close()
|
253
|
+
break
|
254
|
+
case MessageTypes.RESET_INITIATOR:
|
255
|
+
case MessageTypes.RESET_RECEIVER:
|
256
|
+
stream.reset()
|
257
|
+
break
|
258
|
+
default:
|
259
|
+
log('unknown message type %s', type)
|
260
|
+
}
|
261
|
+
}
|
262
|
+
}
|
package/src/stream.ts
CHANGED
@@ -10,7 +10,7 @@ import { logger } from '@libp2p/logger'
|
|
10
10
|
import type { Message } from './message-types.js'
|
11
11
|
import type { Timeline } from '@libp2p/interfaces/connection'
|
12
12
|
import type { Source } from 'it-stream-types'
|
13
|
-
import type { MplexStream } from './
|
13
|
+
import type { MplexStream } from './mplex.js'
|
14
14
|
|
15
15
|
const log = logger('libp2p:mplex:stream')
|
16
16
|
|
@@ -49,7 +49,7 @@ export function createStream (options: Options): MplexStream {
|
|
49
49
|
}
|
50
50
|
|
51
51
|
sourceEnded = true
|
52
|
-
log('%s stream %s source end', type, streamName, err)
|
52
|
+
log.trace('%s stream %s source end', type, streamName, err)
|
53
53
|
|
54
54
|
if (err != null && endErr == null) {
|
55
55
|
endErr = err
|
@@ -70,7 +70,7 @@ export function createStream (options: Options): MplexStream {
|
|
70
70
|
}
|
71
71
|
|
72
72
|
sinkEnded = true
|
73
|
-
log('%s stream %s sink end - err: %o', type, streamName, err)
|
73
|
+
log.trace('%s stream %s sink end - err: %o', type, streamName, err)
|
74
74
|
|
75
75
|
if (err != null && endErr == null) {
|
76
76
|
endErr = err
|
@@ -92,7 +92,7 @@ export function createStream (options: Options): MplexStream {
|
|
92
92
|
},
|
93
93
|
// Close for reading and writing (local error)
|
94
94
|
abort: (err?: Error) => {
|
95
|
-
log('%s stream %s abort', type, streamName, err)
|
95
|
+
log.trace('%s stream %s abort', type, streamName, err)
|
96
96
|
// End the source with the passed error
|
97
97
|
stream.source.end(err)
|
98
98
|
abortController.abort()
|
@@ -148,13 +148,13 @@ export function createStream (options: Options): MplexStream {
|
|
148
148
|
|
149
149
|
// Send no more data if this stream was remotely reset
|
150
150
|
if (err.code === ERR_MPLEX_STREAM_RESET) {
|
151
|
-
log('%s stream %s reset', type, name)
|
151
|
+
log.trace('%s stream %s reset', type, name)
|
152
152
|
} else {
|
153
|
-
log('%s stream %s error', type, name, err)
|
153
|
+
log.trace('%s stream %s error', type, name, err)
|
154
154
|
try {
|
155
155
|
send({ id, type: Types.RESET })
|
156
156
|
} catch (err) {
|
157
|
-
log('%s stream %s error sending reset', type, name, err)
|
157
|
+
log.trace('%s stream %s error sending reset', type, name, err)
|
158
158
|
}
|
159
159
|
}
|
160
160
|
|
@@ -166,7 +166,7 @@ export function createStream (options: Options): MplexStream {
|
|
166
166
|
try {
|
167
167
|
send({ id, type: Types.CLOSE })
|
168
168
|
} catch (err) {
|
169
|
-
log('%s stream %s error sending close', type, name, err)
|
169
|
+
log.trace('%s stream %s error sending close', type, name, err)
|
170
170
|
}
|
171
171
|
|
172
172
|
onSinkEnd()
|