tools/scripts/check_server/clientnet.js
aozhiwei e886664e02 1
2022-04-28 12:36:32 +08:00

137 lines
3.6 KiB
JavaScript

const protobuf = require('protobufjs');
const ws = require('nodejs-websocket');
class ClientNet {
constructor(url, protoPbFile, msgIdPbFile) {
this.url = url;
this.conn = null;
this.protoPbFile = protoPbFile;
this.msgIdPbFile = msgIdPbFile;
this.protoPb = null;
this.msgIdPb = null;
this.cmMsgId = null;
this.smMsgId = null;
this.recvBuf = Buffer.alloc(0);
this.uniqId = 1000;
this.msgHandlerMap = new Map();
}
async init() {
{
const {err, root} = await protobuf.load(this.protoPbFile);
this.protoPb = root;
}
{
const {err, root} = await protobuf.load(this.msgIdPbFile);
this.msgIdPb = root;
this.cmMsgId = this.msgIdPb.lookup('CMMessageId_e');
this.smMsgId = this.msgIdPb.lookup('SMMessageId_e');
}
}
async connect() {
this.conn = await ws.connect(this.url);
this.on('binary', this.#onReceive.bind(this));
}
on(eventName, ...args) {
this.conn.on(eventName, ...args);
}
async #onReceive(inStream) {
inStream.on('readable', async () => {
//console.log('inStream.readable');
const newData = inStream.read();
if (newData) {
this.recvBuf = Buffer.concat([this.recvBuf, newData]);
await this.#onParsePacket();
}
});
inStream.on('end', () => {
//console.log('inStream.end', this.recvBuf.length);
});
inStream.on('close', () => {
//console.log('inStream.close');
});
}
async #onParsePacket() {
while (this.recvBuf.length > 12) {
const msgSize = this.recvBuf.readUInt16LE(0);
const msgId = this.recvBuf.readUInt16LE(2);
const seqId = this.recvBuf.readUInt32LE(4);
const magicCode = this.recvBuf.readUInt16LE(8);
const ext = this.recvBuf.readUInt16LE(10);
if (this.recvBuf.length >= 12 + msgSize) {
await this.#processMsg(msgId, this.recvBuf.slice(12, 12 + msgSize));
this.recvBuf = this.recvBuf.slice(12 + msgSize);
}
}
}
async #processMsg(msgId, buff) {
const handlers = this.msgHandlerMap.get(msgId);
if (handlers) {
let msg = null;
handlers.forEach((value, key) => {
if (!msg) {
msg = value.msgType.decode(buff);
}
value.cb(msg);
});
}
}
registerMsgHandle(msgName, cb) {
const msgType = this.protoPb.lookupType(msgName);
const msgId = this.smMsgId.values['_' + msgName];
if (!msgId) {
return null;
}
const handle = {
msgId: msgId,
msgName: msgName,
msgType: msgType,
cb: cb,
uniqId: ++this.uniqId}
;
if (!this.msgHandlerMap.has(msgId)) {
this.msgHandlerMap.set(msgId, new Map([
[handle.uniqId, handle]
]));
} else {
this.msgHandlerMap[msgId].set(handle.uniqId, handle);
}
return handle;
}
unRegisterMsgHandle(handle) {
if (this.msgHandlerMap.has(handle.msgId)) {
if (this.msgHandlerMap[handle.msgId].has(handle.uniqId)) {
this.msgHandlerMap[handle.msgId].delete(handle.uniqId);
}
}
}
async sendMsg(name, msg) {
const msgType = this.protoPb.lookupType(name);
const msgId = this.cmMsgId.values['_' + name];
const msgPb = msgType.create(msg);
const msgBuf = msgType.encode(msg).finish();
let buf = Buffer.alloc(12);
buf.writeInt16LE(msgBuf.length, 0);
buf.writeInt16LE(msgId, 2);
buf.writeInt32LE(0, 4);
buf.writeUInt8('K'.charCodeAt(0), 8);
buf.writeUInt8('S'.charCodeAt(0), 9);
buf.writeInt16LE(0, 10);
this.conn.sendBinary(Buffer.concat([buf, msgBuf]));
console.log(name, msg);
}
}
module.exports = ClientNet;