From 13cd59f9a89b9f355fb1ce9108516cca427dc3c5 Mon Sep 17 00:00:00 2001 From: aozhiwei Date: Mon, 17 Apr 2023 19:50:25 +0800 Subject: [PATCH] 1 --- server/tools/robot/kcpclient/app.js | 8 + server/tools/robot/kcpclient/clientnet.js | 319 ++++++++++++++++++++++ server/tools/robot/kcpclient/package.json | 12 + server/tools/robot/kcpclient/testcase.js | 94 +++++++ 4 files changed, 433 insertions(+) create mode 100644 server/tools/robot/kcpclient/app.js create mode 100644 server/tools/robot/kcpclient/clientnet.js create mode 100644 server/tools/robot/kcpclient/package.json create mode 100644 server/tools/robot/kcpclient/testcase.js diff --git a/server/tools/robot/kcpclient/app.js b/server/tools/robot/kcpclient/app.js new file mode 100644 index 00000000..9ee07f94 --- /dev/null +++ b/server/tools/robot/kcpclient/app.js @@ -0,0 +1,8 @@ +const TestCase = require('./testcase'); + +async function start() { + const testCase = new TestCase(); + await testCase.init(); +} + +start(); diff --git a/server/tools/robot/kcpclient/clientnet.js b/server/tools/robot/kcpclient/clientnet.js new file mode 100644 index 00000000..b23de10b --- /dev/null +++ b/server/tools/robot/kcpclient/clientnet.js @@ -0,0 +1,319 @@ + const protobuf = require('protobufjs'); +const ws = require('nodejs-websocket'); + +function prettyJsonEncode(obj) { + return JSON.stringify(obj, "", " "); +} + +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(); + } + + selfRegisterMsgHandle(msgName) { + this.registerMsgHandle( + msgName, + (msg) => { + this[msgName](msg); + }); + } + + async init() { + { + this.protoPb = await (new protobuf.Root()).load(this.protoPbFile, + { + 'keepCase': true + } + ); + } + { + this.msgIdPb = await (new protobuf.Root()).load(this.msgIdPbFile, + { + 'keepCase': true + } + ); + this.cmMsgId = this.msgIdPb.lookup('CMMessageId_e'); + this.smMsgId = this.msgIdPb.lookup('SMMessageId_e'); + } + { + this.selfRegisterMsgHandle('SMLogin'); + this.selfRegisterMsgHandle('SMGuildCreate'); + this.selfRegisterMsgHandle('SMGuildInfo'); + this.selfRegisterMsgHandle('SMGuildMemberList'); + this.selfRegisterMsgHandle('SMGuildSearch'); + this.selfRegisterMsgHandle('SMGuildSearchMember'); + this.selfRegisterMsgHandle('SMGuildAgree'); + this.selfRegisterMsgHandle('SMGuildMemberSetJob'); + this.selfRegisterMsgHandle('SMGuildApplyList'); + this.selfRegisterMsgHandle('SMGuildChange'); + this.selfRegisterMsgHandle('SMGuildSetPermission'); + this.selfRegisterMsgHandle('SMUserInfoUpdate'); + this.selfRegisterMsgHandle('SMPing'); + } + } + + 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() { + let offset = 0; + while (this.recvBuf.length > offset + 12) { + const msgSize = this.recvBuf.readUInt32LE(offset + 0); + const msgId = this.recvBuf.readUInt16LE(offset + 4); + const magicCode = this.recvBuf.readUInt16LE(offset + 6); + const seqId = this.recvBuf.readUInt32LE(offset + 8); + if (this.recvBuf.length >= offset + 12 + msgSize) { + await this.#processMsg(msgId, + this.recvBuf.slice + ( + offset + 12, + offset + 12 + msgSize) + ); + offset += 12 + msgSize; + } else { + break; + } + } + this.recvBuf = this.recvBuf.slice(offset); + } + + 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); + } + console.log(value.msgType['name'], prettyJsonEncode(msg)); + 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.get(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.writeUInt32LE(msgBuf.length, 0); + buf.writeUInt16LE(msgId, 4); + buf.writeUInt8('K'.charCodeAt(0), 6); + buf.writeUInt8('S'.charCodeAt(0), 7); + buf.writeInt32LE(0, 8); + this.conn.sendBinary(Buffer.concat([buf, msgBuf])); + console.log(name, msg, (Buffer.concat([buf, msgBuf])).length); + } + + SMLogin(msg) { + if (msg.errcode) { + return; + } + if (!msg.user_info.guild_id) { + /*this.sendMsg( + 'CMGuildJoin', + { + 'guild_id': 10010 + });*/ + this.sendMsg( + 'CMGuildCreate', + { + 'guild_name': 'test_guild1' + }); + } else { + this.sendMsg( + 'CMGuildInfo', + { + 'guild_id': msg.user_info.guild_id + }); + this.sendMsg( + 'CMGuildApplyList', + { + }); + this.sendMsg( + 'CMGuildAgree', + { + 'applyid': "10072" + }); + } + /*this.sendMsg( + 'CMGuildAgree', + { + 'applyid': "10000" + }); + this.sendMsg( + 'CMGuildMemberSetJob', + { + 'member_id': "6000_1006_227", + "job": 3 + }); + this.sendMsg( + 'CMPing', + { + });*/ + } + + SMGuildCreate(msg) { + this.sendMsg( + 'CMGuildInfo', + { + 'guild_id': msg.guild_id + }); + } + + SMGuildInfo(msg) { + this.sendMsg( + 'CMGuildMemberList', + { + }); + this.sendMsg( + 'CMGuildApplyList', + { + }); + this.sendMsg( + 'CMGuildSearch', + { + 'guild_name': '' + }); + this.sendMsg( + 'CMGuildSearchMember', + { + 'target_id': this.accountId + }); + this.sendMsg( + 'CMGuildChange', + { + 'guild_notice': 'test notice' + }); + this.sendMsg( + 'CMGuildSetPermission', + { + 'permission': { + 'job': 1, + 'switchs': [ + { + 'key': 110001, + 'val': 0 + }, + { + 'key': 110002, + 'val': 0 + }, + { + 'key': 110003, + 'val': 0 + } + ] + } + }); + } + + SMGuildMemberList(msg) { + + } + + SMGuildSearch(msg) { + } + + SMGuildSearchMember(msg) { + + } + + SMGuildAgree(msg) { + + } + + SMGuildMemberSetJob(msg) { + + } + + SMGuildApplyList(msg) { + + } + + SMGuildChange(msg) { + + } + + SMGuildSetPermission(msg) { + + } + + SMUserInfoUpdate(msg) { + + } + + SMPing(msg) { + + } + +} + +module.exports = ClientNet; diff --git a/server/tools/robot/kcpclient/package.json b/server/tools/robot/kcpclient/package.json new file mode 100644 index 00000000..60db1c4c --- /dev/null +++ b/server/tools/robot/kcpclient/package.json @@ -0,0 +1,12 @@ +{ + "name": "kcpclient", + "version": "1.0.0", + "description": "", + "private": true, + "scripts": {}, + "dependencies": { + "axios": "^0.27.0", + "nodejs-websocket": "^1.7.2", + "protobufjs": "^6.11.2" + } +} diff --git a/server/tools/robot/kcpclient/testcase.js b/server/tools/robot/kcpclient/testcase.js new file mode 100644 index 00000000..88739b17 --- /dev/null +++ b/server/tools/robot/kcpclient/testcase.js @@ -0,0 +1,94 @@ +const axios = require('axios').default; +const ClientNet = require('./clientnet'); + +function getTickCount() { + return Math.floor((new Date()).getTime() / 1); +} + +function httpGet(url, params) { + return new Promise((resolve) => { + const ret = { + err: null, + response: null, + }; + axios({ + method: 'get', + url: url, + timeout: 1000 * 5, + params: params, + responseType: 'text' + }).then((response) => { + ret.response = response.data; + resolve(ret); + }).catch((error) => { + ret.err = error; + resolve(ret); + }); + }); +} + +async function sleep(timeout) { + return new Promise(function (resolve, reject) { + setTimeout(function () { + resolve(); + }, timeout); + }); +} + +class TestCase { + + constructor(url) { + this.relationUrl = 'ws://127.0.0.1:7132'; + //this.relationUrl = 'ws://8.133.161.108/game1006/websocket/'; + this.loginData = null; + this.relationWs = new ClientNet( + this.relationUrl, + 'proto/cs_proto.proto', + 'proto/cs_msgid.proto' + ); + } + + async init() { + await this.step1(); + await this.step2(); + while (true) { + await sleep(1000 * 3); + } + } + + async step1() { + const startTick = getTickCount(); + const {err, response} = await httpGet( + 'http://8.133.161.108/game1006/api/webapp/index.php', + { + 'c': 'Login', + 'a': 'auth', + 'gameid': 1006, + 'channel': 6000, + 'account': 'test1', + 'openid': 'test1' + }); + this.loginData = response; + const endTick = getTickCount(); + console.log('login auth@Login', endTick - startTick, String(err), response); + } + + async step2() { + await this.relationWs.init(); + await this.relationWs.connect(); + this.relationWs.on('connect', () => { + console.log('relation onConnect'); + //this.loginData['account_id'] = '6000_1006_gh36'; + //this.loginData['session_id'] = '1654932040_1654932019_997704543_9c6066a10f56f8fb8fc4210c3d9c0b85'; + this.relationWs.accountId = this.loginData['account_id']; + this.relationWs.sessionId = this.loginData['session_id']; + this.relationWs.sendMsg('CMLogin', { + account_id: this.loginData['account_id'], + session_id: this.loginData['session_id'], + }); + }); + } + +} + +module.exports = TestCase;