@libp2p/mplex
Version:
JavaScript implementation of https://github.com/libp2p/mplex
87 lines • 3.06 kB
JavaScript
import { AbstractStream } from '@libp2p/utils';
import { Uint8ArrayList } from 'uint8arraylist';
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
import { MAX_MSG_SIZE } from "./decode.js";
import { encode } from "./encode.js";
import { InitiatorMessageTypes, ReceiverMessageTypes } from "./message-types.js";
export class MplexStream extends AbstractStream {
streamId;
types;
maxDataSize;
muxer;
constructor(init) {
super(init);
this.types = init.direction === 'outbound' ? InitiatorMessageTypes : ReceiverMessageTypes;
this.maxDataSize = init.maxDataSize;
this.muxer = init.muxer;
this.streamId = parseInt(this.id.substring(1));
if (init.direction === 'outbound') {
// open the stream on the receiver end. do this in a microtask so the
// stream gets added to the streams array by the muxer superclass before
// we send the NEW_STREAM message, otherwise we create a race condition
// whereby we can receive the stream messages before the stream is added
// to the streams list
queueMicrotask(() => {
this.muxer.send(encode({
id: this.streamId,
type: InitiatorMessageTypes.NEW_STREAM,
data: new Uint8ArrayList(uint8ArrayFromString(this.id))
}));
});
}
}
sendData(data) {
const list = new Uint8ArrayList();
const sentBytes = data.byteLength;
while (data.byteLength > 0) {
const toSend = Math.min(data.byteLength, this.maxDataSize);
const slice = data.sublist(0, toSend);
data = data.sublist(toSend);
list.append(encode({
id: this.streamId,
type: this.types.MESSAGE,
data: slice
}));
}
return {
sentBytes,
canSendMore: this.muxer.send(list)
};
}
sendReset() {
return this.muxer.send(encode({
id: this.streamId,
type: this.types.RESET
}));
}
async sendCloseWrite(options) {
this.muxer.send(encode({
id: this.streamId,
type: this.types.CLOSE
}));
options?.signal?.throwIfAborted();
}
async sendCloseRead(options) {
options?.signal?.throwIfAborted();
// mplex does not support close read, only close write
}
sendPause() {
// mplex does not support backpressure
}
sendResume() {
// mplex does not support backpressure
}
}
export function createStream(options) {
const { id, muxer, direction, maxMsgSize = MAX_MSG_SIZE } = options;
return new MplexStream({
...options,
id: direction === 'outbound' ? (`i${id}`) : `r${id}`,
direction,
maxDataSize: maxMsgSize,
muxer,
log: options.log.newScope(`${direction}:${id}`),
protocol: ''
});
}
//# sourceMappingURL=stream.js.map