UNPKG

sdg

Version:

pomelo ts

263 lines 22.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const sdg_1 = tslib_1.__importDefault(require("../sdg")); const base_1 = tslib_1.__importDefault(require("../base")); const sioconnector_1 = tslib_1.__importDefault(require("../connectors/sio/sioconnector")); const events_1 = tslib_1.__importDefault(require("../util/events")); const defaultEncode = (_route, msg) => msg; const defaultDecode = (_route, body) => body; class ConnectorComponent extends base_1.default { constructor(app, opts) { super(app, opts); this.blacklist = []; this.encode = opts.encode; this.decode = opts.decode; this.transformRsp = opts.transformRsp; this.useHostFilter = opts.useHostFilter; this.blacklistFun = opts.blacklistFun; this.forwardMsg = opts.forwardMsg; this.useDict = !!opts.useDict; this.useProtobuf = !!opts.useProtobuf; this.connector = this.getConnector(opts); this.forwardMsg = opts.forwardMsg; this.blacklistFun = opts.blacklistFun; if (opts.useDict) { app.load(sdg_1.default.components.dictionary, app.get('dictionaryConfig')); } if (opts.useProtobuf) { app.load(sdg_1.default.components.protobuf, app.get('protobufConfig')); } } start() { this.server = this.app.components.__server__; this.session = this.app.components.__session__; this.connection = this.app.components.__connection__; if (!this.server) throw 'fail to start connector component for no server component loaded'; if (!this.session) throw 'fail to start connector component for no session component loaded'; } afterStart() { this.connector.start(); this.connector.on('connection', async (socket) => { const can = await this.hostFilter(socket); if (can) this.bindEvents(socket); }); } bindEvents(socket) { if (this.connection) { const curServer = this.app.getCurServer(); const maxConnections = curServer.maxConn; const maxLogined = curServer.maxNum; const statisticInfo = this.connection.getStatisticsInfo(); // 达到最大连接数,t下线 if (maxConnections && statisticInfo.totalConnCount >= maxConnections) { this.app.logger.warn(`the server has reached the max connections ${maxConnections}`); socket.disconnect(); return; } // 达到最大登录量,t下线 if (maxLogined && statisticInfo.loginedCount >= maxLogined) { this.app.logger.warn(`the server has reached the max logined count ${maxLogined}`); socket.disconnect(); return; } this.connection.increaseConnectionCount(); } const session = this.getSession(socket); let closed = false; // 绑定session生命周期对应事件 socket.on('error', (err) => { if (closed) return; closed = true; if (this.connection) { this.connection.decreaseConnectionCount(session.uid); } session.closed(err); }); socket.on('disconnect', reason => { if (closed) return; closed = true; this.logger.warn(`[${socket.id}]disconnected: ${reason}`); if (this.connection) { this.connection.decreaseConnectionCount(session.uid); } session.closed(reason); }); socket.on('closing', (reason) => { socket.send({ route: 'onKick', data: { reason }, ts: Date.now() }); }); socket.on('message', async (msg, cb) => { let msgDecode; const originRoute = msg.route; const route = (this.useDict ? this.app.components.__dictionary__.getAbbr()[originRoute] : originRoute) || originRoute; try { if (this.decode) { msgDecode = this.decode(route, msg.body); } else if (this.connector.decode && this.useProtobuf) { msgDecode = this.connector.decode(route, msg.body); } else { msgDecode = defaultDecode(route, msg.body); } } catch (err) { this.logger.error('decode message error: ', err, msg); } const handlerMsg = msgDecode ? Object.assign({ __route__: route }, msgDecode) : { __route__: route }; try { let data = await this.handleMessage(session, handlerMsg); if (this.transformRsp) { data = this.transformRsp(data); } if (this.encode) { data = this.encode(route, data); } else if (this.connector.encode && this.useProtobuf) { data = this.connector.encode(route, data); } else { data = defaultEncode(route, data); } cb && cb(null, { route: originRoute, data }); } catch (err) { cb && cb(err); } }); } /** * 处理消息事件 * @param session * @param msg * @return {Promise<*>} */ async handleMessage(session, msg) { const type = this.checkServerType(msg.__route__); if (!type) { this.logger.warn(`invalid route string. route: ${msg.__route__}`); return {}; } // 不转发路由 if (this.forwardMsg === false && type === this.app.getServerType()) { this.logger.warn(`illegal route. forwardMsg=false route=${msg.__route__}, sessionId=${session.id}`); // kick client requests for illegal route request. this.session.kickBySessionId(session.id); return {}; } return this.server.globalHandle(msg, session.toFrontendSession()); } /** * 获取当前连接的session * @param socket * @return {*} */ getSession(socket) { const sid = socket.id; let session = this.session.get(sid); if (session) return session; const serverId = this.app.getServerId(); session = this.session.create(sid, serverId, socket); this.logger.debug(`[${serverId}] getSession session is created with session id: ${sid}`); // bind events for session session.on('closed', this.onSessionClose.bind(this)); session.on('bind', (uid) => { this.app.logger.debug(`session: [${session.id}] bind with uid: ${uid}`); if (this.connection) { this.connection.addLoginedUser(uid, { ts: Date.now(), uid, ip: socket.ip }); } this.app.event.emit(events_1.default.BIND_SESSION, session); }); session.on('unbind', (uid) => { if (this.connection) { this.connection.removeLoginedUser(uid); } this.app.event.emit(events_1.default.UNBIND_SESSION, session); }); return session; } send(route, msgRsp, receiveIds, opts) { let encodeData; if (this.transformRsp) { msgRsp = this.transformRsp(msgRsp); } if (this.encode) { encodeData = this.encode(route, msgRsp); } else if (this.connector.encode && this.useProtobuf) { encodeData = this.connector.encode(route, msgRsp); } else { encodeData = defaultEncode(route, msgRsp); } if (this.useDict) route = this.app.components.__dictionary__.getDict()[route] || route; this.doSend(route, encodeData, receiveIds, opts); } async hostFilter(socket) { if (!this.useHostFilter) return true; let check = function (list) { for (let item of list) { let exp = new RegExp(item); if (exp.test(socket.ip)) { socket.disconnect(); return false; } } return true; }; // dynamical check if (this.blacklist.length !== 0 && !check(this.blacklist)) return false; // static check if (this.blacklistFun && typeof this.blacklistFun === 'function') { const list = await this.blacklistFun(); if (!check(list)) return false; } return true; } doSend(route, data, receiveIds, opts) { this.app.components.__pushScheduler__.schedule(route, data, receiveIds, opts); } getConnector(opts) { const connector = this.opts.connector; if (!connector) { return this.getDefaultConnector(opts.socketOpts); } if (typeof connector !== 'function') { return connector; } const curServer = this.app.getCurServer(); return connector(curServer.clientPort, curServer.host, this.opts); } getDefaultConnector(socketOpts) { const curServer = this.app.getCurServer(); return new sioconnector_1.default(curServer.clientPort, curServer.host, socketOpts); } checkServerType(route) { if (!route) return ''; let idx = route.indexOf('.'); if (idx < 0) return ''; return route.substring(0, idx); } onSessionClose(session) { // taskManager.closeQueue(session.id, true); this.app.event.emit(events_1.default.CLOSE_SESSION, session); } } exports.default = ConnectorComponent; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbXBvbmVudHMvY29ubmVjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlEQUF5QjtBQUd6QiwyREFBMkI7QUFDM0IsMEZBQThEO0FBRzlELG9FQUFvQztBQXNCcEMsTUFBTSxhQUFhLEdBQUcsQ0FBQyxNQUFjLEVBQUUsR0FBWSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUM7QUFDNUQsTUFBTSxhQUFhLEdBQUcsQ0FBQyxNQUFjLEVBQUUsSUFBYyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUM7QUFFL0QsTUFBcUIsa0JBQW1CLFNBQVEsY0FBSTtJQWdCbEQsWUFBWSxHQUFnQixFQUFFLElBQWdDO1FBQzVELEtBQUssQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFIWixjQUFTLEdBQWEsRUFBRSxDQUFDO1FBSTlCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUMxQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDMUIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQ3RDLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQztRQUN4QyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDdEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO1FBQ2xDLElBQUksQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7UUFDOUIsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUN0QyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFekMsSUFBSSxDQUFDLFVB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