@stoplight/moleculer
Version:
Fast & powerful microservices framework for Node.JS
82 lines (67 loc) • 1.82 kB
JavaScript
/*
* moleculer
* Copyright (c) 2018 MoleculerJS (https://github.com/moleculerjs/moleculer)
* MIT Licensed
*/
;
const Writable = require("stream").Writable;
const { resolvePacketType } = require("./constants");
/**
* TCP packet parser
*/
class Parser extends Writable {
/**
* Create an instance of Parser
*
* @param {*} options
*/
constructor(options, maxPacketSize) {
super(options);
this.maxPacketSize = maxPacketSize;
this.buf = null;
}
_write(chunk, encoding, cb) {
let packet = chunk;
if (this.buf && this.buf.length > 0) {
// There is previous chunk, concatenate them
packet = Buffer.concat([this.buf, chunk]);
this.buf = null;
}
// Find all messages from the chunk
while (packet.length > 0) {
if (packet.length < 6) {
// Too short, waiting for the next chunk
this.buf = Buffer.from(packet);
return cb();
}
if (this.maxPacketSize && packet.length > this.maxPacketSize) {
return cb(
new Error(
`Incoming packet is larger than the 'maxPacketSize' limit (${packet.length} > ${this.maxPacketSize})!`
)
);
}
// Check the CRC
const crc = packet[1] ^ packet[2] ^ packet[3] ^ packet[4] ^ packet[5];
if (crc !== packet[0]) {
return cb(new Error("Invalid packet CRC! " + crc));
}
const length = packet.readInt32BE(1);
// The chunk contain a message
if (packet.length >= length) {
const msg = packet.slice(6, length);
const type = resolvePacketType(packet[5]);
this.emit("data", type, msg);
// Remove processed message from incoming data
packet = packet.slice(length);
} else {
// The chunk is not contain the whole message.
// Waiting for the next one.
this.buf = Buffer.from(packet);
return cb();
}
}
cb();
}
}
module.exports = Parser;