int-cli
Version:
INT is the new generation of bottom-up created system of IoT and blockchain
163 lines (162 loc) • 6.43 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const package_1 = require("./package");
const events_1 = require("events");
const error_code_1 = require("../error_code");
const msgpack = require('msgpack-lite');
const assert = require('assert');
var READER_STATE;
(function (READER_STATE) {
READER_STATE[READER_STATE["error"] = -1] = "error";
READER_STATE[READER_STATE["wait"] = 0] = "wait";
READER_STATE[READER_STATE["header"] = 1] = "header";
READER_STATE[READER_STATE["body"] = 2] = "body";
READER_STATE[READER_STATE["data"] = 3] = "data";
})(READER_STATE || (READER_STATE = {}));
var READER_EVENT;
(function (READER_EVENT) {
READER_EVENT["error"] = "error";
READER_EVENT["pkg"] = "pkg";
})(READER_EVENT = exports.READER_EVENT || (exports.READER_EVENT = {}));
class PackageStreamReader extends events_1.EventEmitter {
constructor() {
super();
this.m_stateInfo = {
state: READER_STATE.wait,
pkg: new package_1.Package(),
pendingLength: 0,
pending: [],
};
this.m_connection = null;
this.m_dataListener = (buffers) => {
let stateInfo = this.m_stateInfo;
if (stateInfo.state === READER_STATE.wait) {
stateInfo.pkg = new package_1.Package();
stateInfo.pending = [];
stateInfo.state = READER_STATE.header;
stateInfo.pendingLength = 0;
}
this._pushPending(buffers);
do {
if (stateInfo.state === READER_STATE.wait) {
stateInfo.pkg = new package_1.Package();
stateInfo.state = READER_STATE.header;
}
if (stateInfo.state === READER_STATE.header) {
let headerBuffers = this._popPending(package_1.Package.headerLength);
if (!headerBuffers) {
break;
}
let headerBuffer = Buffer.concat(headerBuffers);
let header = stateInfo.pkg.header;
let offset = 0;
header.magic = headerBuffer.readUInt16BE(offset);
offset += 2;
if (header.magic !== package_1.Package.magic) {
stateInfo.state = READER_STATE.error;
setImmediate(() => this.emit('error', error_code_1.ErrorCode.RESULT_PARSE_ERROR, 'magic' // 标记一下触发error的字段
));
}
header.version = headerBuffer.readUInt16BE(offset);
offset += 2;
header.flags = headerBuffer.readUInt16BE(offset);
offset += 2;
header.cmdType = headerBuffer.readUInt16BE(offset);
offset += 2;
header.totalLength = headerBuffer.readUInt32BE(offset);
offset += 4;
header.bodyLength = headerBuffer.readUInt32BE(offset);
offset += 4;
stateInfo.state = READER_STATE.body;
}
if (stateInfo.state === READER_STATE.body) {
if (stateInfo.pkg.header.bodyLength) {
let bodyBuffers = this._popPending(stateInfo.pkg.header.bodyLength);
if (!bodyBuffers) {
break;
}
let bodyBuffer = Buffer.concat(bodyBuffers);
Object.assign(stateInfo.pkg.body, msgpack.decode(bodyBuffer));
}
stateInfo.state = READER_STATE.data;
}
if (stateInfo.state === READER_STATE.data) {
let pkg;
if (stateInfo.pkg.dataLength) {
let dataBuffers = this._popPending(stateInfo.pkg.dataLength);
if (!dataBuffers) {
break;
}
stateInfo.pkg.data.push(...dataBuffers);
pkg = stateInfo.pkg;
}
else {
pkg = stateInfo.pkg;
}
stateInfo.state = READER_STATE.wait;
if (pkg) {
pkg.data[0] = Buffer.concat(pkg.data);
setImmediate(() => { this.emit(READER_EVENT.pkg, pkg); });
}
}
} while (stateInfo.pendingLength);
};
}
_clearPending() {
this.m_stateInfo.pendingLength = 0;
this.m_stateInfo.pending = [];
}
_popPending(length) {
let stateInfo = this.m_stateInfo;
if (length > stateInfo.pendingLength) {
return null;
}
let next = length;
let spliceTo = 0;
let popLast = null;
for (; spliceTo < stateInfo.pending.length; ++spliceTo) {
let buffer = stateInfo.pending[spliceTo];
if (buffer.length === next) {
spliceTo += 1;
break;
}
else if (buffer.length > next) {
popLast = Buffer.from(buffer.buffer, buffer.offset, next);
stateInfo.pending[spliceTo] = Buffer.from(buffer.buffer, buffer.offset + next, buffer.length - next);
break;
}
else {
next -= buffer.length;
}
}
let pop = stateInfo.pending.splice(0, spliceTo);
if (popLast) {
pop.push(popLast);
}
stateInfo.pendingLength -= length;
return pop;
}
_pushPending(buffers) {
for (let buffer of buffers) {
this.m_stateInfo.pending.push(buffer);
this.m_stateInfo.pendingLength += buffer.length;
}
}
start(connection) {
if (this.m_connection) {
return;
}
this.m_connection = connection;
this.m_connection.on('data', this.m_dataListener);
}
stop() {
if (this.m_connection) {
this.m_connection.removeListener('data', this.m_dataListener);
this.m_connection = null;
}
}
close() {
this.stop();
}
}
exports.PackageStreamReader = PackageStreamReader;