'use strict'; const Constant = require('../const'); const byteBuffer = require('./byte_buffer'); const Long = require('long'); /** * 0 1 2 4 12 * +---------+---------+-------------------+-------------------------------------------------------------------------------+ * | version | req/res | reserved | request id | * +---------------------------------------+---------------------------------------+---------------------------------------+ * | timeout | connection object length | application object length | * +---------------------------------------+-------------------+-------------------+---------------------------------------+ * | conn object (JSON format) ... | app object | * +-----------------------------------------------------------+ | * | ... | * +-----------------------------------------------------------------------------------------------------------------------+ * * packet protocol: * (1B): protocol version * (1B): req/res * (2B): reserved * (8B): request id * (4B): timeout * (4B): connection object length * (4B): application object length * -------------------------------- * conn object (JSON format) * -------------------------------- * app object */ class Packet { /** * cluster protocol packet * * @param {Object} options * - @param {Number} id - The identifier * - @param {Number} type - req/res * - @param {Number} timeout - The timeout * - @param {Object} connObj - connection object * - @param {Buffer} data - app data * @constructor */ constructor(options) { this.id = options.id; this.type = options.type; this.timeout = options.timeout; this.connObj = options.connObj; this.data = typeof options.data === 'string' ? Buffer.from(options.data) : options.data; } get isResponse() { return this.type === Constant.RESPONSE; } encode() { const header = Buffer.from([ Constant.VERSION, this.type, 0, 0 ]); const connBuf = Buffer.from(JSON.stringify(this.connObj)); const appLen = this.data ? this.data.length : 0; byteBuffer.reset(); byteBuffer.put(header); byteBuffer.putLong(this.id); byteBuffer.putInt(this.timeout); byteBuffer.putInt(connBuf.length); byteBuffer.putInt(appLen); byteBuffer.put(connBuf); if (appLen) { byteBuffer.put(this.data); } return byteBuffer.array(); } static decode(buf) { const isResponse = buf[1] === Constant.RESPONSE; const id = new Long( buf.readInt32BE(8), // low, high buf.readInt32BE(4) ).toNumber(); const timeout = buf.readInt32BE(12); const connLength = buf.readInt32BE(16); const appLength = buf.readInt32BE(20); const connBuf = Buffer.alloc(connLength); buf.copy(connBuf, 0, 24, 24 + connLength); const connObj = JSON.parse(connBuf); let data; if (appLength) { data = Buffer.alloc(appLength); buf.copy(data, 0, 24 + connLength, 24 + connLength + appLength); } return { id, isResponse, timeout, connObj, data, }; } } module.exports = Packet;