xud
Version:
Exchange Union Daemon
206 lines • 9.67 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* tslint:disable brace-style */
const events_1 = require("events");
const errors_1 = __importDefault(require("./errors"));
const Framer_1 = __importDefault(require("./Framer"));
const packets_1 = require("./packets");
const Packet_1 = require("./packets/Packet");
const packetTypes = __importStar(require("./packets/types"));
/** Wire protocol msg parser */
let Parser = /** @class */ (() => {
class Parser extends events_1.EventEmitter {
constructor(framer, msgHeaderLength = Framer_1.default.MSG_HEADER_LENGTH, maxBufferSize = Parser.MAX_BUFFER_SIZE) {
super();
this.framer = framer;
this.msgHeaderLength = msgHeaderLength;
this.maxBufferSize = maxBufferSize;
this.pending = [];
this.waiting = 0;
this.waitingHeader = 0;
this.setEncryptionKey = (key) => {
this.encryptionKey = key;
this.msgHeaderLength = Framer_1.default.ENCRYPTED_MSG_HEADER_LENGTH;
};
this.feed = (chunk) => {
// verify that total size isn't exceeding
const totalSize = this.getTotalSize(chunk);
if (totalSize > this.maxBufferSize) {
this.error(errors_1.default.PARSER_MAX_BUFFER_SIZE_EXCEEDED(totalSize));
return;
}
// reading through a split message
if (this.waiting) {
this.read(this.waiting, chunk);
}
// reading through a message which is split on the header
else if (this.waitingHeader) {
this.pending.push(chunk);
const data = Buffer.concat(this.pending);
const length = this.parseLength(data);
if (!length) {
return;
}
this.pending = [];
this.read(length + this.msgHeaderLength, data);
}
// starting to read a new message which is split on the header
else if (chunk.length < this.msgHeaderLength) {
this.pending.push(chunk);
this.waitingHeader = this.msgHeaderLength - chunk.length;
}
// starting to read a new message
else {
const length = this.parseLength(chunk);
if (!length) {
return;
}
this.read(length + this.msgHeaderLength, chunk);
}
};
this.read = (length, chunk) => {
this.pending.push(chunk.slice(0, length));
// message isn't complete
if (length > chunk.length) {
this.waiting = length - chunk.length;
}
// chunk is finalizing the msg
else {
this.parseMessage(this.pending);
this.resetBuffer();
// chunk is containing more messages
if (length < chunk.length) {
this.feed(chunk.slice(length));
}
}
};
this.getTotalSize = (chunk) => {
const current = this.pending
.map(buffer => buffer.length)
.reduce((acc, curr) => acc + curr, 0);
return current + chunk.length;
};
this.resetBuffer = () => {
this.waiting = 0;
this.waitingHeader = 0;
this.pending = [];
};
this.parseLength = (data) => {
try {
return this.framer.parseLength(data, !!this.encryptionKey);
}
catch (err) {
this.error(err);
return 0;
}
};
this.parseMessage = (chunks) => {
try {
const msg = Buffer.concat(chunks);
const { header, packet } = this.framer.unframe(msg, this.encryptionKey);
const parsedPacket = this.parsePacket(header, Uint8Array.from(packet));
this.emit('packet', parsedPacket);
}
catch (err) {
this.error(err);
}
};
this.parsePacket = (header, payload) => {
let packetOrPbObj;
switch (header.type) {
case packets_1.PacketType.SessionInit:
packetOrPbObj = packetTypes.SessionInitPacket.deserialize(payload);
break;
case packets_1.PacketType.SessionAck:
packetOrPbObj = packetTypes.SessionAckPacket.deserialize(payload);
break;
case packets_1.PacketType.NodeStateUpdate:
packetOrPbObj = packetTypes.NodeStateUpdatePacket.deserialize(payload);
break;
case packets_1.PacketType.Disconnecting:
packetOrPbObj = packetTypes.DisconnectingPacket.deserialize(payload);
break;
case packets_1.PacketType.Ping:
packetOrPbObj = packetTypes.PingPacket.deserialize(payload);
break;
case packets_1.PacketType.Pong:
packetOrPbObj = packetTypes.PongPacket.deserialize(payload);
break;
case packets_1.PacketType.Order:
packetOrPbObj = packetTypes.OrderPacket.deserialize(payload);
break;
case packets_1.PacketType.OrderInvalidation:
packetOrPbObj = packetTypes.OrderInvalidationPacket.deserialize(payload);
break;
case packets_1.PacketType.GetOrders:
packetOrPbObj = packetTypes.GetOrdersPacket.deserialize(payload);
break;
case packets_1.PacketType.Orders:
packetOrPbObj = packetTypes.OrdersPacket.deserialize(payload);
break;
case packets_1.PacketType.GetNodes:
packetOrPbObj = packetTypes.GetNodesPacket.deserialize(payload);
break;
case packets_1.PacketType.Nodes:
packetOrPbObj = packetTypes.NodesPacket.deserialize(payload);
break;
case packets_1.PacketType.SanitySwap:
packetOrPbObj = packetTypes.SanitySwapInitPacket.deserialize(payload);
break;
case packets_1.PacketType.SanitySwapAck:
packetOrPbObj = packetTypes.SanitySwapAckPacket.deserialize(payload);
break;
case packets_1.PacketType.SwapRequest:
packetOrPbObj = packetTypes.SwapRequestPacket.deserialize(payload);
break;
case packets_1.PacketType.SwapAccepted:
packetOrPbObj = packetTypes.SwapAcceptedPacket.deserialize(payload);
break;
case packets_1.PacketType.SwapFailed:
packetOrPbObj = packetTypes.SwapFailedPacket.deserialize(payload);
break;
default:
throw errors_1.default.PARSER_UNKNOWN_PACKET_TYPE(header.type.toString());
}
if (!Packet_1.isPacket(packetOrPbObj)) {
throw errors_1.default.PARSER_INVALID_PACKET(`${packets_1.PacketType[header.type]} ${JSON.stringify(packetOrPbObj)}`);
}
const packet = packetOrPbObj;
if (header.checksum && header.checksum !== packet.checksum()) {
throw errors_1.default.PARSER_DATA_INTEGRITY_ERR(`${packets_1.PacketType[header.type]} ${JSON.stringify(packet)}`);
}
return packet;
};
this.error = (err) => {
this.emit('error', err);
this.resetBuffer();
};
}
}
Parser.MAX_BUFFER_SIZE = (4 * 1024 * 1024); // in bytes
return Parser;
})();
exports.default = Parser;
//# sourceMappingURL=Parser.js.map