123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- import { Emitter } from "@socket.io/component-emitter";
- import { deconstructPacket, reconstructPacket } from "./binary.js";
- import { isBinary, hasBinary } from "./is-binary.js";
- import debugModule from "debug";
- const debug = debugModule("socket.io-parser");
- const RESERVED_EVENTS = [
- "connect",
- "connect_error",
- "disconnect",
- "disconnecting",
- "newListener",
- "removeListener",
- ];
- export const protocol = 5;
- export var PacketType;
- (function (PacketType) {
- PacketType[PacketType["CONNECT"] = 0] = "CONNECT";
- PacketType[PacketType["DISCONNECT"] = 1] = "DISCONNECT";
- PacketType[PacketType["EVENT"] = 2] = "EVENT";
- PacketType[PacketType["ACK"] = 3] = "ACK";
- PacketType[PacketType["CONNECT_ERROR"] = 4] = "CONNECT_ERROR";
- PacketType[PacketType["BINARY_EVENT"] = 5] = "BINARY_EVENT";
- PacketType[PacketType["BINARY_ACK"] = 6] = "BINARY_ACK";
- })(PacketType || (PacketType = {}));
- export class Encoder {
-
- constructor(replacer) {
- this.replacer = replacer;
- }
-
- encode(obj) {
- debug("encoding packet %j", obj);
- if (obj.type === PacketType.EVENT || obj.type === PacketType.ACK) {
- if (hasBinary(obj)) {
- return this.encodeAsBinary({
- type: obj.type === PacketType.EVENT
- ? PacketType.BINARY_EVENT
- : PacketType.BINARY_ACK,
- nsp: obj.nsp,
- data: obj.data,
- id: obj.id,
- });
- }
- }
- return [this.encodeAsString(obj)];
- }
-
- encodeAsString(obj) {
-
- let str = "" + obj.type;
-
- if (obj.type === PacketType.BINARY_EVENT ||
- obj.type === PacketType.BINARY_ACK) {
- str += obj.attachments + "-";
- }
-
-
- if (obj.nsp && "/" !== obj.nsp) {
- str += obj.nsp + ",";
- }
-
- if (null != obj.id) {
- str += obj.id;
- }
-
- if (null != obj.data) {
- str += JSON.stringify(obj.data, this.replacer);
- }
- debug("encoded %j as %s", obj, str);
- return str;
- }
-
- encodeAsBinary(obj) {
- const deconstruction = deconstructPacket(obj);
- const pack = this.encodeAsString(deconstruction.packet);
- const buffers = deconstruction.buffers;
- buffers.unshift(pack);
- return buffers;
- }
- }
- function isObject(value) {
- return Object.prototype.toString.call(value) === "[object Object]";
- }
- export class Decoder extends Emitter {
-
- constructor(reviver) {
- super();
- this.reviver = reviver;
- }
-
- add(obj) {
- let packet;
- if (typeof obj === "string") {
- if (this.reconstructor) {
- throw new Error("got plaintext data when reconstructing a packet");
- }
- packet = this.decodeString(obj);
- const isBinaryEvent = packet.type === PacketType.BINARY_EVENT;
- if (isBinaryEvent || packet.type === PacketType.BINARY_ACK) {
- packet.type = isBinaryEvent ? PacketType.EVENT : PacketType.ACK;
-
- this.reconstructor = new BinaryReconstructor(packet);
-
- if (packet.attachments === 0) {
- super.emitReserved("decoded", packet);
- }
- }
- else {
-
- super.emitReserved("decoded", packet);
- }
- }
- else if (isBinary(obj) || obj.base64) {
-
- if (!this.reconstructor) {
- throw new Error("got binary data when not reconstructing a packet");
- }
- else {
- packet = this.reconstructor.takeBinaryData(obj);
- if (packet) {
-
- this.reconstructor = null;
- super.emitReserved("decoded", packet);
- }
- }
- }
- else {
- throw new Error("Unknown type: " + obj);
- }
- }
-
- decodeString(str) {
- let i = 0;
-
- const p = {
- type: Number(str.charAt(0)),
- };
- if (PacketType[p.type] === undefined) {
- throw new Error("unknown packet type " + p.type);
- }
-
- if (p.type === PacketType.BINARY_EVENT ||
- p.type === PacketType.BINARY_ACK) {
- const start = i + 1;
- while (str.charAt(++i) !== "-" && i != str.length) { }
- const buf = str.substring(start, i);
- if (buf != Number(buf) || str.charAt(i) !== "-") {
- throw new Error("Illegal attachments");
- }
- p.attachments = Number(buf);
- }
-
- if ("/" === str.charAt(i + 1)) {
- const start = i + 1;
- while (++i) {
- const c = str.charAt(i);
- if ("," === c)
- break;
- if (i === str.length)
- break;
- }
- p.nsp = str.substring(start, i);
- }
- else {
- p.nsp = "/";
- }
-
- const next = str.charAt(i + 1);
- if ("" !== next && Number(next) == next) {
- const start = i + 1;
- while (++i) {
- const c = str.charAt(i);
- if (null == c || Number(c) != c) {
- --i;
- break;
- }
- if (i === str.length)
- break;
- }
- p.id = Number(str.substring(start, i + 1));
- }
-
- if (str.charAt(++i)) {
- const payload = this.tryParse(str.substr(i));
- if (Decoder.isPayloadValid(p.type, payload)) {
- p.data = payload;
- }
- else {
- throw new Error("invalid payload");
- }
- }
- debug("decoded %s as %j", str, p);
- return p;
- }
- tryParse(str) {
- try {
- return JSON.parse(str, this.reviver);
- }
- catch (e) {
- return false;
- }
- }
- static isPayloadValid(type, payload) {
- switch (type) {
- case PacketType.CONNECT:
- return isObject(payload);
- case PacketType.DISCONNECT:
- return payload === undefined;
- case PacketType.CONNECT_ERROR:
- return typeof payload === "string" || isObject(payload);
- case PacketType.EVENT:
- case PacketType.BINARY_EVENT:
- return (Array.isArray(payload) &&
- (typeof payload[0] === "number" ||
- (typeof payload[0] === "string" &&
- RESERVED_EVENTS.indexOf(payload[0]) === -1)));
- case PacketType.ACK:
- case PacketType.BINARY_ACK:
- return Array.isArray(payload);
- }
- }
-
- destroy() {
- if (this.reconstructor) {
- this.reconstructor.finishedReconstruction();
- this.reconstructor = null;
- }
- }
- }
- class BinaryReconstructor {
- constructor(packet) {
- this.packet = packet;
- this.buffers = [];
- this.reconPack = packet;
- }
-
- takeBinaryData(binData) {
- this.buffers.push(binData);
- if (this.buffers.length === this.reconPack.attachments) {
-
- const packet = reconstructPacket(this.reconPack, this.buffers);
- this.finishedReconstruction();
- return packet;
- }
- return null;
- }
-
- finishedReconstruction() {
- this.reconPack = null;
- this.buffers = [];
- }
- }
|