You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
2.7 KiB

import { isBinary } from "./is-binary.js";
/**
* Replaces every Buffer | ArrayBuffer | Blob | File in packet with a numbered placeholder.
*
* @param {Object} packet - socket.io event packet
* @return {Object} with deconstructed packet and list of buffers
* @public
*/
export function deconstructPacket(packet) {
const buffers = [];
const packetData = packet.data;
const pack = packet;
pack.data = _deconstructPacket(packetData, buffers);
pack.attachments = buffers.length; // number of binary 'attachments'
return { packet: pack, buffers: buffers };
}
function _deconstructPacket(data, buffers) {
if (!data)
return data;
if (isBinary(data)) {
const placeholder = { _placeholder: true, num: buffers.length };
buffers.push(data);
return placeholder;
}
else if (Array.isArray(data)) {
const newData = new Array(data.length);
for (let i = 0; i < data.length; i++) {
newData[i] = _deconstructPacket(data[i], buffers);
}
return newData;
}
else if (typeof data === "object" && !(data instanceof Date)) {
const newData = {};
for (const key in data) {
if (Object.prototype.hasOwnProperty.call(data, key)) {
newData[key] = _deconstructPacket(data[key], buffers);
}
}
return newData;
}
return data;
}
/**
* Reconstructs a binary packet from its placeholder packet and buffers
*
* @param {Object} packet - event packet with placeholders
* @param {Array} buffers - binary buffers to put in placeholder positions
* @return {Object} reconstructed packet
* @public
*/
export function reconstructPacket(packet, buffers) {
packet.data = _reconstructPacket(packet.data, buffers);
delete packet.attachments; // no longer useful
return packet;
}
function _reconstructPacket(data, buffers) {
if (!data)
return data;
if (data && data._placeholder === true) {
const isIndexValid = typeof data.num === "number" &&
data.num >= 0 &&
data.num < buffers.length;
if (isIndexValid) {
return buffers[data.num]; // appropriate buffer (should be natural order anyway)
}
else {
throw new Error("illegal attachments");
}
}
else if (Array.isArray(data)) {
for (let i = 0; i < data.length; i++) {
data[i] = _reconstructPacket(data[i], buffers);
}
}
else if (typeof data === "object") {
for (const key in data) {
if (Object.prototype.hasOwnProperty.call(data, key)) {
data[key] = _reconstructPacket(data[key], buffers);
}
}
}
return data;
}