imsdk-server-core
Version:
轻量级Web服务器框架、WebSocket服务器框架。采用Typescript编写,简单易用。
713 lines (712 loc) • 29.3 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WssServer = void 0;
/**
* 对ws封装的类
* ws相关信息:https://github.com/websockets/ws
*/
const uuid_1 = require("uuid");
const ws_1 = __importDefault(require("ws"));
const https_1 = __importDefault(require("https"));
const http_1 = __importDefault(require("http"));
const WssSession_1 = require("./WssSession");
const AllExport_1 = require("../client/AllExport");
class WssServer {
/**
* @param context 上下文包装类实例
* @param category 日志分类
* @param config 配置信息
* @param wsscfg 库ws配置信息,参考依赖库 https://github.com/websockets/ws
*
* 本类将过滤掉wsscfg.host参数和wsscfg.port参数,请通过context来传入
*/
constructor(context, category, config = {}, wsscfg = {}) {
this._context = context;
this._config = {
pwd: null,
secret: null,
binary: false,
cycle: 60 * 1000,
timeout: 60 * 1000 * 3,
reqIdCache: 32
};
Object.assign(this._config, config); //拷贝配置信息
//绑定log4js实例
this._logger = context.getLogger(category);
//处理wsscfg
if (wsscfg.host)
this._logger.warn('ingore wsscfg.host');
delete wsscfg.host;
if (wsscfg.port)
this._logger.warn('ingore wsscfg.port');
delete wsscfg.port;
if (wsscfg.noServer)
this._logger.warn('ingore wsscfg.noServer');
delete wsscfg.noServer;
this._wsscfg = wsscfg.server ? {} : { server: context.ssls ? https_1.default.createServer(context.readSSLKerCert()) : http_1.default.createServer() };
Object.assign(this._wsscfg, wsscfg); //拷贝ws配置信息
//绑定app和server
this._wssapp = new ws_1.default.Server(this._wsscfg); //创建ws应用实例
this._server = this._wsscfg.server; //绑定HTTP/S服务器实例
//其它属性
this._routerMap = {};
this._remoteMap = {};
this._socketMap = {};
this._sessionMap = {};
this._channelMap = {};
this._clusterMap = {};
this._totalSocket = 0;
this._totalSession = 0;
this._cycleTicker = null; //定时器
this._serverCyclerListener = null;
this._sessionCloseListener = null;
}
/**
* 初始化集群
*/
initClusters() {
const heartick = Math.floor(this._config.cycle / 1000);
for (let i = 0; i < this._context.links.length; i++) {
const appName = this._context.links[i];
const address = this._context.nodes[appName];
const cluster = [];
for (let k = 0; k < address.length; k++) {
const url = (address[k].ssls ? 'wss://' : 'ws://') + (address[k].inip || address[k].host) + ':' + address[k].port;
cluster.push({
grp: appName,
url: url,
rmc: new AllExport_1.WssBridge(url, this._config.pwd, this._config.binary, 8000, heartick, 2),
});
}
if (cluster.length > 0) {
this._clusterMap[appName] = cluster;
}
}
}
/**
* 设置周期监听器
* @param serverCyclerListener
* @param sessionCloseListener
*/
setListeners(serverCyclerListener, sessionCloseListener) {
this._serverCyclerListener = serverCyclerListener;
this._sessionCloseListener = sessionCloseListener;
}
/**
* 设置路由监听器
* @param route
* @param listener
*/
setRouter(route, listener) {
this._routerMap[route] = listener;
}
/**
* 设置远程监听器
* @param route
* @param listener
*/
setRemote(route, listener) {
this._remoteMap[route] = listener;
}
/**
* 绑定uid到session
* @param session
* @param uid
* @param closeold
*/
bindUid(session, uid, closeold = false) {
//旧session处理
const sessionold = this._sessionMap[uid.toString()];
if (sessionold) {
this.unbindUid(sessionold); //解绑uid对应的旧session(此步骤务必在close之前执行,否则close事件中,会将uid对应的新session移除掉)
if (closeold)
sessionold.close(RouteCode.CODE_NEWBIND.code, RouteCode.CODE_NEWBIND.data); //关闭旧的session
}
//新session处理
this.unbindUid(session); //新session解绑旧的uid
session.bindUid(uid); //新session绑定新的的uid
this._sessionMap[uid.toString()] = session; //新session绑定到_sessionMap
this._logger.debug('bindUid:', session.ip, session.id, session.uid);
}
;
/**
* 解绑session的uid
* @param session
*/
unbindUid(session) {
if (!session.isBinded())
return;
this._logger.debug('unbindUid:', session.ip, session.id, session.uid);
delete this._sessionMap[session.uid.toString()]; //从_sessionMap中移除
session.unbindUid();
}
/**
* 根据uid从本节点获取session
* @param uid
*/
getSession(uid) {
return this._sessionMap[uid.toString()];
}
/**
* 加入本节点的某个消息推送组
* @param session
* @param gid
*/
joinChannel(session, gid) {
const channel = this._channelMap[gid.toString()] || { count: 0, sessions: {} };
if (!channel.sessions[session.id]) {
channel.sessions[session.id] = session;
channel.count++;
session.joinChannel(gid);
}
this._channelMap[gid.toString()] = channel;
this._logger.debug('joinChannel:', session.ip, session.id, session.uid, gid);
}
/**
* 退出本节点的某个消息推送组
* @param session
* @param gid
*/
quitChannel(session, gid) {
const channel = this._channelMap[gid.toString()];
if (!channel)
return;
if (channel.sessions[session.id]) {
delete channel.sessions[session.id];
channel.count--;
session.quitChannel(gid);
}
if (channel.count <= 0)
delete this._channelMap[gid.toString()];
this._logger.debug('quitChannel:', session.ip, session.id, session.uid, gid);
}
/**
* 删除本节点的某个消息推送组
* @param gid
*/
deleteChannel(gid) {
const channel = this._channelMap[gid.toString()];
if (!channel)
return;
for (let id in channel.sessions) {
const session = channel.sessions[id];
session.quitChannel(gid);
}
delete this._channelMap[gid.toString()];
this._logger.debug('deleteChannel:', gid);
}
/**
* 响应本节点的某个session的请求
* @param session
* @param reqPack
* @param message
*/
response(session, reqPack, message) {
const pack = new AllExport_1.WssBridgePackData(RouteCode.ROUTE_RESPONSE, reqPack.reqId, message);
const data = AllExport_1.WssBridgePackData.serialize(pack, this._config.pwd, this._config.binary);
session.send(data, this._getSendOptions());
this._logger.debug('response:', session.ip, session.id, session.uid, pack);
}
/**
* 推送消息到本节点的某个session
* @param uid
* @param route
* @param message
*/
pushSession(uid, route, message) {
const session = this._sessionMap[uid.toString()];
if (!session)
return;
const pack = new AllExport_1.WssBridgePackData(route, undefined, message);
const data = AllExport_1.WssBridgePackData.serialize(pack, this._config.pwd, this._config.binary);
session.send(data, this._getSendOptions());
this._logger.debug('pushSession:', session.ip, session.id, session.uid, pack);
}
/**
* 推送消息到本节点的某批session
* @param uids
* @param route
* @param message
*/
pushSessionBatch(uids, route, message) {
const pack = new AllExport_1.WssBridgePackData(route, undefined, message);
const data = AllExport_1.WssBridgePackData.serialize(pack, this._config.pwd, this._config.binary);
for (let i = 0; i < uids.length; i++) {
const session = this._sessionMap[uids[i].toString()];
if (session) {
session.send(data, this._getSendOptions());
}
}
this._logger.debug('pushSessionBatch:', uids, pack);
}
/**
* 推送消息到本节点的某个消息推送组
* @param gid
* @param route
* @param message
*/
pushChannel(gid, route, message) {
const channel = this._channelMap[gid.toString()];
if (!channel)
return;
const pack = new AllExport_1.WssBridgePackData(route, undefined, message);
const data = AllExport_1.WssBridgePackData.serialize(pack, this._config.pwd, this._config.binary);
for (let id in channel.sessions) {
const session = channel.sessions[id];
session.send(data, this._getSendOptions());
}
this._logger.debug('pushChannel:', gid, pack);
}
/**
* 推送消息到本节点的某个消息推送组,每个成员的数据都进过差异处理
* @param gid
* @param route
* @param message
* @param customCallback 在这个函数中对每个成员的数据进行差异处理
*/
pushChannelCustom(gid, route, message, customCallback) {
const channel = this._channelMap[gid.toString()];
if (!channel)
return;
for (let id in channel.sessions) {
const session = channel.sessions[id];
const pack = new AllExport_1.WssBridgePackData(route, undefined, customCallback(session.uid, message));
const data = AllExport_1.WssBridgePackData.serialize(pack, this._config.pwd, this._config.binary);
session.send(data, this._getSendOptions());
this._logger.debug('pushChannelCustom:', session.ip, session.id, session.uid, gid, pack);
}
}
/**
* 推送消息到本节点的已经绑定过uid的全部session
* @param route
* @param message
*/
broadcast(route, message) {
const pack = new AllExport_1.WssBridgePackData(route, undefined, message);
const data = AllExport_1.WssBridgePackData.serialize(pack, this._config.pwd, this._config.binary);
for (let uid in this._sessionMap) {
const session = this._sessionMap[uid];
session.send(data, this._getSendOptions());
}
this._logger.debug('broadcast:', pack);
}
/**
* 推送消息到某个节点的某个session,建议通过dispatchCallback来优化推送性能
* @param appName 节点分组名
* @param uid
* @param route
* @param message
* @param dispatchCallback 分配节点,如果未指定该函数,则从该节点分组的全部节点中搜索对应uid的session
*/
pushClusterSession(appName, uid, route, message, dispatchCallback) {
const cluster = this._clusterMap[appName];
const innerData = this._generateInnerData(uid, route, message);
if (dispatchCallback) {
const handle = cluster[dispatchCallback(cluster, uid, innerData)];
handle.rmc.request(RouteCode.ROUTE_INNERP2P, innerData);
this._logger.debug('pushClusterSession:', appName, handle.url, innerData);
}
else {
for (let i = 0; i < cluster.length; i++) {
const handle = cluster[i];
handle.rmc.request(RouteCode.ROUTE_INNERP2P, innerData);
this._logger.debug('pushClusterSession:', appName, handle.url, innerData);
}
}
}
/**
* 推送消息到某个节点的某个消息推送组,建议通过dispatchCallback来优化推送性能
* @param appName 节点分组名
* @param gid
* @param route
* @param message
* @param dispatchCallback 分配节点,如果未指定该函数,则从该节点分组的全部节点中搜索对应gid的channel
*/
pushClusterChannel(appName, gid, route, message, dispatchCallback) {
const cluster = this._clusterMap[appName];
const innerData = this._generateInnerData(gid, route, message);
if (dispatchCallback) {
const handle = cluster[dispatchCallback(cluster, gid, innerData)];
handle.rmc.request(RouteCode.ROUTE_INNERGRP, innerData);
this._logger.debug('pushClusterChannel:', appName, handle.url, innerData);
}
else {
for (let i = 0; i < cluster.length; i++) {
const handle = cluster[i];
handle.rmc.request(RouteCode.ROUTE_INNERGRP, innerData);
this._logger.debug('pushClusterChannel:', appName, handle.url, innerData);
}
}
}
/**
* 推送消息到某个节点的已经绑定过uid的全部session
* @param appName 节点分组名
* @param route
* @param message
* @param dispatchCallback 分配节点,如果未指定该函数,将推送到该节点分组的全部节点
*/
clusterBroadcast(appName, route, message, dispatchCallback) {
const cluster = this._clusterMap[appName];
const innerData = this._generateInnerData(null, route, message);
if (dispatchCallback) {
const handle = cluster[dispatchCallback(cluster, null, innerData)];
handle.rmc.request(RouteCode.ROUTE_INNERALL, innerData);
this._logger.debug('clusterBroadcast:', appName, handle.url, innerData);
}
else {
for (let i = 0; i < cluster.length; i++) {
const handle = cluster[i];
handle.rmc.request(RouteCode.ROUTE_INNERALL, innerData);
this._logger.debug('clusterBroadcast:', appName, handle.url, innerData);
}
}
}
/**
* 节点间远程路由异步调用
* @param appName 节点分组名
* @param route
* @param message
* @param dispatchCallback 分配节点,如果未指定该函数,则从该节点分组的全部节点中随机选择一个节点
*/
callRemote(appName, route, message, dispatchCallback) {
const cluster = this._clusterMap[appName];
const innerData = this._generateInnerData(null, route, message);
const index = dispatchCallback ? dispatchCallback(cluster, null, innerData) : Math.min(Math.floor(Math.random() * cluster.length), cluster.length - 1);
const handle = cluster[index];
this._logger.debug('callRemote:', appName, handle.url, innerData);
handle.rmc.request(RouteCode.ROUTE_INNERRMC, innerData);
}
/**
* 节点间远程路由异步调用,并返回结果
* @param appName 节点分组名
* @param route
* @param message
* @param dispatchCallback 分配节点,如果未指定该函数,则从该节点分组的全部节点中随机选择一个节点
*/
callRemoteForResult(appName, route, message, dispatchCallback) {
const cluster = this._clusterMap[appName];
const msgdata = this._generateInnerData(null, route, message);
const index = dispatchCallback ? dispatchCallback(cluster, null, msgdata) : Math.min(Math.floor(Math.random() * cluster.length), cluster.length - 1);
const handle = cluster[index];
this._logger.debug('callRemoteForResult:', appName, handle.url, msgdata);
return new Promise((resolve) => {
handle.rmc.request(RouteCode.ROUTE_INNERRMC, msgdata, (resp, params) => {
resolve(resp);
}, (resp, params) => {
resolve(resp);
}, this);
});
}
/**
* 开启服务器
* @param callback 服务器启动后的回调函数
*/
start(callback) {
//参数检测
if (this._config.cycle < 10000)
throw Error('cycle >= 10,000ms');
if (this._config.timeout < 30000)
throw Error('timeout >= 30,000ms');
if (this._config.cycle * 3 > this._config.timeout)
throw Error('timeout >= cycle * 3');
//注册监听
this._wssapp.on('connection', (socket, request) => {
this._onWebSocketConnection(socket, request);
});
//开启心跳循环
this._cycleTicker = setInterval(() => {
try {
this._onServerLifeCycle();
}
catch (e) {
this._logger.error('Unhandled life cycle exception:', e);
}
}, this._config.cycle);
//连接关联的集群节点
for (let appName in this._clusterMap) {
const cluster = this._clusterMap[appName];
for (let i = 0; i < cluster.length; i++) {
this._connectForCluster(cluster[i]);
}
}
//启动服务器
this._server.listen(this._context.port, () => {
this._logger.info('ssls', this._context.ssls, this._context.host, this._context.port, 'is listening...');
if (callback)
callback();
});
}
/**
* 关闭服务器
* @param callback
*/
close(callback) {
//销毁心跳循环
if (this._cycleTicker) {
clearInterval(this._cycleTicker);
this._cycleTicker = null;
}
//断开关联的集群节点
for (let appName in this._clusterMap) {
const cluster = this._clusterMap[appName];
for (let i = 0; i < cluster.length; i++) {
cluster[i].rmc.disconnect();
}
}
//关闭服务器
this._server.close((error) => {
this._logger.info('ssls', this._context.ssls, this._context.host, this._context.port, 'was closed.');
if (callback)
callback(error);
});
}
/**
* 周期循环
*/
_onServerLifeCycle() {
let totalSocket = 0;
let totalSession = 0;
for (let id in this._socketMap) {
const session = this._socketMap[id];
if (session.isExpired(this._config.timeout)) {
session.close(RouteCode.CODE_TIMEOUT.code, RouteCode.CODE_TIMEOUT.data); //清除超时的链接
}
else {
totalSocket += 1;
totalSession += session.isBinded() ? 1 : 0;
}
}
this._logger.info('_onServerLifeCycle:', 'totalSocket->', totalSocket, 'totalSession->', totalSession);
//更新连接数量
this._totalSocket = totalSocket;
this._totalSession = totalSession;
//回调上层绑定的监听器
if (this._serverCyclerListener) {
this._serverCyclerListener(this, this._totalSocket, this._totalSession);
}
}
/**
* 收到连接后注册监听
* @param socket
* @param request
*/
_onWebSocketConnection(socket, request) {
const session = new WssSession_1.WssSession(socket, this._context.getIPV4({ headers: request.headers, ip: request.socket.remoteAddress }));
this._socketMap[session.id] = session; //绑定到_socketMap
socket.binaryType = 'arraybuffer'; //指定读取格式为arraybuffer
socket.on('message', (data) => {
this._onWebSocketMessage(session, data);
});
socket.on('close', (code, reason) => {
this._logger.info('on websocket close:', session.ip, session.id, session.uid, code, reason);
//回调上层绑定的监听器
if (this._sessionCloseListener) {
this._sessionCloseListener(this, session, code, reason);
}
//统一进行内存清理操作
session.eachChannel((gid) => { this.quitChannel(session, gid); }); //退出已加入的所有分组
this.unbindUid(session); //可能已经绑定了uid,需要进行解绑操作
delete this._socketMap[session.id]; //从_socketMap中移除
});
socket.on('error', (error) => {
this._logger.error('on websocket error:', session.ip, session.id, session.uid, error.toString());
session.close(RouteCode.CODE_SOCKET.code, RouteCode.CODE_SOCKET.data + ': ' + error.toString());
});
this._logger.info('on websocket connection:', session.ip, session.id);
}
/**
*
* @param session
* @param data
*/
_onWebSocketMessage(session, data) {
const pack = AllExport_1.WssBridgePackData.deserialize(data, this._config.pwd);
//解析包数据
if (!pack) {
this._logger.error('_onWebSocketMessage:', session.ip, session.id, session.uid, RouteCode.CODE_PARSE.code, data);
session.close(RouteCode.CODE_PARSE.code, RouteCode.CODE_PARSE.data);
return;
}
//校验包格式
if (typeof pack.route !== 'string' || typeof pack.reqId !== 'number' || pack.message === undefined || pack.message === null) {
this._logger.error('_onWebSocketMessage:', session.ip, session.id, session.uid, RouteCode.CODE_FORMAT.code, pack);
session.close(RouteCode.CODE_FORMAT.code, RouteCode.CODE_FORMAT.data);
return;
}
//校验重复包
if (!session.updateReqId(pack.reqId, this._config.reqIdCache)) {
this._logger.error('_onWebSocketMessage:', session.ip, session.id, session.uid, RouteCode.CODE_REPEAT.code, pack);
session.close(RouteCode.CODE_REPEAT.code, RouteCode.CODE_REPEAT.data);
return;
}
//收到心跳包
if (pack.route === RouteCode.ROUTE_HEARTICK) {
this._logger.trace('_onWebSocketMessage:', session.ip, session.id, session.uid, pack);
session.updateHeart(); //更新本次心跳时间戳
this._sendHeartick(session, pack); //按照原样发回客户端
return;
}
//集群P2P包
if (pack.route === RouteCode.ROUTE_INNERP2P) {
if (this._validateInnerData(pack.message)) {
this._logger.debug('_onWebSocketMessage:', session.ip, session.id, session.uid, pack);
this.pushSession(pack.message.tid, pack.message.route, pack.message.message);
}
else {
this._logger.error('_onWebSocketMessage:', session.ip, session.id, session.uid, RouteCode.CODE_SIGN.code, pack);
session.close(RouteCode.CODE_SIGN.code, RouteCode.CODE_SIGN.data);
}
return;
}
//集群GRP包
if (pack.route === RouteCode.ROUTE_INNERGRP) {
if (this._validateInnerData(pack.message)) {
this._logger.debug('_onWebSocketMessage:', session.ip, session.id, session.uid, pack);
this.pushChannel(pack.message.tid, pack.message.route, pack.message.message);
}
else {
this._logger.error('_onWebSocketMessage:', session.ip, session.id, session.uid, RouteCode.CODE_SIGN.code, pack);
session.close(RouteCode.CODE_SIGN.code, RouteCode.CODE_SIGN.data);
}
return;
}
//集群ALL包
if (pack.route === RouteCode.ROUTE_INNERALL) {
if (this._validateInnerData(pack.message)) {
this._logger.debug('_onWebSocketMessage:', session.ip, session.id, session.uid, pack);
this.broadcast(pack.message.route, pack.message.message);
}
else {
this._logger.error('_onWebSocketMessage:', session.ip, session.id, session.uid, RouteCode.CODE_SIGN.code, pack);
session.close(RouteCode.CODE_SIGN.code, RouteCode.CODE_SIGN.data);
}
return;
}
//集群RMC包
if (pack.route === RouteCode.ROUTE_INNERRMC) {
if (this._validateInnerData(pack.message)) {
if (this._remoteMap[pack.message.route]) {
this._logger.debug('_onWebSocketMessage:', session.ip, session.id, session.uid, pack);
this._remoteMap[pack.message.route](this, session, new AllExport_1.WssBridgePackData(pack.message.route, pack.reqId, pack.message.message)); //调用远程方法
}
else {
this._logger.error('_onWebSocketMessage:', session.ip, session.id, session.uid, RouteCode.CODE_REMOTE.code, pack);
session.close(RouteCode.CODE_REMOTE.code, RouteCode.CODE_REMOTE.data);
}
}
else {
this._logger.error('_onWebSocketMessage:', session.ip, session.id, session.uid, RouteCode.CODE_SIGN.code, pack);
session.close(RouteCode.CODE_SIGN.code, RouteCode.CODE_SIGN.data);
}
return;
}
//自定义路由
if (this._routerMap[pack.route]) {
this._logger.debug('_onWebSocketMessage:', session.ip, session.id, session.uid, pack);
this._routerMap[pack.route](this, session, pack); //调用路由方法
return;
}
//没找到路由
this._logger.error('_onWebSocketMessage:', session.ip, session.id, session.uid, RouteCode.CODE_ROUTE.code, pack);
session.close(RouteCode.CODE_ROUTE.code, RouteCode.CODE_ROUTE.data);
}
/**
* 返回发送数据到客户端websocket的选项
*/
_getSendOptions() {
return { binary: this._config.binary };
}
/**
* 响应心跳包
* @param session
* @param reqPack
*/
_sendHeartick(session, reqPack) {
const pack = new AllExport_1.WssBridgePackData(RouteCode.ROUTE_HEARTICK, reqPack.reqId, reqPack.message);
const data = AllExport_1.WssBridgePackData.serialize(pack, this._config.pwd, this._config.binary);
session.send(data, this._getSendOptions());
this._logger.trace('_sendHeartick:', session.ip, session.id, session.uid, pack);
}
/**
* 连接到集群节点
* @param node
*/
_connectForCluster(node) {
node.rmc.setLogLevel(AllExport_1.WssBridge.LOG_LEVEL_NONE);
node.rmc.connect(() => {
this._logger.mark('cluster onopen->', node.grp, node.url);
}, (code, reason, params) => {
// this._logger.warn('cluster onclose->', code, reason);
}, (error, params) => {
// this._logger.error('cluster onerror->', error);
}, (count, params) => {
this._logger.debug('cluster onretry->', node.grp, node.url, count, 'times');
}, null, this);
}
/**
* 生成内部签名数据包
* @param tid
* @param route
* @param message
*/
_generateInnerData(tid, route, message) {
const data = {};
if (tid)
data.tid = tid;
data.route = route;
data.message = message;
data.word = uuid_1.v1();
data.sign = this._context.getMd5(route + data.word + this._config.secret);
return data;
}
/**
* 校验内部签名数据包
* @param data
*/
_validateInnerData(data) {
return this._context.getMd5(data.route + data.word + this._config.secret) === data.sign;
}
/**
* 返回Logger实例
*/
get logger() { return this._logger; }
get wssapp() { return this._wssapp; }
get server() { return this._server; }
get wssPwd() { return this._config.pwd; }
get wssSecret() { return this._config.secret; }
}
exports.WssServer = WssServer;
/**
* 状态码范围参考: https://tools.ietf.org/html/rfc6455#section-7.4.2
* 以及:https://github.com/websockets/ws/issues/715
*/
class RouteCode {
}
/**
* 路由
*/
RouteCode.ROUTE_HEARTICK = '$heartick$'; //心跳包路由
RouteCode.ROUTE_RESPONSE = '$response$'; //响应请求路由
RouteCode.ROUTE_INNERP2P = '$innerP2P$'; //集群点对点消息路由
RouteCode.ROUTE_INNERGRP = '$innerGRP'; //集群分组消息路由
RouteCode.ROUTE_INNERALL = '$innerALL$'; //集群广播消息路由
RouteCode.ROUTE_INNERRMC = '$innerRMC$'; //集群远程方法路由
/**
* 状态
* 本框架保留状态码:
* 4001-4100 服务端保留状态码范围
* 4101-4200 客户端保留状态码范围
* 4201-4999 可自定义的状态码范围
*/
RouteCode.CODE_PARSE = { code: 4001, data: 'parse error' };
RouteCode.CODE_FORMAT = { code: 4002, data: 'format error' };
RouteCode.CODE_REPEAT = { code: 4003, data: 'repeat error' };
RouteCode.CODE_SIGN = { code: 4004, data: 'sign error' };
RouteCode.CODE_REMOTE = { code: 4005, data: 'remote error' };
RouteCode.CODE_ROUTE = { code: 4006, data: 'route error' };
RouteCode.CODE_SOCKET = { code: 4007, data: 'socket error' };
RouteCode.CODE_TIMEOUT = { code: 4008, data: 'timeout error' };
RouteCode.CODE_NEWBIND = { code: 4009, data: 'newbind error' };