123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.decodePayload = exports.decodePacket = exports.encodePayload = exports.encodePacket = exports.protocol = void 0;
- exports.createPacketEncoderStream = createPacketEncoderStream;
- exports.createPacketDecoderStream = createPacketDecoderStream;
- const encodePacket_js_1 = require("./encodePacket.js");
- Object.defineProperty(exports, "encodePacket", { enumerable: true, get: function () { return encodePacket_js_1.encodePacket; } });
- const decodePacket_js_1 = require("./decodePacket.js");
- Object.defineProperty(exports, "decodePacket", { enumerable: true, get: function () { return decodePacket_js_1.decodePacket; } });
- const commons_js_1 = require("./commons.js");
- const SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text
- const encodePayload = (packets, callback) => {
- // some packets may be added to the array while encoding, so the initial length must be saved
- const length = packets.length;
- const encodedPackets = new Array(length);
- let count = 0;
- packets.forEach((packet, i) => {
- // force base64 encoding for binary packets
- (0, encodePacket_js_1.encodePacket)(packet, false, (encodedPacket) => {
- encodedPackets[i] = encodedPacket;
- if (++count === length) {
- callback(encodedPackets.join(SEPARATOR));
- }
- });
- });
- };
- exports.encodePayload = encodePayload;
- const decodePayload = (encodedPayload, binaryType) => {
- const encodedPackets = encodedPayload.split(SEPARATOR);
- const packets = [];
- for (let i = 0; i < encodedPackets.length; i++) {
- const decodedPacket = (0, decodePacket_js_1.decodePacket)(encodedPackets[i], binaryType);
- packets.push(decodedPacket);
- if (decodedPacket.type === "error") {
- break;
- }
- }
- return packets;
- };
- exports.decodePayload = decodePayload;
- function createPacketEncoderStream() {
- return new TransformStream({
- transform(packet, controller) {
- (0, encodePacket_js_1.encodePacketToBinary)(packet, (encodedPacket) => {
- const payloadLength = encodedPacket.length;
- let header;
- // inspired by the WebSocket format: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#decoding_payload_length
- if (payloadLength < 126) {
- header = new Uint8Array(1);
- new DataView(header.buffer).setUint8(0, payloadLength);
- }
- else if (payloadLength < 65536) {
- header = new Uint8Array(3);
- const view = new DataView(header.buffer);
- view.setUint8(0, 126);
- view.setUint16(1, payloadLength);
- }
- else {
- header = new Uint8Array(9);
- const view = new DataView(header.buffer);
- view.setUint8(0, 127);
- view.setBigUint64(1, BigInt(payloadLength));
- }
- // first bit indicates whether the payload is plain text (0) or binary (1)
- if (packet.data && typeof packet.data !== "string") {
- header[0] |= 0x80;
- }
- controller.enqueue(header);
- controller.enqueue(encodedPacket);
- });
- },
- });
- }
- let TEXT_DECODER;
- function totalLength(chunks) {
- return chunks.reduce((acc, chunk) => acc + chunk.length, 0);
- }
- function concatChunks(chunks, size) {
- if (chunks[0].length === size) {
- return chunks.shift();
- }
- const buffer = new Uint8Array(size);
- let j = 0;
- for (let i = 0; i < size; i++) {
- buffer[i] = chunks[0][j++];
- if (j === chunks[0].length) {
- chunks.shift();
- j = 0;
- }
- }
- if (chunks.length && j < chunks[0].length) {
- chunks[0] = chunks[0].slice(j);
- }
- return buffer;
- }
- function createPacketDecoderStream(maxPayload, binaryType) {
- if (!TEXT_DECODER) {
- TEXT_DECODER = new TextDecoder();
- }
- const chunks = [];
- let state = 0 /* State.READ_HEADER */;
- let expectedLength = -1;
- let isBinary = false;
- return new TransformStream({
- transform(chunk, controller) {
- chunks.push(chunk);
- while (true) {
- if (state === 0 /* State.READ_HEADER */) {
- if (totalLength(chunks) < 1) {
- break;
- }
- const header = concatChunks(chunks, 1);
- isBinary = (header[0] & 0x80) === 0x80;
- expectedLength = header[0] & 0x7f;
- if (expectedLength < 126) {
- state = 3 /* State.READ_PAYLOAD */;
- }
- else if (expectedLength === 126) {
- state = 1 /* State.READ_EXTENDED_LENGTH_16 */;
- }
- else {
- state = 2 /* State.READ_EXTENDED_LENGTH_64 */;
- }
- }
- else if (state === 1 /* State.READ_EXTENDED_LENGTH_16 */) {
- if (totalLength(chunks) < 2) {
- break;
- }
- const headerArray = concatChunks(chunks, 2);
- expectedLength = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length).getUint16(0);
- state = 3 /* State.READ_PAYLOAD */;
- }
- else if (state === 2 /* State.READ_EXTENDED_LENGTH_64 */) {
- if (totalLength(chunks) < 8) {
- break;
- }
- const headerArray = concatChunks(chunks, 8);
- const view = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length);
- const n = view.getUint32(0);
- if (n > Math.pow(2, 53 - 32) - 1) {
- // the maximum safe integer in JavaScript is 2^53 - 1
- controller.enqueue(commons_js_1.ERROR_PACKET);
- break;
- }
- expectedLength = n * Math.pow(2, 32) + view.getUint32(4);
- state = 3 /* State.READ_PAYLOAD */;
- }
- else {
- if (totalLength(chunks) < expectedLength) {
- break;
- }
- const data = concatChunks(chunks, expectedLength);
- controller.enqueue((0, decodePacket_js_1.decodePacket)(isBinary ? data : TEXT_DECODER.decode(data), binaryType));
- state = 0 /* State.READ_HEADER */;
- }
- if (expectedLength === 0 || expectedLength > maxPayload) {
- controller.enqueue(commons_js_1.ERROR_PACKET);
- break;
- }
- }
- },
- });
- }
- exports.protocol = 4;
|