├── modules ├── distributed │ ├── election.h │ ├── node.h │ ├── node.cpp │ ├── coordinate.h │ ├── coordinate.cpp │ └── CMakeLists.txt ├── dbProxy │ ├── redisConnect.cpp │ ├── mysqlConnect.h │ ├── CMakeLists.txt │ ├── mysqlConnect.cpp │ └── redisConnect.h ├── CMakeLists.txt ├── network │ ├── tcpConnector.h │ ├── session.h │ ├── tcpAcceptor.h │ ├── sessionMgr.h │ ├── msgBlock.h │ ├── CMakeLists.txt │ ├── sessionMgr.cpp │ ├── tcpConnector.cpp │ ├── session.cpp │ └── tcpAcceptor.cpp └── luaAdapter │ ├── CMakeLists.txt │ ├── luaAdapter.h │ └── luaAdapter.cpp ├── CMakeLists.txt ├── core ├── service.h ├── appConfig.hpp ├── CMakeLists.txt ├── dynamic_module_factory.h ├── types.h ├── application.cpp ├── module.cpp ├── application.h ├── module.h ├── appImpl.hpp ├── args.h ├── appImpl.cpp └── args.cpp ├── utils ├── single.h ├── timer.hpp ├── logger.hpp ├── dump.lua ├── profiler.lua ├── crc32.hpp ├── logger_impl.hpp ├── timer_impl.hpp └── protobuf.lua ├── script ├── event_list.lua ├── profiler.lua ├── utils.lua ├── event_fmt.lua └── protobuf.lua ├── .travis.yml ├── README.md ├── event_list.h ├── install.py └── .gitignore /modules/distributed/election.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /modules/dbProxy/redisConnect.cpp: -------------------------------------------------------------------------------- 1 | #include "redisConnect.h" 2 | 3 | -------------------------------------------------------------------------------- /modules/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_SUBDIRECTORY(network) 2 | ADD_SUBDIRECTORY(distributed) 3 | ADD_SUBDIRECTORY(luaAdapter) 4 | ADD_SUBDIRECTORY(dbProxy) -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(BLOCK) 2 | 3 | if(WIN32) 4 | endif() 5 | 6 | if(UNIX) 7 | set(CMAKE_CXX_FLAGS "-std=c++1y ${CMAKE_CXX_FLAGS}") 8 | endif() 9 | 10 | if (Darwin) 11 | set(CMAKE_CXX_FLAGS "-std=c++1y ${CMAKE_CXX_FLAGS}") 12 | endif() 13 | 14 | SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 15 | SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) 16 | 17 | ADD_SUBDIRECTORY(core) 18 | ADD_SUBDIRECTORY(modules) 19 | -------------------------------------------------------------------------------- /core/service.h: -------------------------------------------------------------------------------- 1 | #ifndef _GSF_SERVEICE_HEADER_ 2 | #define _GSF_SERVEICE_HEADER_ 3 | 4 | namespace block 5 | { 6 | enum ServiceState 7 | { 8 | ss_beforeInit, 9 | ss_init, 10 | ss_execute, 11 | ss_shut, 12 | ss_afterShut 13 | }; 14 | 15 | class Service 16 | { 17 | protected: 18 | 19 | /*! 20 | 21 | **/ 22 | virtual void exec(); 23 | 24 | private: 25 | ServiceState ss_; 26 | }; 27 | } 28 | 29 | #endif -------------------------------------------------------------------------------- /core/appConfig.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace block 7 | { 8 | struct AppConfig 9 | { 10 | //! 每帧间隔的毫秒时间 11 | uint32_t tick_count = 20; 12 | 13 | //! args池的初始化大小 14 | uint32_t pool_args_count = 1024 * 10; 15 | 16 | //! 是否开启性能监控日志 17 | bool is_watch_pref = false; 18 | 19 | //! app的名称 20 | std::string name = "default"; 21 | 22 | //! app的id,作用于分布式架构,必须保证唯一。 23 | int32_t appid = 0; 24 | 25 | //! rpc 调用的超时时间 ms 26 | int32_t rpc_timeout = 10000; 27 | }; 28 | } -------------------------------------------------------------------------------- /modules/distributed/node.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace block 11 | { 12 | namespace modules 13 | { 14 | class NodeModule 15 | : public block::Module 16 | { 17 | public: 18 | 19 | NodeModule(); 20 | virtual ~NodeModule(); 21 | 22 | void before_init() override; 23 | void init() override; 24 | void execute() override; 25 | void shut() override; 26 | 27 | protected: 28 | 29 | }; 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /modules/distributed/node.cpp: -------------------------------------------------------------------------------- 1 | #include "node.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | block::modules::NodeModule::NodeModule() 12 | : Module("NodeModule") 13 | { 14 | 15 | } 16 | 17 | block::modules::NodeModule::~NodeModule() 18 | { 19 | 20 | } 21 | 22 | void block::modules::NodeModule::before_init() 23 | { 24 | 25 | } 26 | 27 | void block::modules::NodeModule::init() 28 | { 29 | } 30 | 31 | void block::modules::NodeModule::execute() 32 | { 33 | } 34 | 35 | void block::modules::NodeModule::shut() 36 | { 37 | } -------------------------------------------------------------------------------- /modules/distributed/coordinate.h: -------------------------------------------------------------------------------- 1 | #ifndef _COORDINATE_HEADER_ 2 | #define _COORDINATE_HEADER_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace block 12 | { 13 | namespace modules 14 | { 15 | class CoodinatorModule 16 | : public block::Module 17 | { 18 | public: 19 | 20 | CoodinatorModule(); 21 | virtual ~CoodinatorModule() {} 22 | 23 | void before_init() override; 24 | void init() override; 25 | void execute() override; 26 | void shut() override; 27 | 28 | private: 29 | }; 30 | } 31 | } 32 | 33 | 34 | #endif // !_COORDINATE_HEADER_ 35 | -------------------------------------------------------------------------------- /utils/single.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace block 6 | { 7 | namespace utils 8 | { 9 | template 10 | class Singleton 11 | { 12 | public: 13 | virtual ~Singleton(){ 14 | assert(intance_ptr_); 15 | intance_ptr_ = nullptr; 16 | } 17 | 18 | static T & get_ref() { 19 | assert(intance_ptr_); return (*intance_ptr_); 20 | } 21 | static T * get_ptr() { 22 | assert(intance_ptr_); return intance_ptr_; 23 | } 24 | 25 | public: 26 | Singleton() 27 | { 28 | intance_ptr_ = static_cast(this); 29 | } 30 | 31 | private: 32 | static T * intance_ptr_; 33 | Singleton(const Singleton &) = delete; 34 | }; 35 | 36 | template 37 | T * Singleton::intance_ptr_ = nullptr; 38 | } 39 | } -------------------------------------------------------------------------------- /utils/timer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "timer_impl.hpp" 4 | 5 | namespace block 6 | { 7 | namespace utils 8 | { 9 | struct delay_milliseconds; 10 | struct delay_day; 11 | 12 | class Timer 13 | { 14 | public: 15 | 16 | /*! 17 | 在进程主循环执行 18 | **/ 19 | void exec() 20 | { 21 | impl_.exec(); 22 | } 23 | 24 | /*! 25 | 添加一个定时器 26 | delay_milliseconds 延时若干毫秒 27 | delay_day 延时若干天 28 | **/ 29 | template 30 | uint64_t delay(T delay, std::function callback) 31 | { 32 | return impl_.delay(delay, callback, typename timer_traits::type()); 33 | } 34 | 35 | /*! 36 | 从定时管理器中移除某个定时器 37 | **/ 38 | void remove(uint64_t timerID) 39 | { 40 | impl_.remove(timerID); 41 | } 42 | 43 | private: 44 | TimerImpl impl_; 45 | }; 46 | } 47 | } -------------------------------------------------------------------------------- /script/event_list.lua: -------------------------------------------------------------------------------- 1 | 2 | eid = { 3 | 4 | module = { 5 | init = 101, 6 | shut = 102, 7 | }, 8 | 9 | distributed = { 10 | rpc_begin = 1001, 11 | 12 | coordinat_regist = 1002, 13 | coordinat_unregit = 1003, 14 | coordinat_adjust_weight = 1004, 15 | coordinat_select = 1005, 16 | 17 | rpc_end = 2000, 18 | }, 19 | 20 | network = { 21 | tcp_make_acceptor = 2001, 22 | ws_make_acceptor = 2002, 23 | tcp_make_connector = 2003, 24 | ws_make_connector = 2004, 25 | kick_connect = 2005, 26 | send = 2006, 27 | recv = 2007, 28 | new_connect = 2008, 29 | dis_connect = 2009, 30 | fail_connect = 2010 31 | }, 32 | 33 | dbProxy = { 34 | connect = 2401, 35 | execSql = 2402, 36 | insert = 2403, 37 | load = 2404, 38 | update = 2405, 39 | callback = 2406 40 | }, 41 | 42 | node = { 43 | node_create = 2500, 44 | node_create_succ = 2501, 45 | node_regist = 2502, 46 | node_regist_succ = 2503, 47 | }, 48 | } -------------------------------------------------------------------------------- /modules/distributed/coordinate.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "coordinate.h" 3 | #include 4 | 5 | #include 6 | 7 | block::modules::CoodinatorModule::CoodinatorModule() 8 | : Module("CoodinatorModule") 9 | { 10 | 11 | } 12 | 13 | void block::modules::CoodinatorModule::before_init() 14 | { 15 | using namespace std::placeholders; 16 | /* 17 | listen(block::event::coordinat_regist, std::bind(&CoodinatorModule::eCoordinatRegist, this, _1, _2)); 18 | listen(block::event::coordinat_unregit, std::bind(&CoodinatorModule::eCoordinatUnregist, this, _1, _2)); 19 | 20 | listen(block::event::coordinat_adjust_weight 21 | , std::bind(&CoodinatorModule::eCoordinatAdjustWeight, this, _1, _2)); 22 | 23 | listen(block::event::coordinat_select 24 | , std::bind(&CoodinatorModule::eCoordinatSelect, this, _1, _2)); 25 | */ 26 | } 27 | 28 | void block::modules::CoodinatorModule::init() 29 | { 30 | 31 | } 32 | 33 | void block::modules::CoodinatorModule::execute() 34 | { 35 | 36 | } 37 | 38 | void block::modules::CoodinatorModule::shut() 39 | { 40 | 41 | } 42 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: true 2 | language: cpp 3 | 4 | matrix: 5 | include: 6 | # works on Precise and Trusty 7 | - os: linux 8 | addons: 9 | apt: 10 | sources: 11 | - ubuntu-toolchain-r-test 12 | packages: 13 | - g++-4.9 14 | env: 15 | - MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9" 16 | 17 | before_install: 18 | - eval "${MATRIX_EVAL}" 19 | 20 | compiler: 21 | - g++ 22 | os: 23 | - linux 24 | 25 | install: 26 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then sudo apt-get install -qq cmake; fi 27 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then sudo apt-get install -qq git; fi 28 | 29 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then sudo apt-get install -qq unzip; fi 30 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then sudo apt-get install -qq libtool; fi 31 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then sudo apt-get install -qq autoconf; fi 32 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then sudo apt-get install -qq automake; fi 33 | - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then sudo apt-get install -qq curl; fi 34 | 35 | before_script: 36 | - python install.py 37 | 38 | script: 39 | - cmake --version 40 | - cmake . 41 | - make 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Block 2 | [![Build Status](https://travis-ci.org/pojol/block.svg?branch=master)](https://travis-ci.org/pojol/block) 3 | [![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/labstack/echo/master/LICENSE) 4 | 5 | ## 简介 6 | > *block* 是一个 **模块化的跨平台游戏服务器框架** ,通过不同的 [*Module*](https://github.com/pojol/block/wiki/Core_Module) 组装方式可以适应大多数的架构。通常您只需要使用 **lua** 就能完成大部分的游戏逻辑编写,但是您也可以使用 **c++** 来完成一些高密度计算的逻辑。 7 | 8 | 9 | #### 特性 10 | * 完全逻辑独立的模块,通过Mailbox拉取,推送消息 11 | * 支持分布式构建,支持rpc 12 | * 支持脚本热更(带状态退出,重入 13 | * 支持基于redis的灾备机制和数据缓存 14 | *** 15 | 16 | #### 依赖编译环境 17 | * linux (gcc4.9+ 18 | * windows (vs2015+ 19 | *** 20 | 21 | #### 编译&安装 22 | * install.py 23 | *** 24 | 25 | #### 文档 26 | * [document](https://github.com/pojol/block/wiki) 27 | *** 28 | 29 | #### 依赖库 30 | * [fmtlib](https://github.com/fmtlib/fmt) 31 | * [lua](https://github.com/lua/lua) 32 | * [sol2](https://github.com/ThePhD/sol2) 33 | * [protobuf](https://github.com/google/protobuf) 34 | * [pbc](https://github.com/cloudwu/pbc) 35 | * [libevent](https://github.com/nmathewson/Libevent) 36 | * [glog](https://github.com/google/glog) 37 | * [mysql-connector/c](https://dev.mysql.com/downloads/connector/c/) 38 | * [hiredis](https://github.com/redis/hiredis) 39 | * [redis/windows](https://github.com/MicrosoftArchive/redis) 40 | -------------------------------------------------------------------------------- /modules/network/tcpConnector.h: -------------------------------------------------------------------------------- 1 | #ifndef _GSF_CONNECTOR_HEADER_ 2 | #define _GSF_CONNECTOR_HEADER_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace block 15 | { 16 | namespace network 17 | { 18 | class Session; 19 | class SessionMgr; 20 | 21 | typedef std::shared_ptr SessionPtr; 22 | 23 | class TcpConnectorModule 24 | : public block::Module 25 | { 26 | public: 27 | TcpConnectorModule(const std::string &name); 28 | TcpConnectorModule(); 29 | virtual ~TcpConnectorModule(); 30 | 31 | void before_init() override; 32 | void init() override; 33 | 34 | void execute() override; 35 | 36 | void shut() override; 37 | void after_shut() override; 38 | 39 | private: 40 | void eMakeConncetor(block::ModuleID target, block::ArgsPtr args); 41 | void eSendMsg(block::ModuleID target, block::ArgsPtr args); 42 | 43 | void needCloseSession(int fd); 44 | 45 | private: 46 | 47 | block::ModuleID proxyModuleID_ = block::ModuleNil; 48 | 49 | event_base *eventBasePtr_ = nullptr; 50 | 51 | SessionPtr sessionPtr_ = nullptr; 52 | SessionMgr *sessionMgr_ = nullptr; 53 | 54 | ::bufferevent *bufferEventPtr_ = nullptr; 55 | }; 56 | } 57 | } 58 | 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /modules/network/session.h: -------------------------------------------------------------------------------- 1 | #ifndef _GSF_SESSION_HEADER_ 2 | #define _GSF_SESSION_HEADER_ 3 | 4 | #include 5 | #include 6 | 7 | #include "msgBlock.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace block 15 | { 16 | namespace network 17 | { 18 | class OBuffer; 19 | class IBuffer; 20 | class MsgBinder; 21 | class SessionMgr; 22 | 23 | class Session 24 | { 25 | public: 26 | Session(int fd, block::ModuleID moduleID, SessionMgr *mgr, ::bufferevent *bev); 27 | ~Session(); 28 | 29 | static void readCB(::bufferevent *bev, void *ctx); 30 | static void eventCB(::bufferevent *bev, short what, void *ctx); 31 | 32 | int write(uint32_t msg_id, BlockPtr blockptr); 33 | void read(::bufferevent *bev); 34 | 35 | void disConnect(int32_t err); 36 | void newConnect(); 37 | 38 | block::SessionID getID() const { return fd_; } 39 | block::ModuleID getModuleID() const { return targetM_; } 40 | 41 | protected: 42 | 43 | private: 44 | block::SessionID fd_ = block::SessionNil; 45 | block::ModuleID targetM_ = block::ModuleNil; 46 | 47 | std::function disconnCallback_; 48 | 49 | ::evbuffer *inBufPtr_ = nullptr; 50 | ::evbuffer *outBufPtr_ = nullptr; 51 | 52 | ::bufferevent *bufEvtPtr_ = nullptr; 53 | 54 | SessionMgr * basePtr_ = nullptr; 55 | }; 56 | } 57 | 58 | } 59 | 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /modules/network/tcpAcceptor.h: -------------------------------------------------------------------------------- 1 | #ifndef _GSF_ACCEPTOR_HEADER_ 2 | #define _GSF_ACCEPTOR_HEADER_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace block 14 | { 15 | namespace network 16 | { 17 | class SessionMgr; 18 | 19 | class TcpAcceptorModule 20 | : public block::Module 21 | { 22 | public: 23 | TcpAcceptorModule(const std::string &name); 24 | TcpAcceptorModule(); 25 | virtual ~TcpAcceptorModule(); 26 | 27 | void before_init() override; 28 | void init() override; 29 | 30 | void execute() override; 31 | 32 | void shut() override; 33 | void after_shut() override; 34 | 35 | private: 36 | 37 | void eMakeAcceptor(block::ModuleID target, block::ArgsPtr args); 38 | 39 | void eSendMsg(block::ModuleID target, block::ArgsPtr args); 40 | 41 | void eKick(block::ModuleID target, block::ArgsPtr args); 42 | 43 | void accept_bind(const std::string &ip, int port); 44 | static void accept_listen_cb(::evconnlistener *listener 45 | , evutil_socket_t fd 46 | , sockaddr *sa 47 | , int socklen 48 | , void *arg); 49 | 50 | private: 51 | 52 | block::ModuleID proxyModuleID_ = block::ModuleNil; 53 | 54 | SessionMgr *sessionMgr_ = nullptr; 55 | 56 | event_base *eventBasePtr_ = nullptr; 57 | 58 | ::evconnlistener *acceptListenerPtr_ = nullptr; 59 | }; 60 | 61 | } 62 | } 63 | 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /modules/network/sessionMgr.h: -------------------------------------------------------------------------------- 1 | #ifndef _SESSION_MANAGER_HEADER_ 2 | #define _SESSION_MANAGER_HEADER_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace block 14 | { 15 | namespace network 16 | { 17 | class SessionCloseHandler; 18 | class SessionHandler; 19 | class Session; 20 | 21 | class OBuffer; 22 | class IBuffer; 23 | class MsgBinder; 24 | 25 | typedef std::shared_ptr SessionPtr; 26 | 27 | class SessionMgr 28 | { 29 | public: 30 | ~SessionMgr(); 31 | SessionMgr(Module *base); 32 | 33 | void addClose(int fd); 34 | void addConnect(int fd); 35 | 36 | void addMessage(block::ArgsPtr args); 37 | 38 | void exec(); 39 | 40 | SessionPtr find(int fd); 41 | SessionPtr findByModule(block::ModuleID module_id); 42 | 43 | SessionPtr makeSession(int fd, block::ModuleID module_id, ::bufferevent *bev); 44 | 45 | int curMaxConnect() const; 46 | 47 | private: 48 | 49 | typedef std::unordered_map SessionQueue; 50 | SessionQueue sessionQueue_; 51 | SessionQueue sessionQueueByModule_; 52 | 53 | std::vector disconnectVec_; 54 | std::vector connectVec_; 55 | 56 | std::queue messageQueue_; 57 | 58 | block::ModuleID target_ = block::ModuleNil; 59 | uint32_t sessionIndex_; 60 | 61 | // tmp 62 | block::Module *basePtr_; 63 | }; 64 | } 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(core) 2 | 3 | #引用头文件目录 4 | if(WIN32) 5 | INCLUDE_DIRECTORIES( 6 | ${BLOCK_SOURCE_DIR}/3rd/fmt 7 | ${BLOCK_SOURCE_DIR}/3rd/glog/src 8 | ) 9 | endif() 10 | 11 | if(UNIX) 12 | set(CMAKE_CXX_FLAGS "-std=c++1y ${CMAKE_CXX_FLAGS}") 13 | 14 | INCLUDE_DIRECTORIES( 15 | ${BLOCK_SOURCE_DIR}/lib/glog/include 16 | ${BLOCK_SOURCE_DIR}/lib/fmt/include 17 | ) 18 | endif() 19 | 20 | if (APPLE) 21 | message("APPLE") 22 | INCLUDE_DIRECTORIES( 23 | ${BLOCK_SOURCE_DIR}/3rd/fmt 24 | /usr/local/Cellar/gflags/2.2.1/include 25 | /usr/local/Cellar/glog/0.3.5_3/include 26 | ) 27 | endif() 28 | 29 | Add_Definitions("-DGLOG_NO_ABBREVIATED_SEVERITIES") 30 | 31 | #引用库目录 32 | LINK_DIRECTORIES( 33 | ) 34 | 35 | FILE(GLOB_RECURSE SRC "*.cpp" "*.h" "*.hpp") 36 | ADD_LIBRARY(core STATIC ${SRC}) 37 | 38 | if(MSVC) 39 | # Use the static C library for all build types 40 | foreach(var 41 | CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE 42 | CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO 43 | CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE 44 | CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO 45 | ) 46 | if(${var} MATCHES "/MD") 47 | string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}") 48 | endif() 49 | endforeach() 50 | 51 | SET(LIBRARY_OUTPUT_PATH ${BLOCK_SOURCE_DIR}/lib/win) 52 | elseif(UNIX) 53 | SET(LIBRARY_OUTPUT_PATH ${BLOCK_SOURCE_DIR}/lib/) 54 | elseif(APPLE) 55 | SET(LIBRARY_OUTPUT_PATH ${BLOCK_SOURCE_DIR}/lib/) 56 | endif() 57 | 58 | -------------------------------------------------------------------------------- /core/dynamic_module_factory.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | // 如非必要尽量使用静态显示构建Module 8 | 9 | typedef std::function create_ins; 10 | 11 | class DynamicModuleFactory 12 | { 13 | public: 14 | static void * create(const std::string &name) 15 | { 16 | auto itr = class_map_.find(name); 17 | if (itr == class_map_.end()) { return nullptr; } 18 | 19 | return itr->second(); 20 | } 21 | 22 | static void regist(const std::string &name, create_ins func) 23 | { 24 | auto itr = class_map_.find(name); 25 | 26 | if (itr == class_map_.end()) { 27 | class_map_.insert(std::make_pair(name, func)); 28 | } 29 | } 30 | 31 | private: 32 | static std::map class_map_; 33 | }; 34 | 35 | // 避免对静态成员的重复定义 36 | #ifdef WIN32 37 | __declspec(selectany) std::map DynamicModuleFactory::class_map_; 38 | #else 39 | __attribute((weak)) std::map DynamicModuleFactory::class_map_; 40 | #endif 41 | 42 | struct DynamicRegister 43 | { 44 | DynamicRegister(const std::string &name, create_ins func) 45 | { 46 | DynamicModuleFactory::regist(name, func); 47 | } 48 | }; 49 | 50 | 51 | #define REGISTER_CLASS(class_name) \ 52 | class class_name##DynamicRegister { \ 53 | public: \ 54 | static void * new_instance() \ 55 | { \ 56 | return new class_name; \ 57 | } \ 58 | private: \ 59 | static DynamicRegister reg_; \ 60 | }; \ 61 | DynamicRegister class_name##DynamicRegister::reg_(#class_name, class_name##DynamicRegister::new_instance); 62 | -------------------------------------------------------------------------------- /modules/dbProxy/mysqlConnect.h: -------------------------------------------------------------------------------- 1 | #ifndef _GSF_MYSQL_CONNECTOR_HEADER_ 2 | #define _GSF_MYSQL_CONNECTOR_HEADER_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "mysql.h" 8 | 9 | namespace block 10 | { 11 | namespace modules 12 | { 13 | struct SqlStmt 14 | { 15 | SqlStmt() 16 | : result(nullptr) 17 | , stmt(nullptr) 18 | {} 19 | 20 | ~SqlStmt() 21 | { 22 | if (stmt) { 23 | mysql_free_result(result); 24 | mysql_stmt_close(stmt); 25 | } 26 | } 27 | 28 | uint32_t params; 29 | uint32_t columns; 30 | 31 | bool is_query; 32 | bool is_prepared; 33 | 34 | std::string sql = ""; 35 | 36 | MYSQL_RES* result; 37 | MYSQL_STMT* stmt; 38 | }; 39 | 40 | typedef std::shared_ptr SqlStmtPtr; 41 | 42 | class MysqlConnect 43 | { 44 | public: 45 | MysqlConnect(); 46 | ~MysqlConnect(); 47 | 48 | MysqlConnect(const MysqlConnect &) = delete; 49 | MysqlConnect & operator = (const MysqlConnect &) = delete; 50 | 51 | bool init(const std::string &host, int port, const std::string &user, const std::string &pwd, const std::string &name); 52 | 53 | bool insert(const std::string &query, const char *buf, unsigned long len); 54 | void update(const std::string &query, const char *buf, unsigned long len); 55 | 56 | void execSql(block::ModuleID target, int oper, const std::string &sql, std::function callback); 57 | 58 | private: 59 | 60 | void perpare(const std::string &sql, SqlStmtPtr &stmtPtr); 61 | 62 | private: 63 | MYSQL *basePtr_ = nullptr; 64 | 65 | std::unordered_map prepared_stmt_map; 66 | }; 67 | 68 | typedef std::shared_ptr MysqlPtr; 69 | } 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /modules/distributed/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(distributed) 2 | 3 | if(WIN32) 4 | #引用头文件目录 5 | INCLUDE_DIRECTORIES( 6 | ${BLOCK_SOURCE_DIR}/ 7 | ${BLOCK_SOURCE_DIR}/3rd/Libevent/include 8 | ${BLOCK_SOURCE_DIR}/3rd/fmt 9 | ${BLOCK_SOURCE_DIR}/3rd/glog/src 10 | ) 11 | 12 | #引用库目录 13 | LINK_DIRECTORIES( 14 | ) 15 | endif() 16 | if(UNIX) 17 | #引用头文件目录 18 | INCLUDE_DIRECTORIES( 19 | ${BLOCK_SOURCE_DIR}/ 20 | ${BLOCK_SOURCE_DIR}/lib/libevent/include 21 | ${BLOCK_SOURCE_DIR}/lib/fmt/include 22 | ${BLOCK_SOURCE_DIR}/lib/glog/include 23 | ) 24 | 25 | #引用库目录 26 | LINK_DIRECTORIES( 27 | ${BLOCK_SOURCE_DIR}/lib/ 28 | ) 29 | endif() 30 | 31 | if(APPLE) 32 | INCLUDE_DIRECTORIES( 33 | ${BLOCK_SOURCE_DIR}/3rd/fmt 34 | /usr/local/Cellar/libevent/2.1.8/include 35 | /usr/local/Cellar/gflags/2.2.1/include 36 | /usr/local/Cellar/glog/0.3.5_3/include 37 | ${BLOCK_SOURCE_DIR}/ 38 | ) 39 | endif() 40 | 41 | FILE(GLOB_RECURSE SRC "*.cpp" "*.h") 42 | ADD_LIBRARY(distributed STATIC ${SRC}) 43 | 44 | if(MSVC) 45 | # Use the static C library for all build types 46 | foreach(var 47 | CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE 48 | CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO 49 | CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE 50 | CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO 51 | ) 52 | if(${var} MATCHES "/MD") 53 | string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}") 54 | endif() 55 | endforeach() 56 | 57 | SET(LIBRARY_OUTPUT_PATH ${BLOCK_SOURCE_DIR}/lib/win) 58 | elseif(UNIX) 59 | SET(LIBRARY_OUTPUT_PATH ${BLOCK_SOURCE_DIR}/lib/) 60 | elseif(APPLE) 61 | endif() 62 | 63 | 64 | -------------------------------------------------------------------------------- /modules/network/msgBlock.h: -------------------------------------------------------------------------------- 1 | #ifndef _GSF_MSG_BLOCK_HEADER_ 2 | #define _GSF_MSG_BLOCK_HEADER_ 3 | 4 | #include 5 | #include 6 | 7 | namespace block 8 | { 9 | // 对二进制块做下简单封装, 方便回收内存。 10 | 11 | struct Block 12 | { 13 | Block(uint32_t size) 14 | { 15 | buf_ = (char*)malloc(size); 16 | size_ = size; 17 | pos_ = 0; 18 | } 19 | 20 | Block(SessionID fd, MsgID msg_id, const std::string &block) 21 | { 22 | auto _len = block.length(); 23 | size_ = _len + sizeof(MsgHeadLen) + sizeof(MsgID); 24 | pos_ = 0; 25 | 26 | buf_ = (char*)malloc(size_); 27 | 28 | push_head_len(size_, buf_ + pos_); 29 | push_msg_id(msg_id, buf_ + pos_); 30 | 31 | memcpy(buf_ + pos_, block.c_str(), _len); 32 | } 33 | 34 | void push_head_len(MsgHeadLen val, char *buf) 35 | { 36 | *(MsgHeadLen*)(void*)buf = val; 37 | pos_ += sizeof(MsgHeadLen); 38 | } 39 | 40 | void push_msg_id(MsgID val, char *buf) 41 | { 42 | *(MsgID*)(void*)buf = val; 43 | pos_ += sizeof(MsgID); 44 | } 45 | 46 | MsgID get_msg_id() 47 | { 48 | MsgID _id = *(MsgID*)(void*)(buf_ + sizeof(MsgHeadLen)); 49 | return _id; 50 | } 51 | 52 | int32_t get_body_size() 53 | { 54 | return (size_ - (sizeof(MsgHeadLen) + sizeof(MsgID))); 55 | } 56 | 57 | int32_t get_head_size() 58 | { 59 | return (sizeof(MsgHeadLen) + sizeof(MsgID)); 60 | } 61 | 62 | bool check() 63 | { 64 | MsgHeadLen _len = *(MsgHeadLen*)(void*)(buf_); 65 | if (_len != size_) { 66 | return false; 67 | } 68 | 69 | MsgID _id = get_msg_id(); 70 | if (_id <= 0 || _id > MsgMax) { 71 | return false; 72 | } 73 | 74 | return true; 75 | } 76 | 77 | ~Block() 78 | { 79 | free(buf_); 80 | size_ = 0; 81 | pos_ = 0; 82 | } 83 | 84 | char *buf_; 85 | uint32_t size_; 86 | uint32_t pos_; 87 | }; 88 | 89 | typedef std::shared_ptr BlockPtr; 90 | } 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /modules/luaAdapter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(luaAdapter) 2 | 3 | if(WIN32) 4 | #引用头文件目录 5 | INCLUDE_DIRECTORIES( 6 | ${BLOCK_SOURCE_DIR}/ 7 | ${BLOCK_SOURCE_DIR}/3rd/lua-5.3.4/src 8 | ${BLOCK_SOURCE_DIR}/3rd/sol2 9 | ${BLOCK_SOURCE_DIR}/3rd/fmt 10 | ${BLOCK_SOURCE_DIR}/3rd/glog/src 11 | ) 12 | Add_Definitions("-DGLOG_NO_ABBREVIATED_SEVERITIES") 13 | #引用库目录 14 | LINK_DIRECTORIES( 15 | ) 16 | 17 | endif() 18 | if(UNIX) 19 | #引用头文件目录 20 | INCLUDE_DIRECTORIES( 21 | ${BLOCK_SOURCE_DIR}/ 22 | ${BLOCK_SOURCE_DIR}/lib/glog/include 23 | ${BLOCK_SOURCE_DIR}/lib/lua 24 | ${BLOCK_SOURCE_DIR}/3rd/sol2 25 | ${BLOCK_SOURCE_DIR}/lib/fmt/include 26 | ) 27 | 28 | #引用库目录 29 | LINK_DIRECTORIES( 30 | ${BLOCK_SOURCE_DIR}/lib/ 31 | ) 32 | endif() 33 | 34 | if(APPLE) 35 | INCLUDE_DIRECTORIES( 36 | ${BLOCK_SOURCE_DIR}/3rd/fmt 37 | /usr/local/Cellar/lua/5.3.4_2/include 38 | ${BLOCK_SOURCE_DIR}/3rd/sol2 39 | /usr/local/Cellar/gflags/2.2.1/include 40 | /usr/local/Cellar/glog/0.3.5_3/include 41 | ${BLOCK_SOURCE_DIR}/ 42 | ) 43 | endif() 44 | 45 | FILE(GLOB_RECURSE SRC "*.cpp" "*.h" ".hpp") 46 | ADD_LIBRARY(luaAdapter STATIC ${SRC}) 47 | 48 | if(MSVC) 49 | # Use the static C library for all build types 50 | foreach(var 51 | CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE 52 | CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO 53 | CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE 54 | CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO 55 | ) 56 | if(${var} MATCHES "/MD") 57 | string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}") 58 | endif() 59 | endforeach() 60 | 61 | SET(LIBRARY_OUTPUT_PATH ${BLOCK_SOURCE_DIR}/lib/win) 62 | elseif(UNIX) 63 | SET(LIBRARY_OUTPUT_PATH ${BLOCK_SOURCE_DIR}/lib) 64 | elseif(APPLE) 65 | endif() 66 | 67 | 68 | -------------------------------------------------------------------------------- /core/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace block 6 | { 7 | typedef int64_t ModuleID; 8 | static const int64_t ModuleNil = 0; 9 | 10 | typedef int32_t EventID; 11 | static const int32_t EventNil = INT32_MAX; 12 | 13 | typedef uint64_t TimerID; 14 | static const uint64_t TimerNil = UINT64_MAX; 15 | 16 | typedef uint16_t SessionID; 17 | static const uint16_t SessionNil = UINT16_MAX; 18 | 19 | typedef int32_t NodeID; 20 | static const int32_t NodeNil = INT32_MAX; 21 | 22 | typedef uint16_t MsgID; 23 | static const uint16_t MsgNil = UINT16_MAX; 24 | static const uint16_t MsgMax = UINT16_MAX; 25 | 26 | static const uint16_t LogErr = 3; 27 | static const uint16_t LogWarning = 2; 28 | static const uint16_t LogInfo = 1; 29 | static const uint16_t LogDebug = 0; 30 | 31 | typedef int32_t ErrorID; 32 | static const int32_t ErrNil = INT32_MAX; 33 | 34 | typedef int16_t MsgHeadLen; 35 | static const int32_t MsgHeadLenNil = 0; 36 | 37 | static const uint16_t ARGS_MAX_SIZE = 1024; // 38 | 39 | static const uint32_t NETWORK_CONNECT_MAX = 65534; // 40 | static const uint32_t SESSION_READ_BUFFER_SIZE = 0; // 41 | static const uint32_t SESSION_WRITE_BUFFER_SIZE = 0; // 42 | 43 | static const uint32_t MSGLEN_CLIENTSIZE = 1024 * 4; // 44 | static const uint32_t MSGLEN_RPCSIZE = 1024 * 10; // 45 | 46 | // args type 47 | static const uint8_t at_uint8 = 1; 48 | static const uint8_t at_int8 = 2; 49 | static const uint8_t at_uint16 = 3; 50 | static const uint8_t at_int16 = 4; 51 | static const uint8_t at_uint32 = 5; 52 | static const uint8_t at_int32 = 6; 53 | static const uint8_t at_uint64 = 7; 54 | static const uint8_t at_int64 = 8; 55 | static const uint8_t at_bool = 9; 56 | static const uint8_t at_float = 10; 57 | static const uint8_t at_double = 11; 58 | static const uint8_t at_string = 12; 59 | static const uint8_t at_list = 13; 60 | static const uint8_t at_vec = 14; 61 | static const uint8_t at_map = 15; 62 | static const uint8_t at_block = 16; 63 | static const uint8_t at_eof = 20; 64 | } 65 | -------------------------------------------------------------------------------- /modules/dbProxy/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(dbProxy) 2 | 3 | if(WIN32) 4 | #引用头文件目录 5 | INCLUDE_DIRECTORIES( 6 | ${BLOCK_SOURCE_DIR}/ 7 | ${BLOCK_SOURCE_DIR}/3rd/fmt 8 | ${BLOCK_SOURCE_DIR}/3rd/glog/src 9 | ${BLOCK_SOURCE_DIR}/3rd/mysql_connect/include 10 | ${BLOCK_SOURCE_DIR}/3rd/redis/deps/hiredis 11 | ) 12 | Add_Definitions("-DGLOG_NO_ABBREVIATED_SEVERITIES") 13 | #引用库目录 14 | LINK_DIRECTORIES( 15 | ) 16 | 17 | endif() 18 | if(UNIX) 19 | #引用头文件目录 20 | INCLUDE_DIRECTORIES( 21 | ${BLOCK_SOURCE_DIR}/ 22 | ${BLOCK_SOURCE_DIR}/lib/fmt/include 23 | ${BLOCK_SOURCE_DIR}/lib/mysql_connector/include 24 | ${BLOCK_SOURCE_DIR}/lib/hiredis 25 | ${BLOCK_SOURCE_DIR}/lib/glog/include 26 | ) 27 | 28 | #引用库目录 29 | LINK_DIRECTORIES( 30 | ${BLOCK_SOURCE_DIR}/lib/ 31 | ) 32 | endif() 33 | 34 | 35 | if(APPLE) 36 | INCLUDE_DIRECTORIES( 37 | ${BLOCK_SOURCE_DIR}/3rd/fmt 38 | /usr/local/Cellar/hiredis/0.13.3/include/hiredis 39 | /usr/local/Cellar/mysql-connector-c/6.1.11/include 40 | /usr/local/Cellar/gflags/2.2.1/include 41 | /usr/local/Cellar/glog/0.3.5_3/include 42 | ${BLOCK_SOURCE_DIR}/ 43 | ) 44 | endif() 45 | 46 | FILE(GLOB_RECURSE SRC "*.cpp" "*.h" "*.hpp") 47 | ADD_LIBRARY(dbProxy STATIC ${SRC}) 48 | 49 | if(MSVC) 50 | # Use the static C library for all build types 51 | foreach(var 52 | CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE 53 | CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO 54 | CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE 55 | CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO 56 | ) 57 | if(${var} MATCHES "/MD") 58 | string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}") 59 | endif() 60 | endforeach() 61 | 62 | SET(LIBRARY_OUTPUT_PATH ${BLOCK_SOURCE_DIR}/lib/win) 63 | elseif(UNIX) 64 | SET(LIBRARY_OUTPUT_PATH ${BLOCK_SOURCE_DIR}/lib/) 65 | elseif(APPLE) 66 | endif() 67 | 68 | 69 | -------------------------------------------------------------------------------- /utils/logger.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../core/types.h" 4 | 5 | #define GOOGLE_GLOG_DLL_DECL 6 | #include 7 | 8 | #ifdef WIN32 9 | #include 10 | #else 11 | #include 12 | #endif // WIN32 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "logger_impl.hpp" 20 | 21 | namespace block 22 | { 23 | namespace utils 24 | { 25 | class Logger 26 | { 27 | public: 28 | Logger() {} 29 | ~Logger() {} 30 | 31 | void init(const std::string &appName) 32 | { 33 | impl_.init(appName); 34 | } 35 | 36 | // -- 调试日志 -- 37 | template 38 | void DEBUG(const std::string &content, P&& ...values) 39 | { 40 | impl_.DEBUG_LOG(content, values...); 41 | } 42 | void DEBUG(const std::string &content) 43 | { 44 | impl_.DEBUG_LOG(content); 45 | } 46 | 47 | // -- 诊断日志 -- 48 | template 49 | void INFO(const std::string &content, P &&... values) 50 | { 51 | impl_.INFO_LOG(content, values...); 52 | } 53 | void INFO(const std::string &content) 54 | { 55 | impl_.INFO_LOG(content); 56 | } 57 | 58 | template 59 | void ERR(const std::string &content, P &&... values) 60 | { 61 | impl_.ERR_LOG(content, values...); 62 | } 63 | void ERR(const std::string &content) 64 | { 65 | impl_.ERR_LOG(content); 66 | } 67 | 68 | template 69 | void WARN(const std::string &content, P &&... values) 70 | { 71 | impl_.WARN_LOG(content, values...); 72 | } 73 | void WARN(const std::string &content) 74 | { 75 | impl_.WARN_LOG(content); 76 | } 77 | 78 | // -- 统计日志 -- 79 | // behavior, player, time, args 80 | template 81 | void RECORD(const std::string &behavior, uint32_t player, uint32_t time, const std::string &content, P&& ...values) 82 | { 83 | impl_.RECORD_LOG(behavior, player, time, content, values...); 84 | } 85 | 86 | private: 87 | LoggerImpl impl_; 88 | }; 89 | } 90 | 91 | } 92 | 93 | -------------------------------------------------------------------------------- /core/application.cpp: -------------------------------------------------------------------------------- 1 | #include "application.h" 2 | 3 | 4 | block::Application::Application() 5 | { 6 | } 7 | 8 | std::string block::Application::getName() const 9 | { 10 | return impl_.getName(); 11 | } 12 | 13 | void block::Application::initCfg(const block::AppConfig &cfg) 14 | { 15 | impl_.initCfg(cfg); 16 | } 17 | 18 | block::ModuleID block::Application::createDynamicModule(const std::string &moduleType) 19 | { 20 | return impl_.createDynamicModule(moduleType); 21 | } 22 | 23 | void block::Application::deleteModule(block::ModuleID moduleID) 24 | { 25 | impl_.deleteModule(moduleID); 26 | } 27 | 28 | block::ModuleID block::Application::getModuleID(const std::string &moduleName) const 29 | { 30 | return impl_.getModuleID(moduleName); 31 | } 32 | 33 | bool block::Application::hasModule(block::ModuleID moduleid) 34 | { 35 | return impl_.hasModule(moduleid); 36 | } 37 | 38 | const block::AppConfig & block::Application::getAppCfg() 39 | { 40 | return impl_.getAppCfg(); 41 | } 42 | 43 | int64_t block::Application::getUUID() 44 | { 45 | return impl_.uuid(); 46 | } 47 | 48 | void block::Application::run() 49 | { 50 | impl_.run(); 51 | } 52 | 53 | void block::Application::exit() 54 | { 55 | impl_.exit(); 56 | } 57 | 58 | uint64_t block::Application::getSystemTick() 59 | { 60 | return impl_.getSystemTick(); 61 | } 62 | 63 | block::utils::Logger block::Application::getLogger() 64 | { 65 | return impl_.getLogger(); 66 | } 67 | 68 | block::utils::Timer & block::Application::getTimer() 69 | { 70 | return impl_.getTimer(); 71 | } 72 | 73 | void block::Application::reactorRegist(block::ModuleID moduleID, block::EventID event) 74 | { 75 | impl_.reactorRegist(moduleID, event); 76 | } 77 | 78 | void block::Application::reactorDispatch(block::ModuleID self, block::ModuleID target, block::EventID event, block::ArgsPtr args) 79 | { 80 | impl_.reactorDispatch(self, target, event, std::move(args)); 81 | } 82 | 83 | void block::Application::reactorBoardcast(block::ModuleID self, block::EventID event, block::ArgsPtr args) 84 | { 85 | impl_.reactorBoardcast(self, event, std::move(args)); 86 | } 87 | -------------------------------------------------------------------------------- /modules/network/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(network) 2 | 3 | #引用头文件目录 4 | if(WIN32) 5 | INCLUDE_DIRECTORIES( 6 | ${BLOCK_SOURCE_DIR}/3rd/Libevent/include 7 | ${BLOCK_SOURCE_DIR}/3rd/fmt 8 | ${BLOCK_SOURCE_DIR}/3rd/glog/src 9 | ${BLOCK_SOURCE_DIR}/ 10 | ) 11 | endif() 12 | 13 | if(UNIX) 14 | INCLUDE_DIRECTORIES( 15 | ${BLOCK_SOURCE_DIR}/lib/libevent/include 16 | ${BLOCK_SOURCE_DIR}/lib/fmt/include 17 | ${BLOCK_SOURCE_DIR}/lib/glog/include 18 | ${BLOCK_SOURCE_DIR}/ 19 | ) 20 | endif() 21 | 22 | if(APPLE) 23 | INCLUDE_DIRECTORIES( 24 | /usr/local/Cellar/libevent/2.1.8/include 25 | ${BLOCK_SOURCE_DIR}/3rd/fmt 26 | /usr/local/Cellar/gflags/2.2.1/include 27 | /usr/local/Cellar/glog/0.3.5_3/include 28 | ${BLOCK_SOURCE_DIR}/ 29 | ) 30 | endif() 31 | 32 | Add_Definitions("-DGLOG_NO_ABBREVIATED_SEVERITIES") 33 | 34 | #引用库目录 35 | if(WIN32) 36 | LINK_DIRECTORIES( 37 | ${BLOCK_SOURCE_DIR}/lib 38 | ) 39 | elseif(UNIX) 40 | LINK_DIRECTORIES( 41 | ${BLOCK_SOURCE_DIR}/lib/libevent/lib 42 | ${BLOCK_SOURCE_DIR}/lib 43 | ) 44 | elseif(APPLE) 45 | LINK_DIRECTORIES( 46 | ${BLOCK_SOURCE_DIR}/lib/apple/lib 47 | ) 48 | endif() 49 | 50 | 51 | FILE(GLOB_RECURSE SRC "*.cpp" "*.h") 52 | ADD_LIBRARY(network STATIC ${SRC}) 53 | 54 | if(MSVC) 55 | # Use the static C library for all build types 56 | foreach(var 57 | CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE 58 | CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO 59 | CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE 60 | CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO 61 | ) 62 | if(${var} MATCHES "/MD") 63 | string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}") 64 | 65 | endif() 66 | endforeach() 67 | 68 | SET(LIBRARY_OUTPUT_PATH ${BLOCK_SOURCE_DIR}/lib/win) 69 | #TARGET_LINK_LIBRARIES(network ws2_32.lib) 项目本身是静态库不需要链接静态库 70 | elseif(UNIX) 71 | SET(LIBRARY_OUTPUT_PATH ${BLOCK_SOURCE_DIR}/lib/) 72 | elseif(APPLE) 73 | SET(LIBRARY_OUTPUT_PATH ${BLOCK_SOURCE_DIR}/lib/) 74 | endif() 75 | -------------------------------------------------------------------------------- /modules/luaAdapter/luaAdapter.h: -------------------------------------------------------------------------------- 1 | #ifndef _GSF_LUA_PROXY_HEADER_ 2 | #define _GSF_LUA_PROXY_HEADER_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace block 14 | { 15 | namespace modules 16 | { 17 | enum LuaAppState 18 | { 19 | BEFORE_INIT = 0, 20 | INIT, 21 | EXECUTE, 22 | SHUT, 23 | AFTER_SHUT, 24 | }; 25 | 26 | struct LuaProxy 27 | { 28 | LuaProxy() 29 | : app_state_(LuaAppState::BEFORE_INIT) 30 | {} 31 | 32 | sol::state state_; 33 | std::string dir_name_; 34 | std::string file_name_; 35 | LuaAppState app_state_; 36 | 37 | std::array, 5> call_list_; 38 | }; 39 | 40 | typedef std::shared_ptr LuaProxyPtr; 41 | 42 | class LuaAdapterModule 43 | : public block::Module 44 | { 45 | 46 | public: 47 | LuaAdapterModule(const std::string &name) 48 | : Module(name) 49 | {} 50 | 51 | void before_init() override; 52 | void init() override; 53 | void execute() override; 54 | void shut() override; 55 | 56 | private: 57 | //sol::variadic_args args 58 | 59 | void llogDebug(const std::string &content); 60 | void llogInfo(const std::string &content); 61 | void llogWarning(const std::string &content); 62 | void llogError(const std::string &content); 63 | 64 | uint64_t ldelay(int32_t milliseconds, sol::function callback); 65 | uint64_t ldelayDay(int32_t hour, int32_t minute, sol::function callback); 66 | void lrmvDelay(uint64_t timerID); 67 | 68 | //代理下event的dispatch 和 listen 接口,因为要在这里集中捕获下lua产生的异常。 69 | void ldispatch(block::ModuleID target, block::EventID event, const std::string &buf); 70 | 71 | int llisten(uint32_t event, const sol::function &func); 72 | 73 | void lrpc(uint32_t event, int32_t moduleid, const std::string &buf); 74 | 75 | //void eDistory(block::ModuleID target, block::ArgsPtr args); 76 | void eReload(block::ModuleID target, block::ArgsPtr args); 77 | 78 | void create(); 79 | 80 | LuaProxyPtr proxyPtr_ = nullptr; 81 | 82 | protected: 83 | std::string dir_ = ""; 84 | std::string name_ = ""; 85 | 86 | private: 87 | 88 | bool reloading = false; 89 | 90 | }; 91 | } 92 | } 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /core/module.cpp: -------------------------------------------------------------------------------- 1 | #include "module.h" 2 | #include "application.h" 3 | 4 | void block::Module::before_init() 5 | { 6 | 7 | } 8 | 9 | void block::Module::init() 10 | { 11 | 12 | } 13 | 14 | void block::Module::execute() 15 | { 16 | 17 | } 18 | 19 | void block::Module::shut() 20 | { 21 | 22 | } 23 | 24 | void block::Module::after_shut() 25 | { 26 | 27 | } 28 | 29 | void block::Module::listen(block::EventID event, ListenFunc func) 30 | { 31 | mailboxPtr_->listen(event, func); 32 | } 33 | 34 | void block::Module::dispatch(block::ModuleID target, block::EventID event, block::ArgsPtr args) 35 | { 36 | mailboxPtr_->dispatch(target, event, std::move(args)); 37 | } 38 | 39 | void block::Module::boardcast(block::EventID event, ArgsPtr args) 40 | { 41 | mailboxPtr_->boardcast(event, std::move(args)); 42 | } 43 | 44 | block::Module::Module(const std::string &name) 45 | : name_(name) 46 | #ifdef WATCH_PERF 47 | , tick_consume_(0) 48 | #endif // WATCH_PERF 49 | 50 | { 51 | mailboxPtr_ = std::make_shared(this); 52 | } 53 | 54 | block::Module::~Module() 55 | { 56 | 57 | } 58 | 59 | block::MailBox::MailBox(Module *ptr) 60 | : basePtr_(ptr) 61 | { 62 | 63 | } 64 | 65 | void block::MailBox::listen(block::EventID event, ListenFunc func) 66 | { 67 | auto _itr = listenMap_.find(event); 68 | if (_itr != listenMap_.end()) { 69 | WARN_FMTLOG("[BLOCK] mailbox repeat regist event:{}", event); 70 | } 71 | else { 72 | APP.reactorRegist(basePtr_->getModuleID(), event); 73 | 74 | listenMap_.insert(std::make_pair(event, func)); 75 | } 76 | } 77 | 78 | void block::MailBox::dispatch(block::ModuleID target, block::EventID event, block::ArgsPtr args) 79 | { 80 | APP.reactorDispatch(basePtr_->getModuleID(), target, event, std::move(args)); 81 | } 82 | 83 | void block::MailBox::boardcast(block::EventID event, ArgsPtr args) 84 | { 85 | APP.reactorBoardcast(basePtr_->getModuleID(), event, std::move(args)); 86 | } 87 | 88 | void block::MailBox::pull() 89 | { 90 | while (!taskQueue_.empty()) 91 | { 92 | TaskInfo * info = taskQueue_.front(); 93 | 94 | auto _itr = listenMap_.find(info->event_); 95 | if (_itr != listenMap_.end()) { 96 | _itr->second(info->target_, std::move(info->args_)); 97 | } 98 | else { 99 | WARN_FMTLOG("mailbox : pull can't find module : {}", basePtr_->getModuleID()); 100 | } 101 | 102 | taskQueue_.pop(); 103 | } 104 | } 105 | 106 | void block::MailBox::push(TaskInfo *info) 107 | { 108 | taskQueue_.push(info); 109 | } 110 | -------------------------------------------------------------------------------- /utils/dump.lua: -------------------------------------------------------------------------------- 1 | function dump ( t ) 2 | local print_r_cache={} 3 | local function sub_print_r(t,indent) 4 | if (print_r_cache[tostring(t)]) then 5 | print(indent.."*"..tostring(t)) 6 | else 7 | print_r_cache[tostring(t)]=true 8 | if (type(t)=="table") then 9 | for pos,val in pairs(t) do 10 | if (type(val)=="table") then 11 | print(indent.."["..pos.."] => "..tostring(t).." {") 12 | sub_print_r(val,indent..string.rep(" ",string.len(pos)+8)) 13 | print(indent..string.rep(" ",string.len(pos)+6).."}") 14 | elseif (type(val)=="string") then 15 | print(indent.."["..pos..'] => "'..val..'"') 16 | else 17 | print(indent.."["..pos.."] => "..tostring(val)) 18 | end 19 | end 20 | else 21 | print(indent..tostring(t)) 22 | end 23 | end 24 | end 25 | if (type(t)=="table") then 26 | print(tostring(t).." {") 27 | sub_print_r(t," ") 28 | print("}") 29 | else 30 | sub_print_r(t," ") 31 | end 32 | print() 33 | end 34 | 35 | function dumpStr(t) 36 | local _str = "" 37 | local print_r_cache={} 38 | local function sub_print_r(t,indent) 39 | if (print_r_cache[tostring(t)]) then 40 | _str = _str .. indent.."*"..tostring(t) .. '\n' 41 | else 42 | print_r_cache[tostring(t)]=true 43 | if (type(t)=="table") then 44 | for pos,val in pairs(t) do 45 | if (type(val)=="table") then 46 | _str = _str .. indent.."["..pos.."] => "..tostring(t).." {\n" 47 | sub_print_r(val,indent..string.rep(" ",string.len(pos)+8)) 48 | _str = _str .. indent..string.rep(" ",string.len(pos)+6).."}\n" 49 | elseif (type(val)=="string") then 50 | _str = _str .. indent.."["..pos..'] => "'..val..'"\n' 51 | else 52 | _str = _str .. indent.."["..pos.."] => "..tostring(val) .. '\n' 53 | end 54 | end 55 | else 56 | _str = _str .. indent..tostring(t) .. '\n' 57 | end 58 | end 59 | end 60 | if (type(t)=="table") then 61 | _str = _str .. tostring(t).." {\n" 62 | sub_print_r(t," ") 63 | _str = _str .. "}\n" 64 | else 65 | sub_print_r(t,"") 66 | end 67 | 68 | return _str 69 | end -------------------------------------------------------------------------------- /modules/network/sessionMgr.cpp: -------------------------------------------------------------------------------- 1 | #include "sessionMgr.h" 2 | #include "session.h" 3 | 4 | #include 5 | 6 | block::network::SessionMgr::SessionMgr(block::Module *base) 7 | : basePtr_(base) 8 | { 9 | } 10 | 11 | block::network::SessionMgr::~SessionMgr() 12 | { 13 | 14 | } 15 | 16 | block::network::SessionPtr block::network::SessionMgr::makeSession(int fd, block::ModuleID module_id, ::bufferevent *bev) 17 | { 18 | target_ = module_id; 19 | 20 | auto _session_ptr = std::make_shared(fd, module_id, this, bev); 21 | sessionQueue_.insert(std::make_pair(fd, _session_ptr)); 22 | sessionQueueByModule_.insert(std::make_pair(module_id, _session_ptr)); 23 | 24 | return _session_ptr; 25 | } 26 | 27 | block::network::SessionPtr block::network::SessionMgr::find(int fd) 28 | { 29 | auto _session_itr = sessionQueue_.find(fd); 30 | if (_session_itr != sessionQueue_.end()){ 31 | return _session_itr->second; 32 | } 33 | 34 | return nullptr; 35 | } 36 | 37 | block::network::SessionPtr block::network::SessionMgr::findByModule(block::ModuleID module_id) 38 | { 39 | auto _session_ptr = sessionQueueByModule_.find(module_id); 40 | 41 | if (_session_ptr != sessionQueueByModule_.end()) { 42 | return _session_ptr->second; 43 | } 44 | 45 | return nullptr; 46 | } 47 | 48 | void block::network::SessionMgr::addClose(int fd) 49 | { 50 | disconnectVec_.push_back(fd); 51 | } 52 | 53 | void block::network::SessionMgr::addConnect(int fd) 54 | { 55 | connectVec_.push_back(fd); 56 | } 57 | 58 | 59 | void block::network::SessionMgr::addMessage(block::ArgsPtr args) 60 | { 61 | messageQueue_.push(std::move(args)); 62 | } 63 | 64 | void block::network::SessionMgr::exec() 65 | { 66 | for (int fd : disconnectVec_) 67 | { 68 | auto _itr = sessionQueue_.find(fd); 69 | 70 | if (_itr != sessionQueue_.end()) { 71 | 72 | auto _mitr = sessionQueueByModule_.find(_itr->second->getModuleID()); 73 | if (_mitr != sessionQueueByModule_.end()) { 74 | sessionQueueByModule_.erase(_mitr); 75 | } 76 | 77 | sessionQueue_.erase(_itr); 78 | basePtr_->dispatch(target_, block::event::tcp_dis_connect, block::makeArgs(fd)); 79 | } 80 | } 81 | 82 | disconnectVec_.clear(); 83 | 84 | for (int fd : connectVec_) 85 | { 86 | basePtr_->dispatch(target_, block::event::tcp_new_connect, block::makeArgs(fd)); 87 | } 88 | 89 | connectVec_.clear(); 90 | 91 | while (!messageQueue_.empty()) { 92 | 93 | basePtr_->dispatch(target_, block::event::tcp_recv, std::move(messageQueue_.front())); 94 | 95 | messageQueue_.pop(); 96 | } 97 | } 98 | 99 | int block::network::SessionMgr::curMaxConnect() const 100 | { 101 | return 0; 102 | } -------------------------------------------------------------------------------- /core/application.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "appImpl.hpp" 4 | 5 | namespace block 6 | { 7 | class Application : public block::utils::Singleton 8 | { 9 | friend struct MailBox; 10 | public: 11 | Application(); 12 | 13 | /*! 14 | 获取App的名称 15 | **/ 16 | std::string getName() const; 17 | 18 | /*! 19 | 通过名字获取某个Module的实例ID, 仅支持静态创建的Module。 20 | **/ 21 | block::ModuleID getModuleID(const std::string &moduleName) const; 22 | 23 | /*! 24 | * 判断app中是否存在该module 25 | * */ 26 | bool hasModule(block::ModuleID moduleid); 27 | 28 | /*! 29 | 获取App的配置结构 30 | **/ 31 | const block::AppConfig & getAppCfg(); 32 | 33 | /*! 34 | 获取一个uuid 35 | **/ 36 | int64_t getUUID(); 37 | 38 | /*! 39 | 获取app当前的毫秒数 40 | **/ 41 | uint64_t getSystemTick(); 42 | 43 | /*! 44 | 初始化配置文件 45 | **/ 46 | void initCfg(const block::AppConfig &cfg); 47 | 48 | /*! 49 | 创建一个静态的Module (只能在App.run之前调用 50 | **/ 51 | template 52 | void createModule(T *module); 53 | 54 | /*! 55 | 创建一个动态的Module 56 | **/ 57 | block::ModuleID createDynamicModule(const std::string &moduleType); 58 | 59 | /*! 60 | 从App中删除一个Module 61 | **/ 62 | void deleteModule(block::ModuleID moduleID); 63 | 64 | /*! 65 | App的主循环 66 | **/ 67 | void run(); 68 | 69 | /*! 70 | App退出函数 71 | **/ 72 | void exit(); 73 | 74 | utils::Logger getLogger(); 75 | utils::Timer & getTimer(); 76 | 77 | protected: 78 | void reactorRegist(block::ModuleID moduleID, block::EventID event); 79 | void reactorDispatch(block::ModuleID self, block::ModuleID target, block::EventID event, block::ArgsPtr args); 80 | void reactorBoardcast(block::ModuleID self, block::EventID event, block::ArgsPtr args); 81 | private: 82 | AppImpl impl_; 83 | }; 84 | 85 | template 86 | void block::Application::createModule(T *module) 87 | { 88 | impl_.createModule(module); 89 | } 90 | 91 | #define APP block::Application::get_ref() 92 | 93 | #define TIMER APP.getTimer() 94 | 95 | #define WARN_LOG(content) \ 96 | APP.getLogger().WARN(content) 97 | #define WARN_FMTLOG(content, ...) \ 98 | APP.getLogger().WARN(content, ##__VA_ARGS__) 99 | 100 | #define INFO_LOG(content) \ 101 | APP.getLogger().INFO(content) 102 | #define INFO_FMTLOG(content, ...)\ 103 | APP.getLogger().INFO(content, ##__VA_ARGS__) 104 | 105 | #define DEBUG_LOG(content)\ 106 | APP.getLogger().DEBUG(content) 107 | #define DEBUG_FMTLOG(content, ...)\ 108 | APP.getLogger().DEBUG(content, ##__VA_ARGS__) 109 | 110 | #define ERROR_LOG(content)\ 111 | APP.getLogger().ERR(content) 112 | #define ERROR_FMTLOG(content, ...)\ 113 | APP.getLogger().ERR(content, ##__VA_ARGS__) 114 | 115 | } 116 | -------------------------------------------------------------------------------- /core/module.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "args.h" 15 | #include "types.h" 16 | 17 | #define WATCH_PERF 18 | 19 | namespace block 20 | { 21 | typedef std::function CallbackFunc; 22 | typedef std::function ListenFunc; 23 | 24 | typedef std::function RpcCallback; 25 | 26 | class Module; 27 | struct TaskInfo 28 | { 29 | block::ModuleID target_; 30 | block::EventID event_; 31 | block::ArgsPtr args_; 32 | }; 33 | 34 | /* 35 | 36 | */ 37 | struct MailBox 38 | { 39 | MailBox(Module *ptr); 40 | 41 | /*! 42 | 43 | **/ 44 | void listen(block::EventID event, ListenFunc func); 45 | 46 | /*! 47 | 48 | **/ 49 | void dispatch(block::ModuleID target, block::EventID event, block::ArgsPtr args); 50 | 51 | 52 | /**! 53 | 54 | */ 55 | void boardcast(block::EventID event, ArgsPtr args); 56 | 57 | void pull(); 58 | void push(TaskInfo *info); 59 | 60 | private: 61 | 62 | typedef std::queue TaskQueue; 63 | TaskQueue taskQueue_; 64 | 65 | std::unordered_map listenMap_; 66 | 67 | Module *basePtr_ = nullptr; 68 | }; 69 | 70 | typedef std::shared_ptr MailBoxPtr; 71 | 72 | class Module 73 | { 74 | friend class AppImpl; 75 | friend class Reactor; 76 | friend class Application; 77 | 78 | public: 79 | Module(const std::string &name); 80 | virtual ~Module(); 81 | 82 | block::ModuleID getModuleID() { return module_id_; } 83 | std::string & getModuleName() { return name_; } 84 | 85 | void listen(block::EventID event, ListenFunc func); 86 | void dispatch(block::ModuleID target, block::EventID event, block::ArgsPtr args); 87 | void boardcast(block::EventID event, ArgsPtr args); 88 | 89 | protected: 90 | virtual void before_init(); 91 | virtual void init(); 92 | 93 | virtual void execute(); 94 | 95 | virtual void shut(); 96 | virtual void after_shut(); 97 | 98 | protected: 99 | void setAvailable(bool flag) { available_ = flag; } 100 | bool getAvailable() const { return available_; } 101 | 102 | void setID(block::ModuleID id) { module_id_ = id; } 103 | 104 | std::string name_; 105 | 106 | bool available_ = false; 107 | 108 | #ifdef WATCH_PERF 109 | int64_t tick_consume_; 110 | void add_tick_consume(int64_t c) { tick_consume_ += c; } 111 | 112 | virtual std::string get_tick_info(uint32_t count, uint32_t tick_count) 113 | { 114 | auto c = static_cast(tick_consume_ / 1000 / count); 115 | char buf[20]; 116 | snprintf(buf, sizeof(buf), "%.3f", c); 117 | #ifdef WIN32 118 | sscanf_s(buf, "%f", &c); 119 | #else 120 | sscanf(buf, "%f", &c); 121 | #endif 122 | std::string _info = getModuleName() + ":" + (buf) + " ms\t"; 123 | tick_consume_ = 0; 124 | return _info; 125 | } 126 | #endif // WATCH_PERF 127 | 128 | //! 129 | private: 130 | block::ModuleID module_id_ = block::ModuleNil; 131 | 132 | MailBoxPtr mailboxPtr_ = nullptr; 133 | }; 134 | } 135 | -------------------------------------------------------------------------------- /utils/profiler.lua: -------------------------------------------------------------------------------- 1 | local profiler = { 2 | start_time_ = 0, 3 | end_time_ = 0, 4 | 5 | report_by_title = {}, -- 6 | reports = {}, 7 | } 8 | 9 | function profiler:start() 10 | 11 | self.start_time_ = os.clock() 12 | 13 | self.reports = {} 14 | self.report_by_title = {} 15 | 16 | debug.sethook(profiler._profiling_handler, 'cr', 0) 17 | 18 | end 19 | 20 | function profiler:stop() 21 | print("profiler:end") 22 | 23 | self.end_time_ = os.clock() 24 | debug.sethook() 25 | 26 | local _total_time = self.end_time_ - self.start_time_ 27 | 28 | table.sort(self.reports, function(a, b) 29 | return a.total_time > b.total_time 30 | end) 31 | 32 | str = "prof : \n" 33 | 34 | for _, report in ipairs(self.reports) do 35 | print(report.total_time) 36 | 37 | local _percent = (report.total_time / _total_time) * 100 38 | --if _percent < 1 then 39 | -- break 40 | --end 41 | 42 | str = str .. string.format("%6.3f, %6.2f%%, %7d, %s", report.total_time, _percent, report.call_count, report.title) .. "\n" 43 | --str = str .. (tostring(report.total_time) .. " " .. tostring(percent) .. " " .. tostring(report.call_count) .. " " .. report.title .. "\n") 44 | 45 | end 46 | 47 | print(str) 48 | end 49 | 50 | function profiler:_func_title(function_info) 51 | 52 | local _name = function_info.name or 'anonymous' 53 | 54 | local _line = string.format("%d", function_info.linedefined or 0) 55 | 56 | local _source = function_info.short_src or 'C_FUNC' 57 | --if os.isfile(_source) then 58 | -- _source = path.relative(source, "") 59 | --end 60 | 61 | return string.format("%-30s: %s: %s", _name, _source, _line) 62 | end 63 | 64 | function profiler:_func_report(function_info) 65 | 66 | local _title = self:_func_title(function_info) 67 | 68 | local _report = self.report_by_title[_title] 69 | if not _report then 70 | _report = { 71 | title = _title, 72 | call_count = 0, 73 | total_time = 0, 74 | } 75 | 76 | self.report_by_title[_title] = _report 77 | table.insert(self.reports, _report) 78 | end 79 | 80 | return _report 81 | 82 | end 83 | 84 | function profiler:_profiling_call(function_info) 85 | 86 | local _function_report = self:_func_report(function_info) 87 | assert(_function_report) 88 | 89 | _function_report.call_time = os.clock() 90 | _function_report.call_count = _function_report.call_count + 1 91 | 92 | end 93 | 94 | function profiler:_profiling_return(function_info) 95 | 96 | local _stop_time = os.clock() 97 | 98 | local _report = self:_func_report(function_info) 99 | assert(_report) 100 | 101 | if _report.call_time and _report.call_count > 0 then 102 | _report.total_time = _report.total_time + (_stop_time - _report.call_time) 103 | end 104 | 105 | end 106 | 107 | function profiler._profiling_handler(hooktype) 108 | 109 | local _function_info = debug.getinfo(2, 'nS') 110 | assert(_function_info) 111 | 112 | if hooktype == "call" then 113 | profiler:_profiling_call(_function_info) 114 | elseif hooktype == "return" then 115 | profiler:_profiling_return(_function_info) 116 | end 117 | 118 | end 119 | 120 | 121 | return profiler -------------------------------------------------------------------------------- /script/profiler.lua: -------------------------------------------------------------------------------- 1 | local profiler = { 2 | start_time_ = 0, 3 | end_time_ = 0, 4 | 5 | report_by_title = {}, -- 6 | reports = {}, 7 | } 8 | 9 | function profiler:start() 10 | 11 | self.start_time_ = os.clock() 12 | 13 | self.reports = {} 14 | self.report_by_title = {} 15 | 16 | debug.sethook(profiler._profiling_handler, 'cr', 0) 17 | 18 | end 19 | 20 | function profiler:stop() 21 | print("profiler:end") 22 | 23 | self.end_time_ = os.clock() 24 | debug.sethook() 25 | 26 | local _total_time = self.end_time_ - self.start_time_ 27 | 28 | table.sort(self.reports, function(a, b) 29 | return a.total_time > b.total_time 30 | end) 31 | 32 | str = "prof : \n" 33 | 34 | for _, report in ipairs(self.reports) do 35 | print(report.total_time) 36 | 37 | local _percent = (report.total_time / _total_time) * 100 38 | --if _percent < 1 then 39 | -- break 40 | --end 41 | 42 | str = str .. string.format("%6.3f, %6.2f%%, %7d, %s", report.total_time, _percent, report.call_count, report.title) .. "\n" 43 | --str = str .. (tostring(report.total_time) .. " " .. tostring(percent) .. " " .. tostring(report.call_count) .. " " .. report.title .. "\n") 44 | 45 | end 46 | 47 | print(str) 48 | end 49 | 50 | function profiler:_func_title(function_info) 51 | 52 | local _name = function_info.name or 'anonymous' 53 | 54 | local _line = string.format("%d", function_info.linedefined or 0) 55 | 56 | local _source = function_info.short_src or 'C_FUNC' 57 | --if os.isfile(_source) then 58 | -- _source = path.relative(source, "") 59 | --end 60 | 61 | return string.format("%-30s: %s: %s", _name, _source, _line) 62 | end 63 | 64 | function profiler:_func_report(function_info) 65 | 66 | local _title = self:_func_title(function_info) 67 | 68 | local _report = self.report_by_title[_title] 69 | if not _report then 70 | _report = { 71 | title = _title, 72 | call_count = 0, 73 | total_time = 0, 74 | } 75 | 76 | self.report_by_title[_title] = _report 77 | table.insert(self.reports, _report) 78 | end 79 | 80 | return _report 81 | 82 | end 83 | 84 | function profiler:_profiling_call(function_info) 85 | 86 | local _function_report = self:_func_report(function_info) 87 | assert(_function_report) 88 | 89 | _function_report.call_time = os.clock() 90 | _function_report.call_count = _function_report.call_count + 1 91 | 92 | end 93 | 94 | function profiler:_profiling_return(function_info) 95 | 96 | local _stop_time = os.clock() 97 | 98 | local _report = self:_func_report(function_info) 99 | assert(_report) 100 | 101 | if _report.call_time and _report.call_count > 0 then 102 | _report.total_time = _report.total_time + (_stop_time - _report.call_time) 103 | end 104 | 105 | end 106 | 107 | function profiler._profiling_handler(hooktype) 108 | 109 | local _function_info = debug.getinfo(2, 'nS') 110 | assert(_function_info) 111 | 112 | if hooktype == "call" then 113 | profiler:_profiling_call(_function_info) 114 | elseif hooktype == "return" then 115 | profiler:_profiling_return(_function_info) 116 | end 117 | 118 | end 119 | 120 | 121 | return profiler -------------------------------------------------------------------------------- /core/appImpl.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../event_list.h" 4 | #include "../utils/single.h" 5 | #include "../utils/timer.hpp" 6 | #include "../utils/logger.hpp" 7 | 8 | #include "args.h" 9 | #include "appConfig.hpp" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | 20 | namespace block 21 | { 22 | class Module; 23 | struct MailBox; 24 | typedef std::shared_ptr MailBoxPtr; 25 | typedef std::function RpcCallback; 26 | 27 | class AppImpl 28 | { 29 | enum AppState 30 | { 31 | BEFORE_INIT = 0, 32 | INIT, 33 | EXECUTE, 34 | SHUT, 35 | AFTER_SHUT, 36 | }; 37 | 38 | friend struct MailBox; 39 | public: 40 | AppImpl(); 41 | 42 | std::string getName() const; 43 | 44 | block::ModuleID getModuleID(const std::string &moduleName) const; 45 | 46 | bool hasModule(block::ModuleID moduleid); 47 | 48 | const block::AppConfig & getAppCfg(); 49 | 50 | uint64_t getSystemTick(); 51 | 52 | void initCfg(const block::AppConfig &cfg); 53 | 54 | template 55 | void createModule(T *module); 56 | 57 | block::ModuleID createDynamicModule(const std::string &moduleType); 58 | 59 | void deleteModule(block::ModuleID moduleID); 60 | 61 | void run(); 62 | 63 | void exit(); 64 | 65 | int64_t uuid(); 66 | 67 | utils::Logger getLogger() { return logger_; } 68 | utils::Timer & getTimer() { return timer_; } 69 | 70 | void reactorRegist(block::ModuleID moduleID, block::EventID event); 71 | void reactorDispatch(block::ModuleID self, block::ModuleID target, block::EventID event, block::ArgsPtr args); 72 | void reactorBoardcast(block::ModuleID self, block::EventID event, block::ArgsPtr args); 73 | 74 | protected: 75 | void tick(); 76 | 77 | template 78 | void registModule(T *module, bool dynamic = false); 79 | 80 | void unregist_dynamic_module(block::ModuleID module_id); 81 | 82 | typedef std::tuple, std::function, std::function, Module*> Frame; 83 | void pushFrame(uint64_t index, Frame frame); 84 | void popFrame(); 85 | 86 | private: 87 | utils::Logger logger_; 88 | utils::Timer timer_; 89 | 90 | AppState state_; 91 | int sequence_ = 0; 92 | uint64_t start_time_ = getSystemTick(); 93 | 94 | std::list module_list_; 95 | std::multimap> exit_list_; 96 | 97 | std::unordered_map module_name_map_; 98 | 99 | std::multimap halfway_frame_; 100 | 101 | std::map, MailBoxPtr> mailboxMap_; 102 | 103 | bool shutdown_; 104 | 105 | uint64_t cur_frame_; 106 | 107 | int32_t module_idx_; 108 | 109 | block::AppConfig cfg_; 110 | }; 111 | 112 | 113 | template 114 | void block::AppImpl::createModule(T *module) 115 | { 116 | registModule(module); 117 | } 118 | 119 | template 120 | void block::AppImpl::registModule(T *module, bool dynamic /* = false */) 121 | { 122 | module_list_.push_back(module); 123 | 124 | if (!dynamic) { 125 | module->setID(uuid()); 126 | //auto _type_id = typeid(T).hash_code(); 127 | //auto _id_itr = module_id_map_.find(_type_id); 128 | //if (_id_itr != module_id_map_.end()) { 129 | // printf("regist repeated module!\n"); 130 | // return; 131 | //} 132 | 133 | //module_id_map_.insert(std::make_pair(_type_id, module->get_module_id())); 134 | module_name_map_.insert(std::make_pair(module->getModuleName(), module->getModuleID())); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /event_list.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by pojol on 2017/2/13. 3 | // 4 | 5 | #pragma once 6 | 7 | // 后面用工具自动生成 8 | //! 用于描述框架中用到的事件, 用户可以以此为模板在自己工程中建立一个event_list 用于工程中的事件描述 9 | 10 | namespace block 11 | { 12 | namespace event { 13 | 14 | enum block_event { 15 | /*! 16 | comment: Module初始化成功 17 | args: nil 18 | type: boardcast 19 | res : int32_t module_id 20 | **/ 21 | module_init_succ = 101, 22 | 23 | /*! 24 | comment: Module退出成功 25 | args: nil 26 | type: boardcast 27 | res : int32_t module_id 28 | **/ 29 | module_shut_succ, 30 | 31 | /*! 32 | comment: 创建一个接收器 33 | args: int32_t module_id, string ip, int32_t port 34 | type: dispatch 35 | res : bool succ or fail, string reason 36 | **/ 37 | tcp_make_acceptor = 2001, 38 | 39 | /*! 40 | comment: 创建一个连接器 41 | args: module_id, ip, port 42 | type: dispatch 43 | res : bool succ or fail, string reason 44 | **/ 45 | tcp_make_connector, 46 | 47 | /*! 48 | comment: 踢掉某个现有的连接 49 | args: int32_t fd 50 | type: dispatch 51 | res : bool succ or fail, string reason 52 | **/ 53 | tcp_kick_connect, 54 | 55 | /*! 56 | comment: 发送一条网络消息 57 | args: int32_t fd, int32_t msgid, stream block 58 | type: dispatch 59 | res : nil 60 | **/ 61 | tcp_send, 62 | 63 | /*! 64 | comment: 接收到一条网络消息 65 | args: int32_t fd, int32_t msgid, stream block 66 | type: listen 67 | res : nil 68 | **/ 69 | tcp_recv, 70 | 71 | /*! 72 | comment: 接收到一个新的连接(适用于 acceptor 73 | args: int32_t fd 74 | type: listen 75 | res : nil 76 | **/ 77 | tcp_new_connect, 78 | 79 | /*! 80 | comment: 连接被断开, 只有连接错误才会收到这条事件(服务器主动kick不会 81 | args: int32_t fd 82 | type: listen 83 | res : int32_t fd, string reason 84 | **/ 85 | tcp_dis_connect, 86 | 87 | /*! 88 | comment: 重新装载 Lua Script Module, 会走标准的退出和进入流程 init, shut 。即便持有状态也可以方便的热更 89 | args: int32_t module_id 90 | type: dispatch 91 | res : bool succ 92 | **/ 93 | script_reload = 2301, 94 | 95 | /*! 96 | comment: 建立一个新的Mysql连接 97 | args: string host, string user, string password, string dbName, int32_t port, bool useCache 98 | type: dispatch 99 | res : bool succ 100 | **/ 101 | db_connect = 2401, 102 | 103 | /*! 104 | comment: 执行一条sql语句 105 | args: int32_t moduleID, string sql 106 | type: dispatch 107 | res : nil 108 | **/ 109 | db_execSql, 110 | 111 | /*! 112 | comment: 创建一个实例 113 | args: string tableName, table entityInfo 114 | type: dispatch 115 | res : entityInfo 116 | **/ 117 | db_insert, 118 | 119 | /*! 120 | comment: 获取一个实例 121 | args: int32_t moduleID, string field, int32_t entityID ( entityID == 0 then load all 122 | type: dispatch 123 | res : entityInfo 124 | **/ 125 | db_load, 126 | 127 | /*! 128 | comment: 更新一个实例 129 | args: string field, int32_t entityID, table entityDirty 130 | type: dispatch 131 | res : nil 132 | **/ 133 | db_update, 134 | 135 | db_callback, 136 | 137 | node_init = 2501, 138 | node_addModule, 139 | node_rmvModule, 140 | }; 141 | 142 | } 143 | 144 | namespace rpc 145 | { 146 | enum rpc_event { 147 | //! 凡是gsf集群内使用rpc交互的消息都应该定义在distributed区块 148 | begin = 1001, 149 | 150 | /*! 151 | comment: 调整Node在Coordinator中的权重 152 | args: int32_t node_id, string module_name, int32_t module_fature, int32_t +- weight 153 | type: rpc 154 | res : stream args, int32_t progress, bool succ 155 | **/ 156 | coordinat_adjust_weight, 157 | 158 | 159 | end = 1999, 160 | }; 161 | } 162 | 163 | namespace error 164 | { 165 | enum block_error 166 | { 167 | err_repeated_fd = -10000, 168 | err_upper_limit_session, 169 | err_socket_new, 170 | err_socket_connect, 171 | err_event_eof, 172 | err_event_error, 173 | err_event_timeout, 174 | err_inet_pton, 175 | err_distributed_node_repeat, 176 | }; 177 | } 178 | } -------------------------------------------------------------------------------- /script/utils.lua: -------------------------------------------------------------------------------- 1 | require "event_list" 2 | require "event_fmt" 3 | 4 | function dump ( t ) 5 | local print_r_cache={} 6 | local function sub_print_r(t,indent) 7 | if (print_r_cache[tostring(t)]) then 8 | print(indent.."*"..tostring(t)) 9 | else 10 | print_r_cache[tostring(t)]=true 11 | if (type(t)=="table") then 12 | for pos,val in pairs(t) do 13 | if (type(val)=="table") then 14 | print(indent.."["..pos.."] => "..tostring(t).." {") 15 | sub_print_r(val,indent..string.rep(" ",string.len(pos)+8)) 16 | print(indent..string.rep(" ",string.len(pos)+6).."}") 17 | elseif (type(val)=="string") then 18 | print(indent.."["..pos..'] => "'..val..'"') 19 | else 20 | print(indent.."["..pos.."] => "..tostring(val)) 21 | end 22 | end 23 | else 24 | print(indent..tostring(t)) 25 | end 26 | end 27 | end 28 | if (type(t)=="table") then 29 | print(tostring(t).." {") 30 | sub_print_r(t," ") 31 | print("}") 32 | else 33 | sub_print_r(t," ") 34 | end 35 | print() 36 | end 37 | 38 | function dumpStr(t) 39 | local _str = "" 40 | local print_r_cache={} 41 | local function sub_print_r(t,indent) 42 | if (print_r_cache[tostring(t)]) then 43 | _str = _str .. indent.."*"..tostring(t) .. '\n' 44 | else 45 | print_r_cache[tostring(t)]=true 46 | if (type(t)=="table") then 47 | for pos,val in pairs(t) do 48 | if (type(val)=="table") then 49 | _str = _str .. indent.."["..pos.."] => "..tostring(t).." {\n" 50 | sub_print_r(val,indent..string.rep(" ",string.len(pos)+8)) 51 | _str = _str .. indent..string.rep(" ",string.len(pos)+6).."}\n" 52 | elseif (type(val)=="string") then 53 | _str = _str .. indent.."["..pos..'] => "'..val..'"\n' 54 | else 55 | _str = _str .. indent.."["..pos.."] => "..tostring(val) .. '\n' 56 | end 57 | end 58 | else 59 | _str = _str .. indent..tostring(t) .. '\n' 60 | end 61 | end 62 | end 63 | if (type(t)=="table") then 64 | _str = _str .. tostring(t).." {\n" 65 | sub_print_r(t," ") 66 | _str = _str .. "}\n" 67 | else 68 | sub_print_r(t,"") 69 | end 70 | 71 | return _str 72 | end 73 | 74 | function deep_copy(object) 75 | local lookup_table = {} 76 | local function _copy(object) 77 | if type(object) ~= "table" then 78 | return object 79 | elseif lookup_table[object] then 80 | return lookup_table[object] 81 | end 82 | local new_table = {} 83 | lookup_table[object] = new_table 84 | for key, value in pairs(object) do 85 | new_table[_copy(key)] = _copy(value) 86 | end 87 | return setmetatable(new_table, getmetatable(object)) 88 | end 89 | return _copy(object) 90 | end 91 | 92 | function dispatch(target, event, ...) 93 | 94 | local args = { ... } 95 | local buf = evpack:pack(event, args) 96 | 97 | self:ldispatch(target, event, buf) 98 | end 99 | 100 | function listen(eventID, func) 101 | 102 | function _callback(buf) 103 | _args = evunpack(buf) 104 | func(_args) 105 | end 106 | 107 | self:llisten(eventID, _callback) 108 | end 109 | 110 | function rpc(event_id, module_id, buf, callback) 111 | 112 | function _callback(resBuf, len, progress, succ) 113 | _args = evunpack(resBuf, len) 114 | callback(_args, progress, succ) 115 | end 116 | 117 | if callback ~= nil then 118 | self:lrpc(module_id, event_id, module_id, buf, _callback) 119 | else 120 | self:lrpc(module_id, event_id, module_id, buf, nil) 121 | end 122 | end -------------------------------------------------------------------------------- /modules/network/tcpConnector.cpp: -------------------------------------------------------------------------------- 1 | #include "tcpConnector.h" 2 | 3 | #include "sessionMgr.h" 4 | #include "session.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #ifdef WIN32 12 | #include 13 | #include 14 | #else 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #endif // WIN32 22 | 23 | block::network::TcpConnectorModule::TcpConnectorModule(const std::string &name) 24 | : Module(name) 25 | { 26 | } 27 | 28 | block::network::TcpConnectorModule::TcpConnectorModule() 29 | : Module("ConnectorModule") 30 | { 31 | 32 | } 33 | 34 | block::network::TcpConnectorModule::~TcpConnectorModule() 35 | { 36 | 37 | } 38 | 39 | void block::network::TcpConnectorModule::before_init() 40 | { 41 | eventBasePtr_ = event_base_new(); 42 | sessionMgr_ = new SessionMgr(this); 43 | 44 | using namespace std::placeholders; 45 | 46 | listen(block::event::tcp_make_connector, std::bind(&TcpConnectorModule::eMakeConncetor, this, _1, _2)); 47 | listen(block::event::tcp_send, std::bind(&TcpConnectorModule::eSendMsg, this, _1, _2)); 48 | } 49 | 50 | void block::network::TcpConnectorModule::init() 51 | { 52 | // todo ... 53 | 54 | boardcast(block::event::module_init_succ, block::makeArgs(getModuleID(), getModuleName())); 55 | } 56 | 57 | void block::network::TcpConnectorModule::execute() 58 | { 59 | //! 先处理断连 60 | 61 | // 62 | sessionMgr_->exec(); 63 | 64 | if (eventBasePtr_) { 65 | event_base_loop(eventBasePtr_, EVLOOP_ONCE | EVLOOP_NONBLOCK); 66 | } 67 | } 68 | 69 | void block::network::TcpConnectorModule::shut() 70 | { 71 | bufferevent_free(bufferEventPtr_); 72 | event_base_free(eventBasePtr_); 73 | } 74 | 75 | void block::network::TcpConnectorModule::after_shut() 76 | { 77 | } 78 | 79 | void block::network::TcpConnectorModule::eMakeConncetor(block::ModuleID target, block::ArgsPtr args) 80 | { 81 | std::string _ip = args->pop_string(); 82 | uint32_t _port = args->pop_i32(); 83 | 84 | proxyModuleID_ = target; 85 | 86 | int _fd = 0; 87 | 88 | bufferEventPtr_ = bufferevent_socket_new(eventBasePtr_, -1, BEV_OPT_CLOSE_ON_FREE); 89 | if (!bufferEventPtr_) { 90 | ERROR_LOG("[BLOCK] tcpConnector : bufferevent socket new fail!"); 91 | return; 92 | } 93 | 94 | struct sockaddr_in _sin; 95 | 96 | memset(&_sin, 0, sizeof(_sin)); 97 | _sin.sin_family = AF_INET; 98 | _sin.sin_port = htons(_port); 99 | 100 | if (evutil_inet_pton(AF_INET, _ip.c_str(), &_sin.sin_addr) <= 0) 101 | { 102 | ERROR_LOG("[BLOCK] tcpConnector : err_inet_pton fail!"); 103 | return; 104 | } 105 | 106 | int _ret = bufferevent_socket_connect(bufferEventPtr_, (sockaddr*)&_sin, sizeof(sockaddr_in)); 107 | if (_ret != 0) { 108 | ERROR_LOG("[BLOCK] tcpConnector : bufferevent socket connect fail!"); 109 | return; 110 | } 111 | else { 112 | _fd = bufferevent_getfd(bufferEventPtr_); 113 | } 114 | 115 | //sessionPtr_ = std::make_shared(_fd, target, sessionMgr_, bufferEventPtr_); 116 | sessionPtr_ = sessionMgr_->makeSession(_fd, target, bufferEventPtr_); 117 | bufferevent_setcb(bufferEventPtr_, Session::readCB, NULL, Session::eventCB, sessionPtr_.get()); 118 | bufferevent_enable(bufferEventPtr_, EV_READ | EV_WRITE); 119 | 120 | INFO_LOG("[BLOCK] tcpConnector : make connector success!"); 121 | } 122 | 123 | 124 | void block::network::TcpConnectorModule::needCloseSession(int fd) 125 | { 126 | // 127 | } 128 | 129 | 130 | void block::network::TcpConnectorModule::eSendMsg(block::ModuleID target, block::ArgsPtr args) 131 | { 132 | auto _fd = args->pop_fd(); 133 | auto _msg = args->pop_msgid(); 134 | std::string _str = ""; 135 | 136 | //! 内部消息走的时Args流, 外部的是原始的二进制数据。 所以这里要分开处理下! 137 | if (_msg > block::rpc::begin && _msg < block::rpc::end) { 138 | auto _headlen = sizeof(block::MsgID) + 1; 139 | //args->pop_block(); 140 | //_str = args->get_block(_headlen, args->get_size() - _headlen); 141 | } 142 | else { 143 | _str = args->pop_string(); 144 | } 145 | 146 | auto _block = std::make_shared(sessionPtr_->getID(), _msg, _str); 147 | sessionPtr_->write(_msg, _block); 148 | } 149 | -------------------------------------------------------------------------------- /utils/crc32.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | unsigned int uiCRC32_Table[256] = { 4 | 0x00000000L, 0x77073096L, 0xEE0E612CL, 5 | 0x990951BAL, 0x076DC419L, 0x706AF48FL, 6 | 0xE963A535L, 0x9E6495A3L, 0x0EDB8832L, 7 | 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 8 | 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 9 | 0x90BF1D91L, 0x1DB71064L, 0x6AB020F2L, 10 | 0xF3B97148L, 0x84BE41DEL, 0x1ADAD47DL, 11 | 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 12 | 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 13 | 0x8A65C9ECL, 0x14015C4FL, 0x63066CD9L, 14 | 0xFA0F3D63L, 0x8D080DF5L, 0x3B6E20C8L, 15 | 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 16 | 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 17 | 0xA50AB56BL, 0x35B5A8FAL, 0x42B2986CL, 18 | 0xDBBBC9D6L, 0xACBCF940L, 0x32D86CE3L, 19 | 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 20 | 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 21 | 0xBFD06116L, 0x21B4F4B5L, 0x56B3C423L, 22 | 0xCFBA9599L, 0xB8BDA50FL, 0x2802B89EL, 23 | 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 24 | 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 25 | 0xB6662D3DL, 0x76DC4190L, 0x01DB7106L, 26 | 0x98D220BCL, 0xEFD5102AL, 0x71B18589L, 27 | 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 28 | 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 29 | 0xE10E9818L, 0x7F6A0DBBL, 0x086D3D2DL, 30 | 0x91646C97L, 0xE6635C01L, 0x6B6B51F4L, 31 | 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 32 | 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 33 | 0xF50FC457L, 0x65B0D9C6L, 0x12B7E950L, 34 | 0x8BBEB8EAL, 0xFCB9887CL, 0x62DD1DDFL, 35 | 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 36 | 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 37 | 0xD4BB30E2L, 0x4ADFA541L, 0x3DD895D7L, 38 | 0xA4D1C46DL, 0xD3D6F4FBL, 0x4369E96AL, 39 | 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 40 | 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 41 | 0xDD0D7CC9L, 0x5005713CL, 0x270241AAL, 42 | 0xBE0B1010L, 0xC90C2086L, 0x5768B525L, 43 | 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 44 | 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 45 | 0xC7D7A8B4L, 0x59B33D17L, 0x2EB40D81L, 46 | 0xB7BD5C3BL, 0xC0BA6CADL, 0xEDB88320L, 47 | 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 48 | 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 49 | 0x73DC1683L, 0xE3630B12L, 0x94643B84L, 50 | 0x0D6D6A3EL, 0x7A6A5AA8L, 0xE40ECF0BL, 51 | 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 52 | 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 53 | 0x6906C2FEL, 0xF762575DL, 0x806567CBL, 54 | 0x196C3671L, 0x6E6B06E7L, 0xFED41B76L, 55 | 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 56 | 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 57 | 0x60B08ED5L, 0xD6D6A3E8L, 0xA1D1937EL, 58 | 0x38D8C2C4L, 0x4FDFF252L, 0xD1BB67F1L, 59 | 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 60 | 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 61 | 0x41047A60L, 0xDF60EFC3L, 0xA867DF55L, 62 | 0x316E8EEFL, 0x4669BE79L, 0xCB61B38CL, 63 | 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 64 | 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 65 | 0x5505262FL, 0xC5BA3BBEL, 0xB2BD0B28L, 66 | 0x2BB45A92L, 0x5CB36A04L, 0xC2D7FFA7L, 67 | 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 68 | 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 69 | 0x026D930AL, 0x9C0906A9L, 0xEB0E363FL, 70 | 0x72076785L, 0x05005713L, 0x95BF4A82L, 71 | 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 72 | 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 73 | 0x0BDBDF21L, 0x86D3D2D4L, 0xF1D4E242L, 74 | 0x68DDB3F8L, 0x1FDA836EL, 0x81BE16CDL, 75 | 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 76 | 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 77 | 0x11010B5CL, 0x8F659EFFL, 0xF862AE69L, 78 | 0x616BFFD3L, 0x166CCF45L, 0xA00AE278L, 79 | 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 80 | 0xA7672661L, 0xD06016F7L, 0x4969474DL, 81 | 0x3E6E77DBL, 0xAED16A4AL, 0xD9D65ADCL, 82 | 0x40DF0B66L, 0x37D83BF0L, 0xA9BCAE53L, 83 | 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 84 | 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 85 | 0x24B4A3A6L, 0xBAD03605L, 0xCDD70693L, 86 | 0x54DE5729L, 0x23D967BFL, 0xB3667A2EL, 87 | 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 88 | 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 89 | 0x2D02EF8DL }; 90 | 91 | static uint32_t CRC32(const char *dat, size_t len) 92 | { 93 | unsigned int uiCRC32 = 0xFFFFFFFF; 94 | unsigned char *pszData = (unsigned char*)dat; 95 | 96 | for (size_t i = 0; i < len; ++i) 97 | { 98 | uiCRC32 = ((uiCRC32 >> 8) & 0x00FFFFFF) ^ uiCRC32_Table[(uiCRC32 ^ (unsigned int)*pszData++) & 0xFF]; 99 | } 100 | 101 | return (uiCRC32 ^ 0xFFFFFFFF); 102 | 103 | } -------------------------------------------------------------------------------- /modules/network/session.cpp: -------------------------------------------------------------------------------- 1 | #include "session.h" 2 | #include "sessionMgr.h" 3 | 4 | #include 5 | 6 | #include 7 | 8 | block::network::Session::Session(int fd, block::ModuleID moduleID, SessionMgr *mgr, ::bufferevent *bev) 9 | : fd_(fd) 10 | , targetM_(moduleID) 11 | , bufEvtPtr_(bev) 12 | , basePtr_(mgr) 13 | { 14 | inBufPtr_ = evbuffer_new(); 15 | if (0 != block::SESSION_READ_BUFFER_SIZE) { 16 | evbuffer_expand(inBufPtr_, block::SESSION_READ_BUFFER_SIZE); 17 | } 18 | 19 | outBufPtr_ = evbuffer_new(); 20 | if (0 != block::SESSION_WRITE_BUFFER_SIZE) { 21 | evbuffer_expand(outBufPtr_, block::SESSION_WRITE_BUFFER_SIZE); 22 | } 23 | } 24 | 25 | block::network::Session::~Session() 26 | { 27 | if (inBufPtr_) { 28 | evbuffer_free(inBufPtr_); 29 | } 30 | 31 | if (outBufPtr_) { 32 | evbuffer_free(outBufPtr_); 33 | } 34 | 35 | if (bufEvtPtr_) { 36 | bufferevent_free(bufEvtPtr_); 37 | } 38 | } 39 | 40 | void block::network::Session::readCB(::bufferevent *bev, void *ctx) 41 | { 42 | Session *_session_ptr = static_cast(ctx); 43 | 44 | _session_ptr->read(bev); 45 | 46 | //evbuffer_add_buffer() 47 | } 48 | 49 | void block::network::Session::eventCB(::bufferevent *bev, short what, void *ctx) 50 | { 51 | int32_t _result = 0; 52 | 53 | do { 54 | if (what & BEV_EVENT_EOF) { 55 | _result = block::error::err_event_eof; 56 | break; 57 | } 58 | 59 | if (what & BEV_EVENT_ERROR) { 60 | _result = block::error::err_event_error; 61 | break; 62 | } 63 | 64 | if (what & BEV_EVENT_TIMEOUT) { 65 | _result = block::error::err_event_timeout; 66 | break; 67 | } 68 | 69 | if (what & BEV_EVENT_CONNECTED) { 70 | Session * _session_ptr = static_cast(ctx); 71 | _session_ptr->newConnect(); 72 | break; 73 | } 74 | 75 | } while (0); 76 | 77 | if (0 != _result) { 78 | Session * _session_ptr = static_cast(ctx); 79 | _session_ptr->disConnect(_result); 80 | } 81 | } 82 | 83 | int block::network::Session::write(uint32_t msg_id, BlockPtr blockptr) 84 | { 85 | 86 | int _ret = evbuffer_add(outBufPtr_, blockptr->buf_, blockptr->size_); 87 | evbuffer_write(outBufPtr_, fd_); 88 | 89 | return 0; 90 | } 91 | 92 | void block::network::Session::read(::bufferevent *bev) 93 | { 94 | bufferevent_read_buffer(bev, inBufPtr_); 95 | 96 | uint32_t _buf_len = evbuffer_get_length(inBufPtr_); 97 | 98 | uint32_t _msgheadlen = sizeof(MsgHeadLen); 99 | 100 | char * _head = (char*)malloc(_msgheadlen); 101 | evbuffer_copyout(inBufPtr_, _head, _msgheadlen); 102 | 103 | uint32_t _msg_size = *reinterpret_cast(_head); 104 | 105 | //! 杩欓噷瑕佽ˉ鍏呬竴浜涙暟鎹潡妫€鏌? 106 | if (_buf_len >= _msg_size) { 107 | 108 | while (_buf_len >= _msg_size) 109 | { 110 | auto _block = std::make_shared(_msg_size); 111 | evbuffer_remove(inBufPtr_, _block->buf_, _msg_size); //! 灏嗘暟鎹祦鎷疯礉鍒癿sg block涓? 112 | 113 | MsgID _msg_id = _block->get_msg_id(); 114 | 115 | if (_msg_id > block::rpc::begin && _msg_id < block::rpc::end) { 116 | /* 117 | auto args_ptr = ArgsPool::get_ref().get(); 118 | args_ptr->push(fd_); 119 | args_ptr->push(_msg_id); 120 | args_ptr->push_block(_block->buf_ + _block->get_head_size(), _block->get_body_size()); 121 | 122 | basePtr_->addMessage(std::move(args_ptr)); 123 | */ 124 | } 125 | else { 126 | if (!_block->check()) { //! 鍏堣繖鏍锋鏌ヤ笅block涓殑鍐呭鏄惁鍚堟硶锛屽悗闈㈣偗瀹氫笉鑳借繖鏍锋槑鏂囦紶杈? 127 | break; 128 | } 129 | 130 | std::string _str(_block->buf_ + _block->get_head_size(), _block->get_body_size()); //tmp 131 | //dispatch(targetM_, eid::network::recv, block::makeArgs(fd_, _msg_id, std::move(_str))); 132 | basePtr_->addMessage(block::makeArgs(fd_, _msg_id, std::move(_str))); 133 | } 134 | 135 | _buf_len = evbuffer_get_length(inBufPtr_); 136 | if (_buf_len > _msgheadlen) { 137 | evbuffer_copyout(inBufPtr_, _head, _msgheadlen); 138 | _msg_size = *reinterpret_cast(_head); 139 | } 140 | else { 141 | break; 142 | } 143 | } 144 | } 145 | } 146 | 147 | void block::network::Session::disConnect(int32_t err) 148 | { 149 | basePtr_->addClose(fd_); 150 | //dispatch(targetM_, eid::network::dis_connect, block::makeArgs(fd_, err)); 151 | } 152 | 153 | void block::network::Session::newConnect() 154 | { 155 | basePtr_->addConnect(fd_); 156 | //dispatch(targetM_, eid::network::new_connect, block::makeArgs(fd_)); 157 | } -------------------------------------------------------------------------------- /utils/logger_impl.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../core/types.h" 4 | 5 | #define GOOGLE_GLOG_DLL_DECL 6 | #include 7 | 8 | #ifdef WIN32 9 | #include 10 | #else 11 | #include 12 | #endif // WIN32 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace block 21 | { 22 | namespace utils 23 | { 24 | class LoggerImpl 25 | { 26 | public: 27 | LoggerImpl() {} 28 | ~LoggerImpl() {} 29 | 30 | void init(const std::string &appName) 31 | { 32 | #ifdef WIN32 33 | GetModuleFileName(NULL, path_, 512); 34 | //取出文件路径 35 | for (int i = strlen(path_); i >= 0; i--) 36 | { 37 | if (path_[i] == '\\') 38 | { 39 | path_[i] = '\0'; 40 | break; 41 | } 42 | } 43 | #else 44 | int cnt = readlink("/proc/self/exe", path_, 512); 45 | if (cnt < 0 || cnt >= 512) 46 | { 47 | std::cout << "read path err" << std::endl; 48 | return; 49 | } 50 | for (int i = cnt; i >= 0; --i) 51 | { 52 | if (path_[i] == '/') 53 | { 54 | path_[i + 1] = '\0'; 55 | break; 56 | } 57 | } 58 | #endif // WIN32 59 | 60 | auto _path = std::string(path_) + "/log"; 61 | 62 | FLAGS_log_dir = _path; //设置输出路径 63 | FLAGS_alsologtostderr = true; //设置日志消息除了日志文件之外是否去标准输出 64 | FLAGS_colorlogtostderr = true; //设置记录到标准输出的颜色消息(如果终端支持) 65 | FLAGS_max_log_size = 10; //设置最大日志文件大小(以MB为单位) 66 | FLAGS_logbufsecs = 0; //立即写入到日志 67 | 68 | google::SetLogDestination(google::GLOG_INFO, (_path + "/" + appName + ".info_").c_str()); 69 | //! 将日志输出到同一个文件 70 | //google::SetLogDestination(google::GLOG_WARNING, ""); 71 | //google::SetLogDestination(google::GLOG_ERROR, ""); 72 | 73 | //! 区分info, warning, error 日志文件 74 | google::SetLogDestination(google::GLOG_WARNING, (_path + "/" + appName + ".warning_").c_str()); 75 | google::SetLogDestination(google::GLOG_ERROR, (_path + "/" + appName + ".error_").c_str()); 76 | 77 | google::InitGoogleLogging(appName.c_str()); 78 | } 79 | 80 | void print(int lv, const std::string &content) 81 | { 82 | switch (lv) 83 | { 84 | case block::LogDebug: 85 | DLOG(INFO) << content; 86 | break; 87 | case block::LogInfo: 88 | LOG(INFO) << content; 89 | break; 90 | case block::LogWarning: 91 | LOG(WARNING) << content; 92 | break; 93 | case block::LogErr: 94 | LOG(ERROR) << content; 95 | break; 96 | } 97 | } 98 | 99 | // -- 调试日志 -- 100 | template 101 | void DEBUG_LOG(const std::string &content, P&& ...values); 102 | void DEBUG_LOG(const std::string &content) 103 | { 104 | print(block::LogDebug, content); 105 | } 106 | 107 | // -- 诊断日志 -- 108 | template 109 | void INFO_LOG(const std::string &content, P &&... values); 110 | void INFO_LOG(const std::string &content) 111 | { 112 | print(block::LogInfo, content); 113 | } 114 | 115 | template 116 | void ERR_LOG(const std::string &content, P &&... values); 117 | void ERR_LOG(const std::string &content) 118 | { 119 | print(block::LogErr, content); 120 | } 121 | 122 | template 123 | void WARN_LOG(const std::string &content, P &&... values); 124 | void WARN_LOG(const std::string &content) 125 | { 126 | print(block::LogWarning, content); 127 | } 128 | 129 | // -- 统计日志 -- 130 | // behavior, player, time, args 131 | template 132 | void RECORD_LOG(const std::string &behavior, uint32_t player, uint32_t time, const std::string &content, P&& ...values); 133 | 134 | private: 135 | char path_[512]; 136 | }; 137 | 138 | template 139 | void block::utils::LoggerImpl::RECORD_LOG(const std::string &behavior, uint32_t player, uint32_t time, const std::string &content, P&& ...values) 140 | { 141 | } 142 | 143 | template 144 | void block::utils::LoggerImpl::WARN_LOG(const std::string &content, P&& ...values) 145 | { 146 | print(block::LogWarning, fmt::format(content, std::forward

(values)...)); 147 | } 148 | 149 | 150 | template 151 | void block::utils::LoggerImpl::ERR_LOG(const std::string &content, P&& ...values) 152 | { 153 | print(block::LogErr, fmt::format(content, std::forward

(values)...)); 154 | } 155 | 156 | 157 | template 158 | void block::utils::LoggerImpl::INFO_LOG(const std::string &content, P&& ...values) 159 | { 160 | print(block::LogInfo, fmt::format(content, std::forward

(values)...)); 161 | } 162 | 163 | template 164 | void block::utils::LoggerImpl::DEBUG_LOG(const std::string &content, P&& ...values) 165 | { 166 | print(block::LogDebug, fmt::format(content, std::forward

(values)...)); 167 | } 168 | } 169 | 170 | } 171 | 172 | -------------------------------------------------------------------------------- /utils/timer_impl.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace block 14 | { 15 | namespace utils 16 | { 17 | template 18 | struct timer_traits 19 | { 20 | typedef typename T::type type; 21 | }; 22 | 23 | struct delay_milliseconds_tag 24 | { 25 | }; 26 | struct delay_milliseconds 27 | { 28 | typedef delay_milliseconds_tag type; 29 | 30 | delay_milliseconds(uint32_t milliseconds) 31 | : milliseconds_(milliseconds) 32 | { 33 | } 34 | 35 | uint32_t milliseconds() const { return milliseconds_; } 36 | 37 | private: 38 | uint32_t milliseconds_; 39 | }; 40 | 41 | struct delay_day_tag 42 | { 43 | }; 44 | struct delay_day 45 | { 46 | typedef delay_day_tag type; 47 | 48 | delay_day(uint32_t hour, uint32_t minute) 49 | : hour_(hour), minute_(minute) 50 | { 51 | } 52 | 53 | uint32_t Hour() const { return hour_; } 54 | uint32_t Minute() const { return minute_; } 55 | 56 | private: 57 | uint32_t hour_; 58 | uint32_t minute_; 59 | }; 60 | 61 | class TimerImpl 62 | { 63 | /*! 64 | timer handler 65 | **/ 66 | struct TimerHandler 67 | { 68 | TimerHandler() {} 69 | 70 | std::function target_ = nullptr; 71 | uint64_t timerid_ = UINT64_MAX; 72 | uint32_t repet_ = UINT32_MAX; 73 | }; 74 | 75 | typedef std::shared_ptr TimerHandlerPtr; 76 | 77 | public: 78 | void exec() 79 | { 80 | using namespace std::chrono; 81 | 82 | if (!map_.empty()) { 83 | 84 | auto itr = map_.begin(); 85 | uint64_t _now = get_system_tick() - start_time_; 86 | uint64_t _time_id = itr->first; 87 | 88 | while ((_time_id >> sequence_bit_) < _now) 89 | { 90 | itr->second->target_(); 91 | 92 | // repet! 93 | 94 | map_.erase(itr); 95 | 96 | if (!map_.empty()) { 97 | itr = map_.begin(); 98 | _time_id = itr->first; 99 | } 100 | else { 101 | break; 102 | } 103 | } 104 | } 105 | } 106 | 107 | /*! 108 | 延时若干毫秒 109 | **/ 110 | uint64_t delay(delay_milliseconds milliseconds, std::function callback, delay_milliseconds_tag) 111 | { 112 | auto _tid = make_timer_id(milliseconds.milliseconds()); 113 | 114 | auto _event = std::make_shared(); 115 | _event->target_ = callback; 116 | _event->timerid_ = _tid; 117 | 118 | assert(map_.find(_tid) == map_.end()); 119 | map_.insert(std::make_pair(_tid, _event)); 120 | 121 | return _tid; 122 | } 123 | 124 | /*! 125 | 延时若干天 126 | **/ 127 | uint64_t delay(delay_day day, std::function callback, delay_day_tag) 128 | { 129 | using namespace std::chrono; 130 | 131 | uint32_t _hour = day.Hour(); 132 | uint32_t _minute = day.Minute(); 133 | 134 | typedef duration> dur_day; 135 | time_point _today = time_point_cast(system_clock::now()); 136 | 137 | time_point _second = time_point_cast(system_clock::now()); 138 | 139 | uint32_t _passed_second = static_cast(_second.time_since_epoch().count() - _today.time_since_epoch().count() * 24 * 60 * 60); 140 | uint32_t _space_second = _hour * 60 * 60 + _minute * 60; 141 | 142 | auto _event = std::make_shared(); 143 | uint64_t _delay = 0; 144 | 145 | if (_space_second > _passed_second) { 146 | _delay = (_second + seconds(_space_second - _passed_second)).time_since_epoch().count(); 147 | } 148 | else { 149 | _delay = (_second + seconds((24 * 60 * 60) - _passed_second - _space_second)).time_since_epoch().count(); 150 | } 151 | 152 | auto _tid = make_timer_id(_delay); 153 | 154 | assert(map_.find(_tid) == map_.end()); 155 | _event->target_ = callback; 156 | _event->timerid_ = _tid; 157 | 158 | map_.insert(std::make_pair(_tid, _event)); 159 | 160 | return _tid; 161 | } 162 | 163 | /*! 164 | 从定时管理器中移除某个定时器 165 | 166 | **/ 167 | void remove(uint64_t timerID) 168 | { 169 | auto _titr = map_.find(timerID); 170 | if (_titr != map_.end()) { 171 | map_.erase(_titr); 172 | } 173 | else { 174 | //APP.WARN_LOG("timer", "invalid remove!", " timerID:{}", timerID); 175 | } 176 | } 177 | 178 | private: 179 | 180 | uint64_t get_system_tick() 181 | { 182 | return (uint64_t)std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); 183 | } 184 | 185 | uint64_t make_timer_id(uint64_t delay) 186 | { 187 | uint64_t _tick = 0; 188 | 189 | _tick = get_system_tick() - start_time_ + delay; 190 | 191 | _tick <<= sequence_bit_; 192 | _tick |= (++local_idx_ & sequence_mask_); 193 | 194 | return _tick; 195 | } 196 | 197 | uint64_t start_time_ = get_system_tick(); 198 | 199 | uint64_t local_idx_ = 0; 200 | uint64_t sequence_bit_ = 15; 201 | uint64_t sequence_mask_ = (uint64_t)pow(2, sequence_bit_) - 1; 202 | private: 203 | 204 | typedef std::map TimerMap; 205 | TimerMap map_; 206 | }; 207 | } 208 | } -------------------------------------------------------------------------------- /script/event_fmt.lua: -------------------------------------------------------------------------------- 1 | local at_uint8 = 1 2 | local at_int8 = 2 3 | local at_uint16 = 3 4 | local at_int16 = 4 5 | local at_uint32 = 5 6 | local at_int32 = 6 7 | local at_uint64 = 7 8 | local at_int64 = 8 9 | local at_bool = 9 10 | local at_float = 10 11 | local at_double = 11 12 | local at_string = 12 13 | local at_list = 13 14 | local at_vec = 14 15 | local at_map = 15 16 | local at_eof = 20 17 | 18 | 19 | -- auto generated 20 | evpack = { 21 | 22 | pack = function(self, event, args) 23 | if event == eid.network.tcp_make_acceptor then 24 | local _buf = Args.new() 25 | _buf:push_string(args[1]) 26 | _buf:push_i32(args[2]) 27 | return _buf:exportBuf() 28 | end 29 | 30 | if event == eid.network.tcp_make_connector then 31 | local _buf = Args.new() 32 | pack:push_string(args[1]) 33 | pack:push_i32(args[2]) 34 | return pack:exportBuf() 35 | end 36 | 37 | if event == eid.network.kick_connect then 38 | local pack = Args.new() 39 | pack:push_ui16(args[1]) 40 | return pack:exportBuf() 41 | end 42 | 43 | if event == eid.network.send then 44 | local pack = Args.new() 45 | pack:push_ui16(args[1]) 46 | pack:push_i32(args[2]) 47 | pack:push_string(args[3]) 48 | return pack:exportBuf() 49 | end 50 | 51 | if event == eid.dbProxy.connect then 52 | local pack = Args.new() 53 | pack:push_string(args[1]) 54 | pack:push_string(args[2]) 55 | pack:push_string(args[3]) 56 | pack:push_string(args[4]) 57 | pack:push_i32(args[5]) 58 | pack:push_bool(args[6]) 59 | return pack:exportBuf() 60 | end 61 | 62 | if event == eid.dbProxy.execSql then 63 | local pack = Args.new() 64 | pack:push_string(args[1]) 65 | return pack:exportBuf() 66 | end 67 | 68 | if event == eid.dbProxy.insert then 69 | local pack = Args.new() 70 | pack:push_string(args[1]) 71 | return pack:exportBuf() 72 | end 73 | 74 | if event == eid.dbProxy.load then 75 | local pack = Args.new() 76 | pack:push_i32(args[1]) 77 | return pack:exportBuf() 78 | end 79 | 80 | if event == eid.dbProxy.update then 81 | local pack = Args.new() 82 | pack:push_i32(args[1]) 83 | pack:push_string(args[2]) 84 | return pack:exportBuf() 85 | end 86 | 87 | if event == eid.distributed.coordinat_select then 88 | local pack = Args.new() 89 | pack:push_string(args[1]) 90 | pack:push_i32(args[2]) 91 | return pack:exportBuf() 92 | end 93 | 94 | return "" 95 | end, 96 | 97 | 98 | --[[ 99 | node_regist = function(self, module_id, reg_event, ip, port) 100 | local pack = Args.new() 101 | pack:push_i32(module_id) 102 | pack:push_i32(reg_event) 103 | pack:push_string(ip) 104 | pack:push_i32(port) 105 | return pack:exportBuf() 106 | end, 107 | 108 | node_create = function(self, node_id, node_type, module_id, ip, port, rootIp, rootPort, modules) 109 | 110 | local pack = Args.new() 111 | pack:push_i32(node_id) 112 | pack:push_i32(module_id) 113 | pack:push_string(node_type) 114 | 115 | pack:push_string(ip) 116 | pack:push_i32(port) 117 | 118 | pack:push_string(rootIp) 119 | pack:push_i32(rootPort) 120 | 121 | pack:push_i32(#modules) 122 | for i = 1, #modules do 123 | local mNode = modules[i] 124 | pack:push_string(mNode[1]) 125 | pack:push_i32(mNode[2]) 126 | pack:push_i32(mNode[3]) 127 | end 128 | 129 | return pack:exportBuf() 130 | 131 | end, 132 | 133 | res_nodinfo = function(self, ip, port, node_id) 134 | local pack = Args.new() 135 | pack:push_string(ip) 136 | pack:push_i32(port) 137 | pack:push_i32(node_id) 138 | return pack:exportBuf() 139 | end, 140 | ]] 141 | 142 | } 143 | 144 | function evunpack(buf) 145 | unpack = Args.new() 146 | unpack:importBuf(buf) 147 | 148 | _args = {} 149 | _idx = 1 150 | _tag = unpack:get_tag() 151 | while(_tag ~= 0) do 152 | 153 | if _tag == at_uint16 then 154 | table.insert(_args, _idx, unpack:pop_ui16()) 155 | elseif _tag == at_int16 then 156 | table.insert(_args, _idx, unpack:pop_i16()) 157 | elseif _tag == at_int32 then 158 | table.insert(_args, _idx, unpack:pop_i32()) 159 | elseif _tag == at_uint32 then 160 | table.insert(_args, _idx, unpack:pop_ui32()) 161 | elseif _tag == at_int64 then 162 | table.insert(_args, _idx, unpack:pop_i64()) 163 | elseif _tag == at_uint64 then 164 | table.insert(_args, _idx, unpack:pop_ui64()) 165 | elseif _tag == at_string then 166 | table.insert(_args, _idx, unpack:pop_string()) 167 | elseif _tag == at_bool then 168 | table.insert(_args, _idx, unpack:pop_bool()) 169 | end 170 | 171 | _idx = _idx + 1 172 | _tag = unpack:get_tag() 173 | end 174 | 175 | return _args 176 | end -------------------------------------------------------------------------------- /modules/network/tcpAcceptor.cpp: -------------------------------------------------------------------------------- 1 | #include "tcpAcceptor.h" 2 | 3 | #include "sessionMgr.h" 4 | #include "session.h" 5 | 6 | #ifdef WIN32 7 | #include 8 | #include 9 | #else 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #endif // WIN32 17 | 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | block::network::TcpAcceptorModule::TcpAcceptorModule(const std::string &name) 26 | : Module(name) 27 | { 28 | 29 | } 30 | 31 | block::network::TcpAcceptorModule::TcpAcceptorModule() 32 | : Module("AcceptorModule") 33 | { 34 | 35 | } 36 | 37 | block::network::TcpAcceptorModule::~TcpAcceptorModule() 38 | { 39 | 40 | } 41 | 42 | void block::network::TcpAcceptorModule::before_init() 43 | { 44 | sessionMgr_ = new SessionMgr(this); 45 | 46 | eventBasePtr_ = event_base_new(); 47 | 48 | using namespace std::placeholders; 49 | 50 | listen(block::event::tcp_make_acceptor, std::bind(&TcpAcceptorModule::eMakeAcceptor, this, _1, _2)); 51 | listen(block::event::tcp_send, std::bind(&TcpAcceptorModule::eSendMsg, this, _1, _2)); 52 | listen(block::event::tcp_kick_connect, std::bind(&TcpAcceptorModule::eKick, this, _1, _2)); 53 | } 54 | 55 | void block::network::TcpAcceptorModule::init() 56 | { 57 | 58 | } 59 | 60 | void block::network::TcpAcceptorModule::execute() 61 | { 62 | if (sessionMgr_) { 63 | sessionMgr_->exec(); 64 | } 65 | 66 | if (eventBasePtr_) { 67 | event_base_loop(eventBasePtr_, EVLOOP_ONCE | EVLOOP_NONBLOCK); 68 | } 69 | } 70 | 71 | void block::network::TcpAcceptorModule::shut() 72 | { 73 | evconnlistener_free(acceptListenerPtr_); 74 | } 75 | 76 | void block::network::TcpAcceptorModule::after_shut() 77 | { 78 | if (sessionMgr_) { 79 | delete sessionMgr_; 80 | sessionMgr_ = nullptr; 81 | } 82 | } 83 | 84 | void block::network::TcpAcceptorModule::eMakeAcceptor(block::ModuleID target, block::ArgsPtr args) 85 | { 86 | if (nullptr == acceptListenerPtr_) { 87 | std::string _ip = args->pop_string(); 88 | uint32_t _port = args->pop_i32(); 89 | 90 | proxyModuleID_ = target; //! 绑定代理Module的id 91 | accept_bind(_ip, _port); 92 | } 93 | else { 94 | WARN_FMTLOG("[BLOCK] tcpAcceptor repeat make!"); 95 | } 96 | } 97 | 98 | /* 99 | void block::network::AcceptorModule::bind_remote(const block::ArgsPtr &args, block::CallbackFunc callback) 100 | { 101 | uint32_t _module_id = args->pop_i32(); 102 | uint32_t _msg_id = args->pop_i32(); 103 | 104 | auto _info_ptr = std::make_shared(_module_id, _msg_id, callback); 105 | binder_->regist(_info_ptr); 106 | } 107 | */ 108 | 109 | void block::network::TcpAcceptorModule::accept_bind(const std::string &ip, int port) 110 | { 111 | struct sockaddr_in sin; 112 | memset(&sin, 0, sizeof(sin)); 113 | sin.sin_family = AF_INET; 114 | sin.sin_port = htons(port); 115 | 116 | acceptListenerPtr_ = evconnlistener_new_bind(eventBasePtr_ 117 | , accept_listen_cb 118 | , (void*)this 119 | , LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE 120 | , -1 121 | , (sockaddr*)&sin 122 | , sizeof(sockaddr_in)); 123 | 124 | if (nullptr == acceptListenerPtr_) { 125 | ERROR_LOG("[BLOCK] tcpAcceptor listen err!"); 126 | } 127 | else { 128 | INFO_LOG("[BLOCK] tcpAcceptor listen ready!"); 129 | } 130 | } 131 | 132 | void block::network::TcpAcceptorModule::accept_listen_cb(::evconnlistener *listener, evutil_socket_t fd, sockaddr *sa, int socklen, void *arg) 133 | { 134 | block::network::TcpAcceptorModule *network_ptr_ = (block::network::TcpAcceptorModule*)arg; 135 | ::bufferevent *bev; 136 | int32_t _ret = 0; 137 | 138 | do 139 | { 140 | if (network_ptr_->sessionMgr_->find(fd)) { 141 | network_ptr_->sessionMgr_->addClose(fd); 142 | ERROR_LOG("[BLOCK] tcpAcceptor repeat fd!"); 143 | break; 144 | } 145 | 146 | // check max connect 147 | if (network_ptr_->sessionMgr_->curMaxConnect() >= NETWORK_CONNECT_MAX) { 148 | ERROR_LOG("[BLOCK] tcpAcceptor max connect!"); 149 | break; 150 | } 151 | 152 | bev = bufferevent_socket_new(network_ptr_->eventBasePtr_, fd, BEV_OPT_CLOSE_ON_FREE); 153 | if (!bev) { 154 | ERROR_LOG("[BLOCK] tcpAcceptor new socket fail!"); 155 | break; 156 | } 157 | 158 | } while (0); 159 | 160 | if (0 == _ret) { 161 | auto _session_ptr = network_ptr_->sessionMgr_->makeSession(fd, network_ptr_->proxyModuleID_, bev); 162 | bufferevent_setcb(bev, Session::readCB, NULL, Session::eventCB, _session_ptr.get()); 163 | bufferevent_enable(bev, EV_READ | EV_WRITE); 164 | 165 | Session::eventCB(bev, BEV_EVENT_CONNECTED, (void*)_session_ptr.get()); 166 | } 167 | } 168 | 169 | void block::network::TcpAcceptorModule::eSendMsg(block::ModuleID target, block::ArgsPtr args) 170 | { 171 | assert(nullptr != acceptListenerPtr_); 172 | 173 | auto _fd = args->pop_fd(); 174 | auto _msg = args->pop_msgid(); 175 | std::string _str = ""; 176 | 177 | //! 内部消息走的时Args流, 外部的是原始的二进制数据。 所以这里要分开处理下! 178 | if (_msg > block::rpc::begin && _msg < block::rpc::end) { 179 | //auto _headlen = sizeof(block::SessionID) + 1 + sizeof(block::MsgID) + 1; 180 | //_str = args->get_block(_headlen, args->get_size()); 181 | } 182 | else { 183 | _str = args->pop_string(); 184 | } 185 | 186 | auto _session_ptr = sessionMgr_->find(_fd); 187 | if (_session_ptr) { 188 | auto _block = std::make_shared(_fd, _msg, _str); 189 | _session_ptr->write(_msg, _block); 190 | } 191 | } 192 | 193 | void block::network::TcpAcceptorModule::eKick(block::ModuleID target, block::ArgsPtr args) 194 | { 195 | auto _fd = args->pop_fd(); 196 | sessionMgr_->addClose(_fd); 197 | } 198 | 199 | -------------------------------------------------------------------------------- /install.py: -------------------------------------------------------------------------------- 1 | import os 2 | import stat 3 | import platform 4 | import shutil 5 | 6 | def rmtree(top): 7 | for root, dirs, files in os.walk(top, topdown=False): 8 | for name in files: 9 | filename = os.path.join(root, name) 10 | os.chmod(filename, stat.S_IWUSR) 11 | os.remove(filename) 12 | for name in dirs: 13 | os.rmdir(os.path.join(root, name)) 14 | os.rmdir(top) 15 | 16 | if os.path.exists(os.getcwd() + '/3rd'): 17 | shutil.rmtree(os.getcwd() + '/3rd') 18 | 19 | os.system('mkdir 3rd') 20 | 21 | cur_path_ = os.getcwd() + '/3rd' 22 | root_path = cur_path_[:cur_path_.rfind('/')] 23 | print("root path ", root_path) 24 | print("cur path", cur_path_) 25 | 26 | os.chdir(cur_path_) 27 | ###################libevent################################### 28 | print("download Libevent version release-2.0.22-stable") 29 | 30 | if os.path.exists(cur_path_ + "/Libevent"): 31 | rmtree(cur_path_ + "/Libevent") 32 | 33 | #os.system('git clone https://gitee.com/pojol/Libevent.git') 34 | os.system('git clone https://github.com/nmathewson/Libevent.git') 35 | os.chdir(cur_path_ + "/Libevent") 36 | os.system('git checkout release-2.0.22-stable') 37 | 38 | if platform.system() == 'Linux': 39 | os.system('./autogen.sh') 40 | os.system('./configure --prefix=/' + root_path + '/lib/libevent') 41 | os.system('make') 42 | os.system('make install') 43 | elif platform.system() == 'Darwin': 44 | print("darwin") 45 | #usr/local/Cellar/openssl/1.0.2j/include 46 | os.system('./configure --prefix=/' + root_path + '/lib/libevent' + " CPPFLAGS=-I/usr/local/Cellar/openssl/1.0.2j/include LDFLAGS=-I/usr/local/Cellar/openssl/1.0.2j/lib") 47 | os.system('make') 48 | os.system('make install') 49 | else: 50 | pass 51 | os.chdir(cur_path_) 52 | ''' 53 | ''' 54 | #################glog#################################### 55 | print("download glog version 0.3.4") 56 | 57 | if os.path.exists(cur_path_ + "/glog"): 58 | rmtree(cur_path_ + "/glog") 59 | 60 | #os.system('git clone https://gitee.com/pojol/glog.git') 61 | os.system('git clone https://github.com/google/glog.git') 62 | os.chdir(cur_path_ + "/glog") 63 | os.system('git checkout v0.3.4') 64 | if platform.system() == 'Linux': 65 | os.system('./configure --prefix=/' + root_path + '/lib/glog') 66 | os.system('make') 67 | os.system('make install') 68 | else: 69 | pass 70 | os.chdir(cur_path_) 71 | ###################protobuf############################ 72 | 73 | ##################sol############################## 74 | print("download sol2 version 2.16.0") 75 | 76 | if os.path.exists(cur_path_ + "/sol2"): 77 | rmtree(cur_path_ + "/sol2") 78 | 79 | os.system('git clone https://github.com/ThePhD/sol2.git') 80 | #os.system('git clone https://gitee.com/pojol/sol2.git') 81 | os.chdir(cur_path_ + '/sol2') 82 | os.system('git checkout v2.16.0') 83 | os.chdir(cur_path_) 84 | 85 | 86 | #########################hiredis############################## 87 | print("download hiredis version 0.13.3") 88 | 89 | if os.path.exists(cur_path_ + "/hiredis"): 90 | rmtree(cur_path_ + "/hiredis") 91 | os.system('git clone https://github.com/redis/hiredis.git') 92 | #os.system('git clone https://gitee.com/pojol/hiredis.git') 93 | os.chdir(cur_path_ + '/hiredis') 94 | os.system('git checkout v0.13.3') 95 | if platform.system() == 'Linux': 96 | os.system('make') 97 | os.system('cp -r ' + cur_path_ + '/hiredis' + ' ' + root_path + '/lib/hiredis') 98 | else: 99 | pass 100 | os.chdir(cur_path_) 101 | ######################lua############################ 102 | print("download lua version 5.3.0") 103 | 104 | if os.path.exists(cur_path_ + "/lua-5.3.4"): 105 | rmtree(cur_path_ + "/lua-5.3.4") 106 | 107 | os.system('wget -P ' + root_path + '/3rd http://www.lua.org/ftp/lua-5.3.4.tar.gz') 108 | if platform.system() == 'Linux': 109 | os.system('tar -xzvf ./lua-5.3.4.tar.gz') 110 | os.chdir(cur_path_ + '/lua-5.3.4') 111 | os.system('make linux') 112 | os.system('mkdir ' + root_path + '/lib/lua') 113 | os.system('cp -r ' + cur_path_ + '/lua-5.3.4/src/* ' + ' ' + root_path + '/lib/lua/') 114 | 115 | os.chdir(cur_path_) 116 | 117 | ################### mysql connector ################### 118 | os.system('wget -P ' + root_path + '/3rd https://cdn.mysql.com//Downloads/Connector-C/mysql-connector-c-6.1.11-linux-glibc2.12-x86_64.tar.gz') 119 | if platform.system() == 'Linux': 120 | os.system('tar -xzvf ' + root_path + '/3rd/mysql-connector-c-6.1.11-linux-glibc2.12-x86_64.tar.gz') 121 | os.system('mkdir ' + root_path + '/lib/mysql_connector') 122 | os.system('mkdir ' + root_path + '/lib/mysql_connector/include') 123 | os.system('mkdir ' + root_path + '/lib/mysql_connector/lib') 124 | os.system('cp -r ' + cur_path_ + '/mysql-connector-c-6.1.11-linux-glibc2.12-x86_64/include/*' + ' ' + root_path + '/lib/mysql_connector/include') 125 | os.system('cp -r ' + cur_path_ + '/mysql-connector-c-6.1.11-linux-glibc2.12-x86_64/lib/*' + ' ' + root_path + '/lib/mysql_connector/lib') 126 | pass 127 | os.chdir(cur_path_) 128 | ########################fmtlib########################### 129 | print("download fmtlib version 4.0.0") 130 | if os.path.exists(cur_path_ + "/fmt"): 131 | rmtree(cur_path_ + "/fmt") 132 | if os.path.exists(root_path + "/lib/fmt"): 133 | rmtree(root_path + "/lib/fmt") 134 | 135 | os.system('git clone https://github.com/fmtlib/fmt.git') 136 | #os.system('git clone https://gitee.com/pojol/fmt.git') 137 | os.chdir(cur_path_ + '/fmt') 138 | os.system('git checkout 4.0.0') 139 | if platform.system() == 'Linux' or platform.system() == 'Darwin': 140 | os.system('mkdir build') 141 | os.chdir(cur_path_ + '/fmt/build') 142 | os.system('cmake ..') 143 | os.system('make') 144 | os.chdir(root_path + "/lib") 145 | os.system('mkdir fmt') 146 | os.chdir(root_path + "/lib/fmt") 147 | os.system('mkdir lib') 148 | os.system('mkdir include') 149 | os.chdir(root_path + "/lib/fmt/include") 150 | os.system('mkdir fmt') 151 | os.system('cp -rf ' + cur_path_ + '/fmt/build/fmt/libfmt.a' + ' ' + root_path + '/lib/fmt/lib/') 152 | os.system('cp -rf ' + cur_path_ + '/fmt/fmt/*' + ' ' + root_path + '/lib/fmt/include/fmt') 153 | 154 | os.chdir(root_path) 155 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | /.idea/* 3 | tool/robot/__pycache__/ 4 | tool/robot/scene/__pycache__/login.cpython-35.pyc 5 | LIB_D/ 6 | lib/apple/bin/event_rpcgen.py 7 | lib/apple/include/evdns.h 8 | lib/apple/include/event.h 9 | lib/apple/include/evhttp.h 10 | lib/apple/include/evrpc.h 11 | lib/apple/include/evutil.h 12 | lib/apple/include/event2/buffer.h 13 | lib/apple/include/event2/buffer_compat.h 14 | lib/apple/include/event2/bufferevent.h 15 | lib/apple/include/event2/bufferevent_compat.h 16 | lib/apple/include/event2/bufferevent_ssl.h 17 | lib/apple/include/event2/bufferevent_struct.h 18 | lib/apple/include/event2/dns.h 19 | lib/apple/include/event2/dns_compat.h 20 | lib/apple/include/event2/dns_struct.h 21 | lib/apple/include/event2/event-config.h 22 | lib/apple/include/event2/event.h 23 | lib/apple/include/event2/event_compat.h 24 | lib/apple/include/event2/event_struct.h 25 | lib/apple/include/event2/http.h 26 | lib/apple/include/event2/http_compat.h 27 | lib/apple/include/event2/http_struct.h 28 | lib/apple/include/event2/keyvalq_struct.h 29 | lib/apple/include/event2/listener.h 30 | lib/apple/include/event2/rpc.h 31 | lib/apple/include/event2/rpc_compat.h 32 | lib/apple/include/event2/rpc_struct.h 33 | lib/apple/include/event2/tag.h 34 | lib/apple/include/event2/tag_compat.h 35 | lib/apple/include/event2/thread.h 36 | lib/apple/include/event2/util.h 37 | lib/apple/lib/libevent-2.0.5.dylib 38 | lib/apple/lib/libevent.a 39 | lib/apple/lib/libevent.dylib 40 | lib/apple/lib/libevent.la 41 | lib/apple/lib/libevent_core-2.0.5.dylib 42 | lib/apple/lib/libevent_core.a 43 | lib/apple/lib/libevent_core.dylib 44 | lib/apple/lib/libevent_core.la 45 | lib/apple/lib/libevent_extra-2.0.5.dylib 46 | lib/apple/lib/libevent_extra.a 47 | lib/apple/lib/libevent_extra.dylib 48 | lib/apple/lib/libevent_extra.la 49 | lib/apple/lib/libevent_openssl-2.0.5.dylib 50 | lib/apple/lib/libevent_openssl.a 51 | lib/apple/lib/libevent_openssl.dylib 52 | lib/apple/lib/libevent_openssl.la 53 | lib/apple/lib/libevent_pthreads-2.0.5.dylib 54 | lib/apple/lib/libevent_pthreads.a 55 | lib/apple/lib/libevent_pthreads.dylib 56 | lib/apple/lib/libevent_pthreads.la 57 | lib/apple/lib/pkgconfig/libevent.pc 58 | lib/apple/lib/pkgconfig/libevent_openssl.pc 59 | lib/apple/lib/pkgconfig/libevent_pthreads.pc 60 | lib/linux/libstream.a 61 | lib/ 62 | Win32/Debug/ZERO_CHECK/ZERO_CHECK.log 63 | .vscode/settings.json 64 | 3rd/ 65 | cmake-build-debug/CMakeCache.txt 66 | cmake-build-debug/CMakeFiles/clion-environment.txt 67 | cmake-build-debug/CMakeFiles/clion-log.txt 68 | cmake-build-debug/CMakeFiles/cmake.check_cache 69 | cmake-build-debug/CMakeFiles/CMakeError.log 70 | cmake-build-debug/CMakeFiles/CMakeOutput.log 71 | cmake-build-debug/CMakeFiles/3.10.3/CMakeSystem.cmake 72 | cmake-build-debug/CMakeFiles/3.10.3/CompilerIdC/CMakeCCompilerId.c 73 | cmake-build-debug/CMakeFiles/3.10.3/CompilerIdC/CMakeCCompilerId.o 74 | cmake-build-debug/CMakeFiles/3.10.3/CompilerIdCXX/CMakeCXXCompilerId.cpp 75 | cmake-build-debug/CMakeFiles/3.10.3/CompilerIdCXX/CMakeCXXCompilerId.o 76 | cmake-build-debug/BLOCK.cbp 77 | cmake-build-debug/cmake_install.cmake 78 | cmake-build-debug/Makefile 79 | cmake-build-debug/CMakeFiles/CMakeDirectoryInformation.cmake 80 | cmake-build-debug/CMakeFiles/feature_tests.bin 81 | cmake-build-debug/CMakeFiles/feature_tests.c 82 | cmake-build-debug/CMakeFiles/feature_tests.cxx 83 | cmake-build-debug/CMakeFiles/Makefile.cmake 84 | cmake-build-debug/CMakeFiles/Makefile2 85 | cmake-build-debug/CMakeFiles/progress.marks 86 | cmake-build-debug/CMakeFiles/TargetDirectories.txt 87 | cmake-build-debug/CMakeFiles/3.10.3/CMakeCCompiler.cmake 88 | cmake-build-debug/CMakeFiles/3.10.3/CMakeCXXCompiler.cmake 89 | cmake-build-debug/CMakeFiles/3.10.3/CMakeDetermineCompilerABI_C.bin 90 | cmake-build-debug/CMakeFiles/3.10.3/CMakeDetermineCompilerABI_CXX.bin 91 | cmake-build-debug/core/cmake_install.cmake 92 | cmake-build-debug/core/core.cbp 93 | cmake-build-debug/core/Makefile 94 | cmake-build-debug/core/CMakeFiles/CMakeDirectoryInformation.cmake 95 | cmake-build-debug/core/CMakeFiles/progress.marks 96 | cmake-build-debug/core/CMakeFiles/core.dir/build.make 97 | cmake-build-debug/core/CMakeFiles/core.dir/cmake_clean.cmake 98 | cmake-build-debug/core/CMakeFiles/core.dir/cmake_clean_target.cmake 99 | cmake-build-debug/core/CMakeFiles/core.dir/depend.make 100 | cmake-build-debug/core/CMakeFiles/core.dir/DependInfo.cmake 101 | cmake-build-debug/core/CMakeFiles/core.dir/flags.make 102 | cmake-build-debug/core/CMakeFiles/core.dir/link.txt 103 | cmake-build-debug/core/CMakeFiles/core.dir/progress.make 104 | cmake-build-debug/modules/cmake_install.cmake 105 | cmake-build-debug/modules/Makefile 106 | cmake-build-debug/modules/CMakeFiles/CMakeDirectoryInformation.cmake 107 | cmake-build-debug/modules/CMakeFiles/progress.marks 108 | cmake-build-debug/modules/dbProxy/cmake_install.cmake 109 | cmake-build-debug/modules/dbProxy/dbProxy.cbp 110 | cmake-build-debug/modules/dbProxy/Makefile 111 | cmake-build-debug/modules/dbProxy/CMakeFiles/CMakeDirectoryInformation.cmake 112 | cmake-build-debug/modules/dbProxy/CMakeFiles/progress.marks 113 | cmake-build-debug/modules/dbProxy/CMakeFiles/dbProxy.dir/build.make 114 | cmake-build-debug/modules/dbProxy/CMakeFiles/dbProxy.dir/cmake_clean.cmake 115 | cmake-build-debug/modules/dbProxy/CMakeFiles/dbProxy.dir/cmake_clean_target.cmake 116 | cmake-build-debug/modules/dbProxy/CMakeFiles/dbProxy.dir/depend.make 117 | cmake-build-debug/modules/dbProxy/CMakeFiles/dbProxy.dir/DependInfo.cmake 118 | cmake-build-debug/modules/dbProxy/CMakeFiles/dbProxy.dir/flags.make 119 | cmake-build-debug/modules/dbProxy/CMakeFiles/dbProxy.dir/link.txt 120 | cmake-build-debug/modules/dbProxy/CMakeFiles/dbProxy.dir/progress.make 121 | cmake-build-debug/modules/distributed/cmake_install.cmake 122 | cmake-build-debug/modules/distributed/distributed.cbp 123 | cmake-build-debug/modules/distributed/Makefile 124 | cmake-build-debug/modules/distributed/CMakeFiles/CMakeDirectoryInformation.cmake 125 | cmake-build-debug/modules/distributed/CMakeFiles/progress.marks 126 | cmake-build-debug/modules/distributed/CMakeFiles/distributed.dir/build.make 127 | cmake-build-debug/modules/distributed/CMakeFiles/distributed.dir/cmake_clean.cmake 128 | cmake-build-debug/modules/distributed/CMakeFiles/distributed.dir/cmake_clean_target.cmake 129 | cmake-build-debug/modules/distributed/CMakeFiles/distributed.dir/depend.make 130 | cmake-build-debug/modules/distributed/CMakeFiles/distributed.dir/DependInfo.cmake 131 | cmake-build-debug/modules/distributed/CMakeFiles/distributed.dir/flags.make 132 | cmake-build-debug/modules/distributed/CMakeFiles/distributed.dir/link.txt 133 | cmake-build-debug/modules/distributed/CMakeFiles/distributed.dir/progress.make 134 | cmake-build-debug/modules/luaAdapter/cmake_install.cmake 135 | cmake-build-debug/modules/luaAdapter/luaAdapter.cbp 136 | cmake-build-debug/modules/luaAdapter/Makefile 137 | cmake-build-debug/modules/luaAdapter/CMakeFiles/CMakeDirectoryInformation.cmake 138 | cmake-build-debug/modules/luaAdapter/CMakeFiles/progress.marks 139 | cmake-build-debug/modules/luaAdapter/CMakeFiles/luaAdapter.dir/build.make 140 | cmake-build-debug/modules/luaAdapter/CMakeFiles/luaAdapter.dir/cmake_clean.cmake 141 | cmake-build-debug/modules/luaAdapter/CMakeFiles/luaAdapter.dir/cmake_clean_target.cmake 142 | cmake-build-debug/modules/luaAdapter/CMakeFiles/luaAdapter.dir/depend.make 143 | cmake-build-debug/modules/luaAdapter/CMakeFiles/luaAdapter.dir/DependInfo.cmake 144 | cmake-build-debug/modules/luaAdapter/CMakeFiles/luaAdapter.dir/flags.make 145 | cmake-build-debug/modules/luaAdapter/CMakeFiles/luaAdapter.dir/link.txt 146 | cmake-build-debug/modules/luaAdapter/CMakeFiles/luaAdapter.dir/progress.make 147 | cmake-build-debug/modules/network/cmake_install.cmake 148 | cmake-build-debug/modules/network/Makefile 149 | cmake-build-debug/modules/network/network.cbp 150 | cmake-build-debug/modules/network/CMakeFiles/CMakeDirectoryInformation.cmake 151 | cmake-build-debug/modules/network/CMakeFiles/progress.marks 152 | cmake-build-debug/modules/network/CMakeFiles/network.dir/build.make 153 | cmake-build-debug/modules/network/CMakeFiles/network.dir/cmake_clean.cmake 154 | cmake-build-debug/modules/network/CMakeFiles/network.dir/cmake_clean_target.cmake 155 | cmake-build-debug/modules/network/CMakeFiles/network.dir/depend.make 156 | cmake-build-debug/modules/network/CMakeFiles/network.dir/DependInfo.cmake 157 | cmake-build-debug/modules/network/CMakeFiles/network.dir/flags.make 158 | cmake-build-debug/modules/network/CMakeFiles/network.dir/link.txt 159 | cmake-build-debug/modules/network/CMakeFiles/network.dir/progress.make 160 | -------------------------------------------------------------------------------- /core/args.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "types.h" 15 | #include "../utils/single.h" 16 | 17 | namespace block 18 | { 19 | class out_of_bound : public std::exception 20 | { 21 | public: 22 | out_of_bound() 23 | : err_("Out of bound") 24 | {} 25 | out_of_bound(const char *desc) 26 | { 27 | err_ = desc; 28 | } 29 | 30 | ~out_of_bound() throw() 31 | { 32 | 33 | } 34 | 35 | virtual const char * what() const throw() 36 | { 37 | return err_.c_str(); 38 | } 39 | 40 | private: 41 | std::string err_; 42 | }; 43 | 44 | struct Bytes 45 | { 46 | Bytes(size_t total = 64) 47 | : total_(total) 48 | , size_(0) 49 | { 50 | assert(total != 0); 51 | assert(total < 1024 * 1024 * 100); 52 | 53 | buff_ = static_cast(calloc(1, total)); 54 | } 55 | 56 | Bytes(const char *buf, size_t len) 57 | : total_(64) 58 | { 59 | assert(len != 0); 60 | assert(len < 1024 * 1024 * 100); 61 | 62 | if (total_ <= len) { 63 | size_t _double_size = total_; 64 | while (_double_size < len) { 65 | _double_size <<= 1; 66 | } 67 | total_ = _double_size; 68 | } 69 | 70 | buff_ = static_cast(calloc(1, total_)); 71 | memcpy(buff_, buf, len); 72 | } 73 | 74 | virtual ~Bytes() 75 | { 76 | if (buff_) { 77 | free(buff_); 78 | buff_ = nullptr; 79 | } 80 | } 81 | 82 | void flush() 83 | { 84 | memset(buff_, 0, size_); 85 | size_ = 0; 86 | } 87 | 88 | bool inc(size_t len) 89 | { 90 | size_t _tmp = size_ + len; 91 | if (_tmp < size_) { 92 | throw out_of_bound(); 93 | } 94 | 95 | if (_tmp <= total_) { 96 | size_ = _tmp; 97 | return false; 98 | } 99 | 100 | size_t _double_size = total_; 101 | while (_double_size < _tmp) { 102 | _double_size <<= 1; 103 | } 104 | 105 | char *_tmp_buf = static_cast(calloc(1, _double_size)); 106 | memcpy(_tmp_buf, buff_, size_); 107 | free(buff_); 108 | 109 | buff_ = _tmp_buf; 110 | size_ = _tmp; 111 | total_ = _double_size; 112 | 113 | return true; 114 | } 115 | 116 | char *buff_; 117 | size_t size_; 118 | size_t total_; 119 | }; 120 | 121 | typedef std::shared_ptr BytesPtr; 122 | 123 | /* 124 | int string list 125 | +---+-------+---+---+-------+---+---+-------+-----------+ small cache = 128 126 | |tag|content|tag|len|content|tag|len|content|000000000... resize cache = original * 2 [256, 512 ...] 127 | +---+-------+---+---+-------+---+---+-------+-----------+ 128 | */ 129 | 130 | struct Args 131 | { 132 | using TypeLen = uint16_t; 133 | using TypeTag = uint8_t; 134 | 135 | Args(); 136 | Args(const char *buf, size_t len); 137 | ~Args(); 138 | 139 | //////////////////////////////// push ////////////////////////////////////// 140 | void push(const uint8_t &val); 141 | void push(const int8_t &val); 142 | void push(const uint16_t &val); 143 | void push(const int16_t &val); 144 | void push(const uint32_t &val); 145 | void push(const int32_t &val); 146 | void push(const uint64_t &val); 147 | void push(const int64_t &val); 148 | void push(const bool &val); 149 | void push(const float &val); 150 | void push(const double &val); 151 | void push(const char *val, size_t len); 152 | void push(const std::string &val); 153 | 154 | template 155 | void push_impl(const T &val); 156 | 157 | template 158 | void push(std::list &list); 159 | 160 | template 161 | void push(std::vector &vec); 162 | 163 | template 164 | void push(std::map &map); 165 | 166 | //void push_block(const char *block, int len); 167 | 168 | // lua 169 | void push_ui16(const uint16_t &val); 170 | void push_ui32(const uint32_t &val); 171 | void push_i32(const int32_t &val); 172 | void push_i64(const int64_t &val); 173 | void push_float(const float &val); 174 | void push_double(const double &val); 175 | void push_string(const std::string &val); 176 | void push_bool(const bool &val); 177 | 178 | ///////////////////////////////// pop ////////////////////////////////// 179 | void pop_impl(uint8_t &val); 180 | void pop_impl(int8_t &val); 181 | void pop_impl(uint16_t &val); 182 | void pop_impl(int16_t &val); 183 | void pop_impl(uint32_t &val); 184 | void pop_impl(int32_t &val); 185 | void pop_impl(uint64_t &val); 186 | void pop_impl(int64_t &val); 187 | void pop_impl(bool &val); 188 | void pop_impl(float &val); 189 | void pop_impl(double &val); 190 | 191 | TypeLen pop_typelen(); 192 | 193 | std::string pop_string(); 194 | 195 | template 196 | std::list pop_list(); 197 | 198 | template 199 | std::vector pop_vec(); 200 | 201 | template 202 | std::map pop_map(); 203 | 204 | //std::string pop_block(); 205 | 206 | template 207 | void pop(T &val); 208 | 209 | // lua 210 | uint8_t pop_tag(); 211 | uint8_t pop_ui8(); 212 | int8_t pop_i8(); 213 | uint16_t pop_ui16(); 214 | int16_t pop_i16(); 215 | uint32_t pop_ui32(); 216 | int32_t pop_i32(); 217 | uint64_t pop_ui64(); 218 | int64_t pop_i64(); 219 | bool pop_bool(); 220 | float pop_float(); 221 | double pop_double(); 222 | 223 | block::SessionID pop_fd(); 224 | block::MsgID pop_msgid(); 225 | block::ModuleID pop_moduleid(); 226 | block::TimerID pop_timerid(); 227 | 228 | /////////////////////////////////get////////////////////////////////////// 229 | int get_tag(); 230 | uint32_t get_size() const; 231 | uint32_t get_params_count() const; 232 | uint32_t get_offset() const; 233 | 234 | std::string exportBuf(); 235 | void importBuf(const std::string &str); 236 | 237 | //! debug 238 | std::string print() const; 239 | ///////////////////////////////peek/////////////////////////////////////// 240 | uint8_t peek_tag(); 241 | void * peek(uint8_t type); 242 | std::pair peek_str(); 243 | 244 | ////////////////////////////////////////////////////////////////////////// 245 | 246 | //! private 247 | void flush(); 248 | 249 | void inc(size_t len); 250 | 251 | private: 252 | 253 | BytesPtr bytes_ = nullptr; 254 | char *write_ = nullptr; 255 | char *read_ = nullptr; 256 | 257 | const char *tail_ = nullptr; 258 | size_t params_ = 0; 259 | uint32_t offset_ = 0; 260 | }; 261 | 262 | using deleter_type = std::function; 263 | using ArgsPtr = std::unique_ptr; 264 | 265 | struct ArgsPool : public block::utils::Singleton 266 | { 267 | std::unique_ptr get() 268 | { 269 | #ifdef WATCH_PERF 270 | count_++; 271 | #endif // WATCH_PERF 272 | pool_use_++; 273 | resize(); 274 | 275 | std::unique_ptr _ptr(pool_.back().release(), [this](Args *args) { 276 | args->flush(); 277 | dirty_vec_.push_back(args); 278 | }); 279 | 280 | pool_.pop_back(); 281 | return _ptr; 282 | } 283 | 284 | void make(uint32_t size) 285 | { 286 | for (uint32_t i = 0; i < size; ++i) 287 | { 288 | pool_.push_back(std::make_unique()); 289 | } 290 | 291 | pool_size_ += size; 292 | } 293 | 294 | void reenter() 295 | { 296 | for (auto it : dirty_vec_) 297 | { 298 | pool_.push_back(std::unique_ptr(it)); 299 | pool_use_--; 300 | } 301 | dirty_vec_.clear(); 302 | #ifdef WATCH_PERF 303 | if (count_ > maximun_) { 304 | maximun_ = count_; 305 | count_ = 0; 306 | } 307 | #endif // WATCH_PERF 308 | } 309 | 310 | #ifdef WATCH_PERF 311 | std::string get_perf() 312 | { 313 | std::string _perf = "event pool : single frame maximun use " + std::to_string(maximun_) + '\n'; 314 | _perf += "event pool : size = " + std::to_string(pool_.size()) + '\n'; 315 | maximun_ = 0; 316 | return _perf; 317 | } 318 | 319 | uint32_t count_ = 0; 320 | uint32_t maximun_ = 0; 321 | #endif 322 | 323 | protected: 324 | //! 当池子不够的时候申请更多的空间 325 | void resize() 326 | { 327 | size_t _expanSize = static_cast(pool_size_ * 0.7); 328 | if (pool_use_ > _expanSize) { 329 | make(pool_size_ * 2); 330 | } 331 | } 332 | 333 | private: 334 | std::vector> pool_; 335 | int32_t pool_size_ = 0; 336 | uint32_t pool_use_ = 0; 337 | 338 | std::vector dirty_vec_; 339 | }; 340 | 341 | 342 | template 343 | static void pushArg(ArgsPtr &args, P0 &&p0, P &&... p) 344 | { 345 | args->push(std::forward(p0)); 346 | pushArg(args, std::forward

(p)...); 347 | } 348 | 349 | static void pushArg(ArgsPtr &args) 350 | { 351 | //template terminate 352 | } 353 | 354 | template 355 | ArgsPtr makeArgs(P&& ...upvalues) 356 | { 357 | auto args = ArgsPool::get_ref().get(); 358 | 359 | pushArg(args, std::forward

(upvalues)...); 360 | 361 | return args; 362 | } 363 | } -------------------------------------------------------------------------------- /modules/dbProxy/mysqlConnect.cpp: -------------------------------------------------------------------------------- 1 | #include "mysqlConnect.h" 2 | 3 | #include 4 | 5 | 6 | uint8_t ToValueType(enum_field_types mysqlType) 7 | { 8 | switch (mysqlType) 9 | { 10 | case FIELD_TYPE_TIMESTAMP: 11 | case FIELD_TYPE_DATE: 12 | case FIELD_TYPE_TIME: 13 | case FIELD_TYPE_DATETIME: 14 | case FIELD_TYPE_YEAR: 15 | case FIELD_TYPE_STRING: 16 | case FIELD_TYPE_VAR_STRING: 17 | case FIELD_TYPE_BLOB: 18 | return block::at_block; 19 | case FIELD_TYPE_SET: 20 | case FIELD_TYPE_NULL: 21 | return block::at_string; 22 | case FIELD_TYPE_TINY: 23 | case FIELD_TYPE_SHORT: 24 | case FIELD_TYPE_ENUM: 25 | case FIELD_TYPE_LONG: 26 | return block::at_int32; 27 | case FIELD_TYPE_INT24: 28 | case FIELD_TYPE_LONGLONG: 29 | return block::at_int64; 30 | case FIELD_TYPE_DECIMAL: 31 | case FIELD_TYPE_FLOAT: 32 | return block::at_float; 33 | case FIELD_TYPE_DOUBLE: 34 | return block::at_double; 35 | default: 36 | return block::at_eof; 37 | } 38 | } 39 | 40 | std::pair ToMySqlType(uint8_t cppType) 41 | { 42 | std::pair ret(MYSQL_TYPE_NULL, 0); 43 | 44 | switch (cppType) 45 | { 46 | case block::at_uint8: 47 | ret.first = MYSQL_TYPE_TINY; 48 | ret.second = 1; 49 | break; 50 | case block::at_int8: 51 | ret.first = MYSQL_TYPE_TINY; 52 | ret.second = 0; 53 | break; 54 | case block::at_uint16: 55 | ret.first = MYSQL_TYPE_SHORT; 56 | ret.second = 1; 57 | break; 58 | case block::at_int16: 59 | ret.first = MYSQL_TYPE_SHORT; 60 | ret.second = 0; 61 | break; 62 | case block::at_uint32: 63 | ret.first = MYSQL_TYPE_LONG; 64 | ret.second = 1; 65 | break; 66 | case block::at_int32: 67 | ret.first = MYSQL_TYPE_LONG; 68 | ret.second = 0; 69 | break; 70 | case block::at_uint64: 71 | ret.first = MYSQL_TYPE_LONGLONG; 72 | ret.second = 1; 73 | break; 74 | case block::at_int64: 75 | ret.first = MYSQL_TYPE_LONGLONG; 76 | ret.second = 0; 77 | break; 78 | case block::at_float: 79 | ret.first = MYSQL_TYPE_FLOAT; 80 | ret.second = 0; 81 | break; 82 | case block::at_double: 83 | ret.first = MYSQL_TYPE_DOUBLE; 84 | ret.second = 0; 85 | break; 86 | case block::at_string: 87 | ret.first = MYSQL_TYPE_STRING; 88 | ret.second = 0; 89 | break; 90 | } 91 | return ret; 92 | } 93 | 94 | block::modules::MysqlConnect::MysqlConnect() 95 | { 96 | 97 | } 98 | 99 | block::modules::MysqlConnect::~MysqlConnect() 100 | { 101 | 102 | } 103 | 104 | bool block::modules::MysqlConnect::init(const std::string &host, int port, const std::string &user, const std::string &pwd, const std::string &name) 105 | { 106 | auto init = mysql_init(nullptr); 107 | if (nullptr == init) { 108 | ERROR_LOG("[BLOCK] MysqlConnect init fail!"); 109 | return false; 110 | } 111 | 112 | basePtr_ = mysql_real_connect(init, host.c_str(), user.c_str(), pwd.c_str(), name.c_str(), port, nullptr, 0); 113 | if (nullptr == basePtr_) { 114 | ERROR_LOG("[BLOCK] MysqlConnect connect fail!"); 115 | //mysql_close(base); 116 | return false; 117 | } 118 | 119 | INFO_LOG("[BLOCK] MysqlConnect init success!"); 120 | return true; 121 | } 122 | 123 | 124 | bool block::modules::MysqlConnect::insert(const std::string &query, const char *buf, unsigned long len) 125 | { 126 | SqlStmtPtr stmt; 127 | perpare(query, stmt); 128 | 129 | MYSQL_BIND params[2]; 130 | memset(params, 0, sizeof(params)); 131 | 132 | int id = 0; 133 | 134 | params[0].buffer_type = MYSQL_TYPE_LONG; 135 | params[0].buffer = &id; 136 | 137 | char *blobBuf = nullptr; 138 | try { 139 | blobBuf = new char(len); 140 | } 141 | catch (...) { 142 | mysql_stmt_close(stmt->stmt); 143 | ERROR_LOG("[BLOCK] MysqlConnect insert out of memory"); 144 | return false; 145 | } 146 | std::shared_ptr(blobBuf, [](char *p)->void { delete[] p; }); 147 | 148 | params[1].buffer_type = MYSQL_TYPE_BLOB; 149 | params[1].buffer_length = 10240; 150 | params[1].length = &len; 151 | params[1].is_null = 0; 152 | params[1].buffer = blobBuf; 153 | memcpy(blobBuf, buf, len); 154 | 155 | // bind input arguments 156 | if (mysql_stmt_bind_param(stmt->stmt, params)) 157 | { 158 | std::cout << mysql_stmt_error(stmt->stmt) << std::endl; 159 | return false; 160 | } 161 | 162 | if (mysql_stmt_execute(stmt->stmt)) 163 | { 164 | std::cout << mysql_stmt_error(stmt->stmt) << std::endl; 165 | return false; 166 | } 167 | 168 | return true; 169 | } 170 | 171 | void block::modules::MysqlConnect::update(const std::string &query, const char *buf, unsigned long len) 172 | { 173 | assert(len > 0 && len < 10240); 174 | 175 | SqlStmtPtr stmt; 176 | perpare(query, stmt); 177 | 178 | MYSQL_BIND params[1]; 179 | memset(params, 0, sizeof(params)); 180 | 181 | char *tbuf = nullptr; 182 | try { 183 | tbuf = new char[len]; 184 | } 185 | catch (...) { 186 | mysql_stmt_close(stmt->stmt); 187 | ERROR_LOG("[BLOCK] MysqlConnect update out of memory"); 188 | return; 189 | } 190 | 191 | memcpy(tbuf, buf, len); 192 | 193 | params[0].buffer_type = MYSQL_TYPE_BLOB; 194 | params[0].buffer_length = 10240; 195 | params[0].length = &len; 196 | params[0].is_null = 0; 197 | params[0].buffer = tbuf; 198 | 199 | // bind input arguments 200 | if (mysql_stmt_bind_param(stmt->stmt, params)) 201 | { 202 | std::cout << mysql_stmt_error(stmt->stmt) << std::endl; 203 | } 204 | 205 | if (mysql_stmt_execute(stmt->stmt)) 206 | { 207 | std::cout << mysql_stmt_error(stmt->stmt) << std::endl; 208 | } 209 | 210 | delete tbuf; 211 | } 212 | 213 | void block::modules::MysqlConnect::execSql(block::ModuleID target, int oper, const std::string &sql, std::function callback) 214 | { 215 | MYSQL_RES *result = nullptr; 216 | MYSQL_FIELD *fields = nullptr; 217 | 218 | int _progress = 1; 219 | 220 | auto errf = [&](const std::string &err) { 221 | if (callback) { 222 | callback(target, block::makeArgs(oper, false, 0, 0, err)); 223 | } 224 | else { 225 | ERROR_FMTLOG("[BLOCK] MysqlConnect execSql query fail err : {}", err); 226 | } 227 | }; 228 | 229 | if (nullptr == basePtr_) { 230 | ERROR_LOG("[BLOCK] MysqlConnect execSql fail, connect disable"); 231 | return ; 232 | } 233 | 234 | if (mysql_query(basePtr_, sql.c_str())) { 235 | errf(mysql_error(basePtr_)); 236 | return; 237 | } 238 | 239 | result = mysql_store_result(basePtr_); 240 | if (nullptr == result) { 241 | if (callback) { 242 | callback(target, block::makeArgs(oper, true, 0, 0, "success!")); 243 | } 244 | return; 245 | } 246 | 247 | int32_t rowCount = static_cast(mysql_affected_rows(basePtr_)); 248 | if (0 == rowCount) { 249 | mysql_free_result(result); 250 | errf("row = 0"); 251 | return; 252 | } 253 | 254 | uint32_t fieldCount = mysql_field_count(basePtr_); 255 | fields = mysql_fetch_fields(result); 256 | 257 | std::vector> col_tags; 258 | 259 | for (uint32_t i = 0; i < fieldCount; ++i) 260 | { 261 | col_tags.push_back(std::make_pair(fields[i].name, ToValueType(fields[i].type))); 262 | } 263 | 264 | MYSQL_ROW row; 265 | row = mysql_fetch_row(result); 266 | unsigned long* lengths = mysql_fetch_lengths(result); 267 | size_t col = 0; 268 | 269 | while (nullptr != row) 270 | { 271 | auto argsPtr = block::ArgsPool::get_ref().get(); 272 | argsPtr->push(oper); 273 | argsPtr->push(true); 274 | argsPtr->push(rowCount); 275 | argsPtr->push(_progress); 276 | 277 | for (size_t col = 0; col < fieldCount; col++) 278 | { 279 | auto _val = row[col]; 280 | 281 | switch (col_tags[col].second) 282 | { 283 | case block::at_int32: 284 | argsPtr->push_i32(row[col] != nullptr ? std::stoul(row[col]) : 0); 285 | break; 286 | case block::at_int64: 287 | argsPtr->push_i64(row[col] != nullptr ? std::stoull(row[col]) : 0); 288 | break; 289 | case block::at_float: 290 | argsPtr->push_float(row[col] != nullptr ? std::stof(row[col]) : 0); 291 | break; 292 | case block::at_double: 293 | argsPtr->push_double(row[col] != nullptr ? std::stod(row[col]) : 0); 294 | break; 295 | case block::at_string: 296 | argsPtr->push_string((row[col] != nullptr) ? row[col] : ""); 297 | break; 298 | case block::at_block: 299 | std::string _str = ""; 300 | _str.assign(row[col], lengths[col]); 301 | argsPtr->push_string(_str); 302 | break; 303 | } 304 | } 305 | callback(target, std::move(argsPtr)); 306 | 307 | _progress++; 308 | 309 | row = mysql_fetch_row(result); 310 | } 311 | 312 | if (nullptr != result) 313 | { 314 | mysql_free_result(result); 315 | } 316 | } 317 | 318 | void block::modules::MysqlConnect::perpare(const std::string &sql, SqlStmtPtr &stmtPtr) 319 | { 320 | 321 | auto itr = prepared_stmt_map.find(sql); 322 | if (itr != prepared_stmt_map.end()) { 323 | stmtPtr = itr->second; 324 | return; 325 | } 326 | 327 | do { 328 | if (nullptr == basePtr_) { 329 | ERROR_LOG("[BLOCK] MysqlConnect perpare fail, connect disable"); 330 | break; 331 | } 332 | 333 | stmtPtr = std::make_shared(); 334 | stmtPtr->sql = sql; 335 | 336 | stmtPtr->stmt = mysql_stmt_init(basePtr_); 337 | if (nullptr == stmtPtr->stmt) { 338 | ERROR_LOG("[BLOCK] MysqlConnect stmt init fail!"); 339 | break; 340 | } 341 | 342 | if (mysql_stmt_prepare(stmtPtr->stmt, sql.c_str(), (unsigned long)sql.size())) { 343 | std::cout << mysql_stmt_error(stmtPtr->stmt) << std::endl; 344 | break; 345 | } 346 | 347 | stmtPtr->params = mysql_stmt_param_count(stmtPtr->stmt); 348 | stmtPtr->result = mysql_stmt_result_metadata(stmtPtr->stmt); 349 | 350 | std::string sqlop = sql.substr(0, 6); 351 | if (nullptr == stmtPtr->result && (strcmp(sqlop.c_str(), "SELECT") == 0 || strcmp(sqlop.c_str(), "select") == 0)) { 352 | std::cout << mysql_stmt_error(stmtPtr->stmt) << std::endl; 353 | break; 354 | } 355 | 356 | if (stmtPtr->result) { 357 | stmtPtr->is_query = true; 358 | stmtPtr->columns = mysql_num_fields(stmtPtr->result); 359 | } 360 | prepared_stmt_map.emplace(sql, stmtPtr); 361 | return; 362 | 363 | } while (0); 364 | 365 | stmtPtr.reset(); 366 | 367 | } -------------------------------------------------------------------------------- /modules/dbProxy/redisConnect.h: -------------------------------------------------------------------------------- 1 | #ifndef _REDIS_CACHE_PROXY_HEADER_ 2 | #define _REDIS_CACHE_PROXY_HEADER_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "hiredis.h" 9 | 10 | #ifdef WIN32 11 | #include 12 | #endif // WIN32 13 | 14 | #include 15 | #include 16 | 17 | namespace block 18 | { 19 | namespace modules 20 | { 21 | // rdb 22 | // 在 redis config 文件中 23 | // 找到 SNAPSHOTTING 模块,打开 save "" 关闭rdb文件 24 | 25 | // aof 26 | // 找到 APPEND ONLY MODE 模块 27 | // appendonly yes 打开aof 28 | // appendfilename "" 设置aof文件名 29 | // appendfsync 同步方式选择 everysec 30 | // no-appendfsync-on-rewrite 设置为 no ,保证数据安全。 如果设置为yes在子进程保存的时候会阻塞redis 31 | 32 | // refresh 33 | // 依据客户端的 BGREWRITEAOF 命令, 如果redis正在进行aof 则等待完成之后执行,反正则立即执行。 34 | // #auto-aof-rewrite-percentage 100 关闭自动rewrite 35 | // #auto - aof - rewrite - min - size 64mb 关闭自动rewrite 36 | 37 | struct BlockRedisReply 38 | { 39 | BlockRedisReply(redisReply *reply) 40 | : reply_(reply) { 41 | 42 | } 43 | 44 | ~BlockRedisReply() { 45 | freeReplyObject(reply_); 46 | } 47 | 48 | bool check(const std::string &flag) { 49 | assert(reply_ && reply_->type != REDIS_REPLY_ERROR); 50 | 51 | if (reply_->type == REDIS_REPLY_ERROR) { 52 | ERROR_FMTLOG("[BLOCK] RedisReply cmd : {} err : {}", flag , reply_->str); 53 | return false; 54 | } 55 | 56 | return true; 57 | } 58 | 59 | int type() { 60 | return reply_->type; 61 | } 62 | 63 | int64_t integer() { 64 | return reply_->integer; 65 | } 66 | 67 | std::string str() { 68 | std::string _t(reply_->str, reply_->len); 69 | return _t; 70 | } 71 | 72 | redisReply * reply_; 73 | }; 74 | 75 | typedef std::shared_ptr ReplyPtr; 76 | 77 | /**! 78 | hash 用于保存entity实例 79 | list 用于存放entity的更新操作 80 | 在mergeTimeSpace_ 和 mergeCountSpace_ 两个值到达预设的时候会合并list中的更新操作,覆盖到hash 81 | 82 | 这里序列化的方法 以及 合并数据的方法应该由外部提供。 83 | */ 84 | template 85 | class RedisConnect 86 | { 87 | public: 88 | 89 | bool init(); 90 | void uninit(); 91 | 92 | /**! 93 | 将对象添加到缓存中,时间到达或者次数到达则写入到数据库 94 | */ 95 | bool push(const std::string &field, uint32_t key, const std::string &buf); 96 | 97 | /**! 98 | * 获得缓存中的实例, 会自动执行一次合并以保证获取到最新的实例. 99 | */ 100 | std::string get(const std::string &field, uint32_t key); 101 | std::vector> getAll(); 102 | 103 | /**! 104 | 从缓存中清除某个对象 105 | */ 106 | bool remove(const std::string &key); 107 | 108 | /**! 109 | 在进程的主循环中调用 110 | */ 111 | void run(); 112 | 113 | /**! 114 | 服务器正常退出时调用, 清空redis 115 | */ 116 | void flush_redis_handler(); 117 | 118 | protected: 119 | 120 | /*! 121 | 检查连接是否存在,如果断开则尝试重连。 122 | **/ 123 | bool checkConnect(); 124 | 125 | /**! 126 | 重刷aof文件,体积优化 127 | */ 128 | void refresh(); 129 | 130 | std::pair pop(uint32_t key); 131 | 132 | int getListLen(uint32_t key); 133 | 134 | ReplyPtr command(redisContext *c, const char *format, ...); 135 | 136 | void merge(uint32_t key); 137 | 138 | private: 139 | 140 | std::string ip_ = "127.0.0.1"; 141 | uint32_t port_ = 6379; 142 | 143 | //! 判断连接是否正常 144 | bool is_conn_ = false; 145 | 146 | redisContext *redis_context_; 147 | uint32_t pipeLineCount_ = 0; 148 | std::set keys_; 149 | 150 | std::string field_ = ""; 151 | uint32_t updateCount_ = 0; 152 | uint64_t updateTime_ = APP.getSystemTick(); 153 | uint64_t refreshTime_ = APP.getSystemTick(); 154 | 155 | const uint32_t mergeTimeSpace_ = 1000 * 60 * 2; 156 | const uint32_t mergeCountSpace_ = 100; 157 | const uint32_t refreshSpace_ = 1000 * 60 * 10; 158 | }; 159 | 160 | template 161 | ReplyPtr block::modules::RedisConnect::command(redisContext *c, const char *format, ...) 162 | { 163 | va_list ap; 164 | void *reply = NULL; 165 | va_start(ap, format); 166 | reply = redisvCommand(c, format, ap); 167 | va_end(ap); 168 | 169 | return std::make_shared(static_cast(reply)); 170 | } 171 | 172 | template 173 | bool block::modules::RedisConnect::init() 174 | { 175 | using namespace std::placeholders; 176 | 177 | struct timeval _timeout = { 1, 500000 }; 178 | 179 | redis_context_ = redisConnectWithTimeout(ip_.c_str(), port_, _timeout); 180 | if (redis_context_ && redis_context_->err == 0) { 181 | is_conn_ = true; 182 | } 183 | else { 184 | ERROR_LOG("[BLOCK] RedisConnect init fail"); 185 | } 186 | 187 | return is_conn_; 188 | } 189 | 190 | template 191 | void block::modules::RedisConnect::uninit() 192 | { 193 | updateCount_ = 0; 194 | pipeLineCount_ = 0; 195 | is_conn_ = false; 196 | 197 | flush_redis_handler(); 198 | 199 | redisFree(redis_context_); 200 | } 201 | 202 | template 203 | bool block::modules::RedisConnect::push(const std::string &field, uint32_t key, const std::string &buf) 204 | { 205 | bool _flag = false; 206 | 207 | do{ 208 | if (field_ != "" && field_ != field){ 209 | ERROR_LOG("[BLOCK] RedisConnect push field cannot be changed!"); 210 | break; 211 | } 212 | 213 | if (!checkConnect()){ 214 | break; 215 | } 216 | 217 | std::string _keystr = std::to_string(key); 218 | 219 | auto hgetReply = command(redis_context_, "HGET %s %s", field.c_str(), _keystr.c_str()); 220 | if (!hgetReply->check("hget")) { 221 | break; 222 | } 223 | 224 | if (hgetReply->type() == REDIS_REPLY_NIL){ 225 | 226 | auto hsetReplay = command(redis_context_, "HSET %s %s %b", field.c_str(), _keystr.c_str(), buf.c_str(), buf.length()); 227 | if (!hsetReplay->check("hset")) { 228 | break; 229 | } 230 | } 231 | else { 232 | if (REDIS_OK != redisAppendCommand(redis_context_, "RPUSH %s %b", _keystr.c_str(), buf.c_str(), buf.length())) 233 | { 234 | ERROR_LOG("[BLOCK] RedisConnect push redis append command fail!"); 235 | } 236 | 237 | pipeLineCount_++; 238 | } 239 | 240 | keys_.insert(key); 241 | field_ = field; 242 | _flag = true; 243 | } while (0); 244 | 245 | return _flag; 246 | } 247 | } 248 | 249 | template 250 | std::string block::modules::RedisConnect::get(const std::string &field, uint32_t key) 251 | { 252 | merge(key); 253 | 254 | std::string _keystr = std::to_string(key); 255 | 256 | auto replyPtr = command(redis_context_, "HGET %s %s", field.c_str(), _keystr.c_str()); 257 | if (!replyPtr->check("get")) { 258 | return ""; 259 | } 260 | 261 | if (replyPtr->type() == REDIS_REPLY_NIL) { 262 | return ""; 263 | } 264 | 265 | return replyPtr->str(); 266 | } 267 | 268 | 269 | template 270 | std::vector> block::modules::RedisConnect::getAll() 271 | { 272 | std::vector> _vec; 273 | 274 | for (auto key : keys_) 275 | { 276 | merge(key); 277 | 278 | std::string _keystr = std::to_string(key); 279 | 280 | auto replyPtr = command(redis_context_, "HGET %s %s", field_.c_str(), _keystr.c_str()); 281 | if (!replyPtr->check("get all")) { 282 | break; 283 | } 284 | 285 | _vec.push_back(std::make_pair(key, _keystr)); 286 | } 287 | 288 | return _vec; 289 | } 290 | 291 | template 292 | void block::modules::RedisConnect::run() 293 | { 294 | 295 | if (pipeLineCount_ == 0) { 296 | return; 297 | } 298 | 299 | if (!checkConnect()) { 300 | return; 301 | } 302 | 303 | redisReply *_replay_ptr; 304 | for (uint32_t i = 0; i < pipeLineCount_; ++i) 305 | { 306 | if (REDIS_OK != redisGetReply(redis_context_, (void**)&_replay_ptr)) { 307 | ERROR_LOG("[BLOCK] RedisConnect exec fail!"); 308 | } 309 | 310 | freeReplyObject(_replay_ptr); 311 | } 312 | 313 | updateCount_ += pipeLineCount_; 314 | using namespace std::chrono; 315 | auto _curTime = APP.getSystemTick(); 316 | if ((_curTime - updateTime_) > mergeTimeSpace_ || updateCount_ > mergeCountSpace_){ 317 | 318 | //! 更新到hash 319 | for (auto key : keys_) 320 | { 321 | merge(key); 322 | } 323 | 324 | updateTime_ = _curTime; 325 | updateCount_ = 0; 326 | } 327 | 328 | if ((_curTime - refreshTime_) > refreshSpace_) { 329 | refresh(); 330 | } 331 | 332 | pipeLineCount_ = 0; 333 | } 334 | 335 | template 336 | std::pair block::modules::RedisConnect::pop(uint32_t key) 337 | { 338 | if (!checkConnect()) { 339 | return std::make_pair(0, ""); 340 | } 341 | 342 | std::string _keystr = std::to_string(key); 343 | 344 | int _len = getListLen(key); 345 | if (_len == 0) { 346 | return std::make_pair(0, ""); 347 | } 348 | 349 | T _t; 350 | 351 | for (int i = 0; i < _len; ++i) 352 | { 353 | auto replayPtr = command(redis_context_, "LPOP %s", _keystr.c_str()); 354 | if (!replayPtr->check("pop")) { 355 | break; 356 | } 357 | 358 | if (i == 0) { 359 | _t.ParseFromString(replayPtr->str()); 360 | } 361 | else { 362 | T _newer; 363 | _newer.ParseFromString(replayPtr->str()); 364 | _t.MergeFrom(_newer); 365 | } 366 | } 367 | 368 | std::string _buf; 369 | int32_t _id = _t.id(); 370 | _t.SerializeToString(&_buf); 371 | 372 | return std::make_pair(_id, _buf); 373 | } 374 | 375 | template 376 | bool block::modules::RedisConnect::checkConnect() 377 | { 378 | if (!is_conn_) { 379 | WARN_LOG("[BLOCK] RedisConnect service terminated! check_connect"); 380 | return false; 381 | } 382 | 383 | auto replyPtr = command(redis_context_, "PING"); 384 | 385 | if (replyPtr->check("ping")) { 386 | return true; 387 | } 388 | else { 389 | WARN_LOG("[BLOCK] RedisConnect connect fail! try reconnect!"); 390 | 391 | struct timeval _timeout = { 1, 500000 }; 392 | 393 | redisFree(redis_context_); 394 | 395 | redis_context_ = redisConnectWithTimeout(ip_.c_str(), port_, _timeout); 396 | if (redis_context_) { 397 | return true; 398 | } 399 | else { 400 | ERROR_LOG("[BLOCK] RedisConnect service terminated! can't connect!"); 401 | return false; 402 | } 403 | } 404 | } 405 | 406 | template 407 | void block::modules::RedisConnect::refresh() 408 | { 409 | if (!checkConnect()) { 410 | return; 411 | } 412 | 413 | auto replyPtr = command(redis_context_, "bgrewriteaof"); 414 | replyPtr->check("bgrewriteaof"); 415 | } 416 | 417 | template 418 | void block::modules::RedisConnect::flush_redis_handler() 419 | { 420 | if (!checkConnect()) { 421 | return; 422 | } 423 | 424 | auto replyPtr = command(redis_context_, "flushall"); 425 | replyPtr->check("flushall"); 426 | } 427 | 428 | template 429 | void block::modules::RedisConnect::merge(uint32_t key) 430 | { 431 | auto _p = pop(key); 432 | if (_p.first != 0) { 433 | 434 | auto hsetReplay = command(redis_context_, "HSET %s %s %b", field_.c_str(), std::to_string(_p.first).c_str(), _p.second.c_str(), _p.second.length()); 435 | hsetReplay->check("exec"); 436 | } 437 | } 438 | 439 | template 440 | int block::modules::RedisConnect::getListLen(uint32_t key) 441 | { 442 | if (!checkConnect()) { 443 | return 0; 444 | } 445 | 446 | std::string _keystr = std::to_string(key); 447 | 448 | auto replyPtr = command(redis_context_, "LLEN %s", _keystr.c_str()); 449 | if (!replyPtr->check("LLEN")) { 450 | return 0; 451 | } 452 | else { 453 | return replyPtr->integer(); 454 | } 455 | 456 | } 457 | } 458 | 459 | #endif 460 | -------------------------------------------------------------------------------- /modules/luaAdapter/luaAdapter.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "luaAdapter.h" 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #ifdef WIN32 11 | #include 12 | #else 13 | #include 14 | #endif // WIN32 15 | 16 | #ifdef __cplusplus 17 | extern "C" { // only need to export C interface if 18 | // used by C++ source code 19 | int luaopen_protobuf_c(lua_State *L); 20 | } 21 | #endif 22 | 23 | std::string Traceback(lua_State * _state) 24 | { 25 | lua_Debug info; 26 | int level = 0; 27 | std::string outputTraceback; 28 | char buffer[4096]; 29 | 30 | while (lua_getstack(_state, level, &info)) 31 | { 32 | lua_getinfo(_state, "nSl", &info); 33 | 34 | #if defined(_WIN32) && defined(_MSC_VER) 35 | sprintf_s(buffer, " [%d] %s:%d -- %s [%s]\n", 36 | level, info.short_src, info.currentline, 37 | (info.name ? info.name : ""), info.what); 38 | #else 39 | sprintf(buffer, " [%d] %s:%d -- %s [%s]\n", 40 | level, info.short_src, info.currentline, 41 | (info.name ? info.name : ""), info.what); 42 | #endif 43 | outputTraceback.append(buffer); 44 | ++level; 45 | } 46 | return outputTraceback; 47 | } 48 | 49 | void block::modules::LuaAdapterModule::before_init() 50 | { 51 | using namespace std::placeholders; 52 | 53 | listen(block::event::script_reload, std::bind(&LuaAdapterModule::eReload, this, _1, _2)); 54 | } 55 | 56 | void block::modules::LuaAdapterModule::init() 57 | { 58 | create(); 59 | } 60 | 61 | void block::modules::LuaAdapterModule::execute() 62 | { 63 | //! 64 | try { 65 | if (reloading) { 66 | create(); 67 | return; 68 | } 69 | 70 | sol::table _module = proxyPtr_->state_.get("module"); 71 | 72 | if (proxyPtr_->app_state_ == LuaAppState::INIT) { 73 | proxyPtr_->call_list_[LuaAppState::INIT](_module); 74 | proxyPtr_->app_state_ = LuaAppState::EXECUTE; 75 | } 76 | else if (proxyPtr_->app_state_ == LuaAppState::EXECUTE) { 77 | proxyPtr_->call_list_[LuaAppState::EXECUTE](_module); 78 | } 79 | else if (proxyPtr_->app_state_ == LuaAppState::SHUT) { 80 | proxyPtr_->call_list_[LuaAppState::SHUT](_module); 81 | proxyPtr_->app_state_ = LuaAppState::AFTER_SHUT; 82 | } 83 | else if (proxyPtr_->app_state_ == LuaAppState::AFTER_SHUT) { 84 | proxyPtr_->call_list_[LuaAppState::AFTER_SHUT](_module); 85 | } 86 | } 87 | catch (sol::error e) { 88 | ERROR_FMTLOG("[BLOCK] LuaAdapter execute sol::error : {} traceback : {}", e.what(), Traceback(proxyPtr_->state_)); 89 | 90 | if (proxyPtr_->app_state_ == LuaAppState::INIT) { 91 | //destroy(_lua->lua_id_); 92 | } 93 | else { 94 | 95 | } 96 | } 97 | } 98 | 99 | void block::modules::LuaAdapterModule::shut() 100 | { 101 | sol::table _module = proxyPtr_->state_.get("module"); 102 | proxyPtr_->call_list_[LuaAppState::SHUT](_module); 103 | } 104 | 105 | void block::modules::LuaAdapterModule::ldispatch(block::ModuleID target, block::EventID event, const std::string &buf) 106 | { 107 | auto _smartPtr = block::ArgsPool::get_ref().get(); 108 | 109 | try { 110 | _smartPtr->importBuf(buf); 111 | 112 | dispatch(target, event, std::move(_smartPtr)); 113 | } 114 | catch (sol::error e) { 115 | ERROR_FMTLOG("[BLOCK] LuaAdapter dispatch sol::error : {} traceback : {}", e.what(), Traceback(proxyPtr_->state_)); 116 | } 117 | catch (...) 118 | { 119 | ERROR_FMTLOG("[BLOCK] LuaAdapter unknown err by ldispatch target:{} event:{}", target, event); 120 | } 121 | } 122 | 123 | int block::modules::LuaAdapterModule::llisten(uint32_t event, const sol::function &func) 124 | { 125 | try { 126 | 127 | listen(event, [=](block::ModuleID target, block::ArgsPtr args)->void { 128 | try { 129 | std::string _req = ""; 130 | if (args) { 131 | //std::cout << args->print() << std::endl; 132 | _req = args->exportBuf(); 133 | func(_req); 134 | } 135 | else { 136 | func(nullptr); 137 | } 138 | } 139 | catch (sol::error e) { 140 | ERROR_FMTLOG("[BLOCK] LuaAdapter listen callback sol::error : {} traceback : {}", e.what(), Traceback(proxyPtr_->state_)); 141 | } 142 | }); 143 | 144 | } 145 | catch (sol::error e) { 146 | ERROR_FMTLOG("[BLOCK] LuaAdapter listen sol::error : {} traceback : {}", e.what(), Traceback(proxyPtr_->state_)); 147 | } 148 | catch (...) 149 | { 150 | ERROR_FMTLOG("[BLOCK] LuaAdapter unknown err by llisten module:{} event:{}", getModuleID(), event); 151 | } 152 | return 0; 153 | } 154 | 155 | void block::modules::LuaAdapterModule::lrpc(uint32_t event, int32_t moduleid, const std::string &buf) 156 | { 157 | /* 158 | auto _smartPtr = block::ArgsPool::get_ref().get(); 159 | auto lua = findLua(lua_id); 160 | 161 | try { 162 | _smartPtr->push_block(buf.c_str(), buf.size()); 163 | 164 | auto _callback = [=](const ArgsPtr &cbArgs, int32_t progress, bool bResult) { 165 | try { 166 | std::string _res = ""; 167 | auto _pos = 0; 168 | if (nullptr != cbArgs) { 169 | _pos = cbArgs->get_size(); 170 | _res = cbArgs->pop_block(0, _pos); 171 | } 172 | func(_res, _pos, progress, bResult); 173 | } 174 | catch (sol::error e) { 175 | std::string _err = e.what() + '\n' + Traceback(findLua(lua_id)->state_); 176 | APP.ERR_LOG("LuaProxy", _err); 177 | } 178 | }; 179 | 180 | if (sol::type::lua_nil == func.get_type()) { 181 | //rpc(event, moduleid, std::move(_smartPtr), nullptr); 182 | } 183 | else { 184 | //rpc(event, moduleid, std::move(_smartPtr), _callback); 185 | } 186 | 187 | } 188 | catch (sol::error e) 189 | { 190 | std::string _err = e.what() + '\n' + Traceback(findLua(lua_id)->state_); 191 | APP.ERR_LOG("LuaProxy", _err); 192 | } 193 | catch (...) 194 | { 195 | APP.ERR_LOG("LuaProxy", "unknown err by llisten", " {} {}", moduleid, event); 196 | } 197 | */ 198 | } 199 | 200 | void block::modules::LuaAdapterModule::create() 201 | { 202 | if (proxyPtr_) { // reload 203 | proxyPtr_.reset(new LuaProxy); 204 | } 205 | else { 206 | proxyPtr_ = std::make_shared(); 207 | } 208 | 209 | proxyPtr_->state_.open_libraries( 210 | sol::lib::os 211 | , sol::lib::base 212 | , sol::lib::package 213 | , sol::lib::math 214 | , sol::lib::io 215 | , sol::lib::table 216 | , sol::lib::string 217 | , sol::lib::debug); 218 | proxyPtr_->dir_name_ = dir_; 219 | proxyPtr_->file_name_ = name_; 220 | 221 | auto _path = dir_ + "/" + name_; 222 | 223 | try 224 | { 225 | // set pbc to lua global 226 | //luaopen_protobuf_c(proxyPtr_->state_.lua_state()); 227 | 228 | proxyPtr_->state_.require("protobuf.c", luaopen_protobuf_c); 229 | 230 | auto _ret = proxyPtr_->state_.do_file(_path.c_str()); 231 | if (_ret) { 232 | std::string _err = Traceback(proxyPtr_->state_.lua_state()) + " build err " 233 | + _path + '\t' + lua_tostring(proxyPtr_->state_.lua_state(), _ret.stack_index()) + "\n"; 234 | 235 | ERROR_FMTLOG("[BLOCK] LuaAdapter build fail : {}", _err); 236 | return; 237 | } 238 | 239 | } 240 | catch (sol::error e) 241 | { 242 | ERROR_FMTLOG("[BLOCK] LuaAdapter build unknown fail : {} traceback : {}", e.what(), Traceback(proxyPtr_->state_.lua_state())); 243 | } 244 | 245 | proxyPtr_->state_.new_usertype("Args" 246 | , sol::constructors() 247 | , "push_ui16", &Args::push_ui16 248 | , "push_ui32", &Args::push_ui32 249 | , "push_i32", &Args::push_i32 250 | , "push_string", &Args::push_string 251 | , "push_bool", &Args::push_bool 252 | , "push_i64", &Args::push_i64 253 | , "pop_string", &Args::pop_string 254 | , "pop_i16", &Args::pop_i16 255 | , "pop_ui16", &Args::pop_ui16 256 | , "pop_ui32", &Args::pop_ui32 257 | , "pop_i32", &Args::pop_i32 258 | , "pop_i64", &Args::pop_i64 259 | , "pop_ui64", &Args::pop_ui64 260 | , "pop_bool", &Args::pop_bool 261 | , "get_size", &Args::get_size 262 | , "get_tag", &Args::get_tag 263 | , "get_offset", &Args::get_offset 264 | , "importBuf", &Args::importBuf 265 | , "exportBuf", &Args::exportBuf); 266 | 267 | proxyPtr_->state_.new_usertype("LuaProxyModule" 268 | , "ldispatch", &LuaAdapterModule::ldispatch 269 | , "llisten", &LuaAdapterModule::llisten 270 | , "lrpc", &LuaAdapterModule::lrpc 271 | , "logDebug", &LuaAdapterModule::llogDebug 272 | , "logInfo", &LuaAdapterModule::llogInfo 273 | , "logWarn", &LuaAdapterModule::llogWarning 274 | , "logError", &LuaAdapterModule::llogError 275 | , "delay", &LuaAdapterModule::ldelay 276 | , "delayDay", &LuaAdapterModule::ldelayDay 277 | , "rmvDelay", &LuaAdapterModule::lrmvDelay); 278 | proxyPtr_->state_.set("self", this); 279 | proxyPtr_->state_.set("module_id", getModuleID()); 280 | 281 | proxyPtr_->state_.new_usertype("Application" 282 | , "getModuleID", &Application::getModuleID 283 | , "getName", &Application::getName 284 | , "getUUID", &Application::getUUID 285 | , "createDynamicModule", &Application::createDynamicModule 286 | , "deleteModule", &Application::deleteModule); 287 | proxyPtr_->state_.set("APP", block::Application::get_ptr()); 288 | 289 | proxyPtr_->call_list_[LuaAppState::BEFORE_INIT] = [&](sol::table t) { 290 | t.get>("before_init")(dir_ + "/"); 291 | }; 292 | proxyPtr_->call_list_[LuaAppState::INIT] = [&](sol::table t) { 293 | t.get>("init")(); 294 | }; 295 | proxyPtr_->call_list_[LuaAppState::EXECUTE] = [&](sol::table t) { 296 | t.get>("execute")(); 297 | }; 298 | proxyPtr_->call_list_[LuaAppState::SHUT] = [&](sol::table t) { 299 | t.get>("shut")(); 300 | }; 301 | proxyPtr_->call_list_[LuaAppState::AFTER_SHUT] = [&](sol::table t) { 302 | t.get>("after_shut")(); 303 | }; 304 | 305 | try { 306 | sol::table _module = proxyPtr_->state_.get("module"); 307 | proxyPtr_->call_list_[LuaAppState::BEFORE_INIT](_module); 308 | proxyPtr_->app_state_ = LuaAppState::INIT; 309 | } 310 | catch (sol::error e) { 311 | ERROR_FMTLOG("[BLOCK] LuaAdapter before init fail err : {} traceback : {}", e.what(), Traceback(proxyPtr_->state_.lua_state())); 312 | return; 313 | } 314 | 315 | reloading = false; 316 | } 317 | 318 | void block::modules::LuaAdapterModule::eReload(block::ModuleID target, block::ArgsPtr args) 319 | { 320 | try { 321 | 322 | sol::table _module = proxyPtr_->state_.get("module"); 323 | proxyPtr_->call_list_[LuaAppState::SHUT](_module); 324 | 325 | reloading = true; 326 | } 327 | catch (sol::error e) { 328 | ERROR_FMTLOG("[BLOCK] LuaAdapter reload fail err : {} traceback : {}", e.what(), Traceback(proxyPtr_->state_.lua_state())); 329 | } 330 | catch (...) { 331 | ERROR_LOG("[BLOCK] LuaAdapter reload unknown err!"); 332 | } 333 | } 334 | 335 | void block::modules::LuaAdapterModule::llogDebug(const std::string &content) 336 | { 337 | DEBUG_LOG(content); 338 | } 339 | 340 | void block::modules::LuaAdapterModule::llogInfo(const std::string &content) 341 | { 342 | INFO_LOG(content); 343 | } 344 | 345 | void block::modules::LuaAdapterModule::llogWarning(const std::string &content) 346 | { 347 | WARN_LOG(content); 348 | } 349 | 350 | void block::modules::LuaAdapterModule::llogError(const std::string &content) 351 | { 352 | ERROR_LOG(content); 353 | } 354 | 355 | uint64_t block::modules::LuaAdapterModule::ldelay(int32_t milliseconds, sol::function callback) 356 | { 357 | auto _tid = TIMER.delay(block::utils::delay_milliseconds(milliseconds), [=]() { 358 | try 359 | { 360 | callback(); 361 | } 362 | catch (sol::error e) { 363 | ERROR_FMTLOG("[BLOCK] LuaAdapter delay func err : {} traceback: {}", e.what(), Traceback(proxyPtr_->state_)); 364 | } 365 | catch (...) 366 | { 367 | ERROR_LOG("[BLOCK] LuaAdapter delay func unknown err"); 368 | } 369 | }); 370 | 371 | return _tid; 372 | } 373 | 374 | uint64_t block::modules::LuaAdapterModule::ldelayDay(int32_t hour, int32_t minute, sol::function callback) 375 | { 376 | auto _tid = TIMER.delay(block::utils::delay_day(hour, minute), [=]() { 377 | 378 | try { 379 | callback(); 380 | } 381 | catch (sol::error e) { 382 | ERROR_FMTLOG("[BLOCK] LuaAdapter delayDay func err : {} traceback : {}", e.what(), Traceback(proxyPtr_->state_)); 383 | } 384 | catch (...) 385 | { 386 | ERROR_LOG("[BLOCK] LuaAdapter delayDay func unknown err"); 387 | } 388 | }); 389 | 390 | return _tid; 391 | } 392 | 393 | void block::modules::LuaAdapterModule::lrmvDelay(uint64_t timerID) 394 | { 395 | TIMER.remove(timerID); 396 | } -------------------------------------------------------------------------------- /core/appImpl.cpp: -------------------------------------------------------------------------------- 1 | #include "appImpl.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef WIN32 9 | #include 10 | #else 11 | #include 12 | #endif // WIN32 13 | 14 | #include "module.h" 15 | #include "dynamic_module_factory.h" 16 | 17 | block::AppImpl::AppImpl() 18 | : shutdown_(false) 19 | , module_idx_(2) 20 | , state_(AppState::BEFORE_INIT) 21 | , cur_frame_(0) 22 | {} 23 | 24 | std::string block::AppImpl::getName() const 25 | { 26 | return cfg_.name; 27 | } 28 | 29 | void block::AppImpl::initCfg(const block::AppConfig &cfg) 30 | { 31 | cfg_ = cfg; 32 | 33 | //logger_ = std::make_shared(); 34 | logger_.init(cfg_.name); 35 | //timer_ = std::make_shared(); 36 | 37 | //! 38 | new block::ArgsPool; 39 | block::ArgsPool::get_ref().make(cfg.pool_args_count); 40 | } 41 | 42 | block::ModuleID block::AppImpl::createDynamicModule(const std::string &moduleType) 43 | { 44 | if (module_name_map_.find(moduleType) != module_name_map_.end()) { 45 | logger_.WARN("[BLOCK] create dynamic module fail, module name : {} has been static module used!", moduleType); 46 | return 0; 47 | } 48 | 49 | block::Module *_module_ptr = static_cast(DynamicModuleFactory::create(moduleType)); 50 | _module_ptr->setID(uuid()); 51 | 52 | registModule(_module_ptr, true); 53 | 54 | pushFrame(cur_frame_ + 1, std::make_tuple(0, std::bind(&Module::before_init, _module_ptr), nullptr, nullptr, _module_ptr)); 55 | pushFrame(cur_frame_ + 2, std::make_tuple(1, nullptr, std::bind(&Module::init, _module_ptr), nullptr, _module_ptr)); 56 | // 将regist提前,因为脚本层的module在动态创建的时候需要存在于module_list之中,否则会导致事件的注册失败。 57 | //pushFrame(cur_frame_ + 3, std::make_tuple(2, nullptr, nullptr 58 | // , std::bind(&Application::registModule, this, std::placeholders::_1, std::placeholders::_2), _module_ptr)); 59 | pushFrame(cur_frame_ + 3, std::make_tuple(2, nullptr, nullptr, nullptr, _module_ptr)); 60 | 61 | return _module_ptr->getModuleID(); 62 | } 63 | 64 | void block::AppImpl::deleteModule(block::ModuleID moduleID) 65 | { 66 | auto itr = std::find_if(module_list_.begin(), module_list_.end(), [&](std::list::value_type it) { 67 | return (it->getModuleID() == moduleID); 68 | }); 69 | 70 | if (itr != module_list_.end()) { 71 | 72 | auto module_ptr = *itr; 73 | 74 | exit_list_.insert(std::make_pair(cur_frame_, std::make_pair(0, module_ptr))); // 在循环外处理清理逻辑 75 | exit_list_.insert(std::make_pair(cur_frame_ + 1, std::make_pair(1, module_ptr))); 76 | exit_list_.insert(std::make_pair(cur_frame_ + 2, std::make_pair(2, module_ptr))); 77 | exit_list_.insert(std::make_pair(cur_frame_ + 3, std::make_pair(3, module_ptr))); 78 | } 79 | else { 80 | logger_.WARN("[BLOCK] unregistModule can't find module {}", moduleID); 81 | } 82 | } 83 | 84 | block::ModuleID block::AppImpl::getModuleID(const std::string &moduleName) const 85 | { 86 | auto itr = module_name_map_.find(moduleName); 87 | if (itr != module_name_map_.end()) { 88 | return itr->second; 89 | } 90 | else { 91 | return block::ModuleNil; 92 | } 93 | } 94 | 95 | bool block::AppImpl::hasModule(block::ModuleID moduleid) 96 | { 97 | auto _find = std::find_if(module_list_.begin(), module_list_.end(), [&](std::list::value_type it) { 98 | return (it->getModuleID() == moduleid); 99 | }); 100 | 101 | if (_find != module_list_.end()){ 102 | return true; 103 | } 104 | 105 | return false; 106 | } 107 | 108 | const block::AppConfig & block::AppImpl::getAppCfg() 109 | { 110 | return cfg_; 111 | } 112 | 113 | int64_t block::AppImpl::uuid() 114 | { 115 | int64_t _uuid = 0; 116 | uint64_t _tick = getSystemTick() - start_time_; 117 | 118 | _uuid |= _tick << 22; 119 | _uuid |= cfg_.appid & 0x3FF << 12; 120 | 121 | _uuid |= sequence_++ & 0xFFF; 122 | if (sequence_ == 0x1000) { 123 | sequence_ = 0; 124 | } 125 | 126 | return _uuid; 127 | } 128 | 129 | void block::AppImpl::pushFrame(uint64_t index, Frame frame) 130 | { 131 | halfway_frame_.insert(std::make_pair(index, frame)); 132 | } 133 | 134 | void block::AppImpl::popFrame() 135 | { 136 | if (!halfway_frame_.empty()) { 137 | auto itr = halfway_frame_.find(cur_frame_); 138 | for (size_t i = 0; i < halfway_frame_.count(cur_frame_); ++i, ++itr) 139 | { 140 | int idx = std::get<0>(itr->second); 141 | if (idx == 0) { 142 | auto func = std::get<1>(itr->second); 143 | auto ptr = std::get<4>(itr->second); 144 | //func(); 145 | ptr->before_init(); 146 | } 147 | else if (idx == 1) { 148 | auto func = std::get<2>(itr->second); 149 | auto ptr = std::get<4>(itr->second); 150 | //func(); 151 | //if (ptr->getAvailable()) { 152 | ptr->mailboxPtr_->pull(); 153 | //} 154 | ptr->init(); 155 | } 156 | else if (idx == 2) { 157 | auto point = std::get<4>(itr->second); 158 | point->setAvailable(true); 159 | } 160 | } 161 | 162 | halfway_frame_.erase(cur_frame_); 163 | } 164 | 165 | if (!exit_list_.empty()) { 166 | 167 | auto itr = exit_list_.find(cur_frame_); 168 | for (size_t i = 0; i < exit_list_.count(cur_frame_); ++i, ++itr) 169 | { 170 | auto idx = itr->second.first; 171 | if (idx == 0) { 172 | 173 | auto _module_id = (itr->second.second)->getModuleID(); 174 | auto _module_name = (itr->second.second)->getModuleName(); 175 | auto litr = std::find_if(module_list_.begin(), module_list_.end(), [&](std::list::value_type it) { 176 | return (it->getModuleID() == _module_id); 177 | }); 178 | 179 | if (litr != module_list_.end()) { 180 | module_list_.erase(litr); 181 | 182 | auto _mitr = module_name_map_.find(_module_name); 183 | if (_mitr != module_name_map_.end()) { 184 | module_name_map_.erase(_mitr); 185 | } 186 | } 187 | else { 188 | logger_.WARN("[BLOCK] popFrame can't find module {}", _module_id); 189 | } 190 | } 191 | else if (idx == 1) { 192 | (itr->second.second)->shut(); 193 | } 194 | else if (idx == 2) { 195 | (itr->second.second)->after_shut(); 196 | } 197 | else { 198 | delete itr->second.second; 199 | itr->second.second = nullptr; 200 | } 201 | } 202 | 203 | exit_list_.erase(cur_frame_); 204 | } 205 | } 206 | 207 | void block::AppImpl::reactorRegist(block::ModuleID moduleID, block::EventID event) 208 | { 209 | auto _find = std::find_if(module_list_.begin(), module_list_.end(), [&](std::list::value_type it) { 210 | return (it->getModuleID() == moduleID); 211 | }); 212 | 213 | if (_find != module_list_.end()) { 214 | 215 | auto _repItr = mailboxMap_.find(std::make_pair(moduleID, event)); 216 | if (_repItr != mailboxMap_.end()) { 217 | logger_.WARN("[BLOCK]application regist event:{} repet, module:{}", event, (*_find)->getModuleName()); 218 | return; 219 | } 220 | 221 | mailboxMap_.insert(std::make_pair(std::make_pair(moduleID, event), (*_find)->mailboxPtr_)); 222 | 223 | } 224 | else { 225 | logger_.WARN("[BLOCK]application regist event:{} can't find module id:{}", event, moduleID); 226 | } 227 | } 228 | 229 | void block::AppImpl::reactorDispatch(block::ModuleID self, block::ModuleID target, block::EventID event, block::ArgsPtr args) 230 | { 231 | //! 找到目标mailbox 232 | auto _find = mailboxMap_.find(std::make_pair(target, event)); 233 | if (_find != mailboxMap_.end()) { 234 | 235 | auto taskPtr = new TaskInfo(); 236 | taskPtr->target_ = self; 237 | taskPtr->event_ = event; 238 | taskPtr->args_ = std::move(args); 239 | 240 | //! 将task加入到mailbox的FIFO队列 241 | _find->second->push(taskPtr); 242 | } 243 | else { 244 | logger_.WARN("[BLOCK] application dispatch, can't find event module:{}, event:{}", target, event); 245 | return; 246 | } 247 | } 248 | 249 | void block::AppImpl::reactorBoardcast(block::ModuleID self, block::EventID event, block::ArgsPtr args) 250 | { 251 | for (auto itr = mailboxMap_.begin(); itr != mailboxMap_.end(); ++itr) 252 | { 253 | if (itr->first.second == event) { 254 | 255 | auto taskPtr = new TaskInfo(); 256 | taskPtr->target_ = self; 257 | taskPtr->event_ = event; 258 | taskPtr->args_ = std::move(args); 259 | 260 | itr->second->push(taskPtr); 261 | } 262 | } 263 | } 264 | 265 | void block::AppImpl::run() 266 | { 267 | //! run 268 | while (!shutdown_) 269 | { 270 | using namespace std::chrono; 271 | 272 | auto _before = time_point_cast(system_clock::now()); 273 | auto _ttime = time_point_cast(system_clock::now()); 274 | 275 | #ifdef WATCH_PERF 276 | int64_t t1 = 0; 277 | #endif // WATCH_PERF 278 | 279 | auto _callback = [&](AppState state) { 280 | for (auto it : module_list_) 281 | { 282 | if (state == AppState::BEFORE_INIT) { 283 | it->before_init(); 284 | it->setAvailable(true); 285 | } 286 | else if (state == AppState::INIT) { 287 | if (it->getAvailable()) { 288 | it->mailboxPtr_->pull(); 289 | } 290 | 291 | it->init(); 292 | } 293 | else if (state == AppState::EXECUTE) { 294 | 295 | if (it->getAvailable()) { 296 | it->mailboxPtr_->pull(); 297 | it->execute(); 298 | } 299 | #ifdef WATCH_PERF 300 | t1 = (time_point_cast(system_clock::now()) - _ttime).count(); 301 | it->add_tick_consume(t1); 302 | _ttime = time_point_cast(system_clock::now()); 303 | #endif // WATCH_PERF 304 | } 305 | else if (state == AppState::SHUT) { 306 | 307 | if (it->getAvailable()) { 308 | it->mailboxPtr_->pull(); 309 | } 310 | 311 | it->shut(); 312 | 313 | it->setAvailable(false); 314 | } 315 | else if (state == AppState::AFTER_SHUT) { 316 | it->after_shut(); 317 | } 318 | else { 319 | // waht? 320 | } 321 | } 322 | 323 | //! 动态创建的module,要先执行前面的状态帧。 才能同步到application状态中! 324 | popFrame(); 325 | /* 326 | while (!unregist_list_.empty()) { 327 | auto itr = unregist_list_.front(); 328 | unregist_dynamic_module(itr); 329 | unregist_list_.pop_front(); 330 | } 331 | */ 332 | //static_cast(block::EventModule::get_ptr())->execute(); 333 | #ifdef WATCH_PERF 334 | //t1 = (time_point_cast(system_clock::now()) - _ttime).count(); 335 | //static_cast(block::EventModule::get_ptr())->add_tick_consume(t1); 336 | //_ttime = time_point_cast(system_clock::now()); 337 | #endif // WATCH_PERF 338 | }; 339 | 340 | timer_.exec(); 341 | 342 | _callback(state_); 343 | if (state_ == AppState::BEFORE_INIT) { 344 | state_ = AppState::INIT; 345 | } 346 | else if (state_ == AppState::INIT) { 347 | state_ = AppState::EXECUTE; 348 | } 349 | else if (state_ == AppState::EXECUTE) { 350 | 351 | } 352 | else if (state_ == AppState::SHUT) { 353 | state_ = AppState::AFTER_SHUT; 354 | } 355 | else if (state_ == AppState::AFTER_SHUT) { 356 | //exit(); 357 | } 358 | 359 | ++cur_frame_; 360 | tick(); 361 | block::ArgsPool::get_ref().reenter(); 362 | 363 | auto _use = time_point_cast(system_clock::now()) - _before; 364 | uint32_t _use_ms = static_cast(_use.count() / 1000); 365 | if (_use_ms < cfg_.tick_count) { 366 | #ifdef WIN32 367 | Sleep(cfg_.tick_count - _use_ms); 368 | #else 369 | usleep(1000 * (cfg_.tick_count - _use_ms)); 370 | #endif // WIN32 371 | } 372 | else { 373 | auto of = _use_ms - cfg_.tick_count; 374 | logger_.WARN("[BLOCK]application single frame processing time overflow : {}ms", of); 375 | } 376 | } 377 | } 378 | 379 | void block::AppImpl::exit() 380 | { 381 | 382 | } 383 | 384 | uint64_t block::AppImpl::getSystemTick() 385 | { 386 | return (uint64_t)std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); 387 | } 388 | 389 | void block::AppImpl::unregist_dynamic_module(block::ModuleID module_id) 390 | { 391 | auto itr = std::find_if(module_list_.begin(), module_list_.end(), [&](std::list::value_type it) { 392 | return (it->getModuleID() == module_id); 393 | }); 394 | 395 | if (itr != module_list_.end()) { 396 | 397 | (*itr)->shut(); 398 | (*itr)->after_shut(); 399 | 400 | //! 401 | 402 | module_list_.erase(itr); 403 | } 404 | } 405 | 406 | void block::AppImpl::tick() 407 | { 408 | /* 409 | if (cfg_.is_watch_pref){ 410 | int _t = (last_tick_ + 1) % tick_len_; 411 | 412 | if (_t == 0) { 413 | std::string _pref = "------------------- pref -------------------\n"; 414 | for (auto it : module_list_) 415 | { 416 | _pref += it->get_tick_info(tick_len_, cfg_.tick_count); 417 | } 418 | 419 | _pref += static_cast(block::EventModule::get_ptr())->get_tick_info(tick_len_, cfg_.tick_count) + "\n"; 420 | std::cout << _pref << block::ArgsPool::get_ref().get_perf(); 421 | } 422 | 423 | last_tick_ = _t; 424 | } 425 | */ 426 | } 427 | -------------------------------------------------------------------------------- /utils/protobuf.lua: -------------------------------------------------------------------------------- 1 | local c = require "protobuf.c" 2 | 3 | local setmetatable = setmetatable 4 | local type = type 5 | local table = table 6 | local assert = assert 7 | local pairs = pairs 8 | local ipairs = ipairs 9 | local string = string 10 | local print = print 11 | local io = io 12 | local tinsert = table.insert 13 | local rawget = rawget 14 | local rawset = rawset 15 | 16 | local M = {} 17 | 18 | local _pattern_cache = {} 19 | 20 | local P,GC 21 | 22 | P = debug.getregistry().PROTOBUF_ENV 23 | 24 | if P then 25 | GC = c._gc() 26 | else 27 | P= c._env_new() 28 | GC = c._gc(P) 29 | end 30 | 31 | M.GC = GC 32 | 33 | function M.lasterror() 34 | return c._last_error(P) 35 | end 36 | 37 | local decode_type_cache = {} 38 | local _R_meta = {} 39 | 40 | function _R_meta:__index(key) 41 | local v = decode_type_cache[self._CType][key](self, key) 42 | self[key] = v 43 | return v 44 | end 45 | 46 | local _reader = {} 47 | 48 | function _reader:real(key) 49 | return c._rmessage_real(self._CObj , key , 0) 50 | end 51 | 52 | function _reader:string(key) 53 | return c._rmessage_string(self._CObj , key , 0) 54 | end 55 | 56 | function _reader:bool(key) 57 | return c._rmessage_int(self._CObj , key , 0) ~= 0 58 | end 59 | 60 | function _reader:message(key, message_type) 61 | local rmessage = c._rmessage_message(self._CObj , key , 0) 62 | if rmessage then 63 | local v = { 64 | _CObj = rmessage, 65 | _CType = message_type, 66 | _Parent = self, 67 | } 68 | return setmetatable( v , _R_meta ) 69 | end 70 | end 71 | 72 | function _reader:int(key) 73 | return c._rmessage_int(self._CObj , key , 0) 74 | end 75 | 76 | function _reader:real_repeated(key) 77 | local cobj = self._CObj 78 | local n = c._rmessage_size(cobj , key) 79 | local ret = {} 80 | for i=0,n-1 do 81 | tinsert(ret, c._rmessage_real(cobj , key , i)) 82 | end 83 | return ret 84 | end 85 | 86 | function _reader:string_repeated(key) 87 | local cobj = self._CObj 88 | local n = c._rmessage_size(cobj , key) 89 | local ret = {} 90 | for i=0,n-1 do 91 | tinsert(ret, c._rmessage_string(cobj , key , i)) 92 | end 93 | return ret 94 | end 95 | 96 | function _reader:bool_repeated(key) 97 | local cobj = self._CObj 98 | local n = c._rmessage_size(cobj , key) 99 | local ret = {} 100 | for i=0,n-1 do 101 | tinsert(ret, c._rmessage_int(cobj , key , i) ~= 0) 102 | end 103 | return ret 104 | end 105 | 106 | function _reader:message_repeated(key, message_type) 107 | local cobj = self._CObj 108 | local n = c._rmessage_size(cobj , key) 109 | local ret = {} 110 | for i=0,n-1 do 111 | local m = { 112 | _CObj = c._rmessage_message(cobj , key , i), 113 | _CType = message_type, 114 | _Parent = self, 115 | } 116 | tinsert(ret, setmetatable( m , _R_meta )) 117 | end 118 | return ret 119 | end 120 | 121 | function _reader:int_repeated(key) 122 | local cobj = self._CObj 123 | local n = c._rmessage_size(cobj , key) 124 | local ret = {} 125 | for i=0,n-1 do 126 | tinsert(ret, c._rmessage_int(cobj , key , i)) 127 | end 128 | return ret 129 | end 130 | 131 | --[[ 132 | #define PBC_INT 1 133 | #define PBC_REAL 2 134 | #define PBC_BOOL 3 135 | #define PBC_ENUM 4 136 | #define PBC_STRING 5 137 | #define PBC_MESSAGE 6 138 | #define PBC_FIXED64 7 139 | #define PBC_FIXED32 8 140 | #define PBC_BYTES 9 141 | #define PBC_INT64 10 142 | #define PBC_UINT 11 143 | #define PBC_UNKNOWN 12 144 | #define PBC_REPEATED 128 145 | ]] 146 | 147 | _reader[1] = function(msg) return _reader.int end 148 | _reader[2] = function(msg) return _reader.real end 149 | _reader[3] = function(msg) return _reader.bool end 150 | _reader[4] = function(msg) return _reader.string end 151 | _reader[5] = function(msg) return _reader.string end 152 | _reader[6] = function(msg) 153 | local message = _reader.message 154 | return function(self,key) 155 | return message(self, key, msg) 156 | end 157 | end 158 | _reader[7] = _reader[1] 159 | _reader[8] = _reader[1] 160 | _reader[9] = _reader[5] 161 | _reader[10] = _reader[7] 162 | _reader[11] = _reader[7] 163 | 164 | _reader[128+1] = function(msg) return _reader.int_repeated end 165 | _reader[128+2] = function(msg) return _reader.real_repeated end 166 | _reader[128+3] = function(msg) return _reader.bool_repeated end 167 | _reader[128+4] = function(msg) return _reader.string_repeated end 168 | _reader[128+5] = function(msg) return _reader.string_repeated end 169 | _reader[128+6] = function(msg) 170 | local message = _reader.message_repeated 171 | return function(self,key) 172 | return message(self, key, msg) 173 | end 174 | end 175 | _reader[128+7] = _reader[128+1] 176 | _reader[128+8] = _reader[128+1] 177 | _reader[128+9] = _reader[128+5] 178 | _reader[128+10] = _reader[128+7] 179 | _reader[128+11] = _reader[128+7] 180 | 181 | local _decode_type_meta = {} 182 | 183 | function _decode_type_meta:__index(key) 184 | local t, msg = c._env_type(P, self._CType, key) 185 | local func = assert(_reader[t],key)(msg) 186 | self[key] = func 187 | return func 188 | end 189 | 190 | setmetatable(decode_type_cache , { 191 | __index = function(self, key) 192 | local v = setmetatable({ _CType = key } , _decode_type_meta) 193 | self[key] = v 194 | return v 195 | end 196 | }) 197 | 198 | local function decode_message( message , buffer, length) 199 | local rmessage = c._rmessage_new(P, message, buffer, length) 200 | if rmessage then 201 | local self = { 202 | _CObj = rmessage, 203 | _CType = message, 204 | } 205 | c._add_rmessage(GC,rmessage) 206 | return setmetatable( self , _R_meta ) 207 | end 208 | end 209 | 210 | ----------- encode ---------------- 211 | 212 | local encode_type_cache = {} 213 | 214 | local function encode_message(CObj, message_type, t) 215 | local type = encode_type_cache[message_type] 216 | for k,v in pairs(t) do 217 | local func = type[k] 218 | func(CObj, k , v) 219 | end 220 | end 221 | 222 | local _writer = { 223 | real = c._wmessage_real, 224 | enum = c._wmessage_string, 225 | string = c._wmessage_string, 226 | int = c._wmessage_int, 227 | } 228 | 229 | function _writer:bool(k,v) 230 | c._wmessage_int(self, k, v and 1 or 0) 231 | end 232 | 233 | function _writer:message(k, v , message_type) 234 | local submessage = c._wmessage_message(self, k) 235 | encode_message(submessage, message_type, v) 236 | end 237 | 238 | function _writer:real_repeated(k,v) 239 | for _,v in ipairs(v) do 240 | c._wmessage_real(self,k,v) 241 | end 242 | end 243 | 244 | function _writer:bool_repeated(k,v) 245 | for _,v in ipairs(v) do 246 | c._wmessage_int(self, k, v and 1 or 0) 247 | end 248 | end 249 | 250 | function _writer:string_repeated(k,v) 251 | for _,v in ipairs(v) do 252 | c._wmessage_string(self,k,v) 253 | end 254 | end 255 | 256 | function _writer:message_repeated(k,v, message_type) 257 | for _,v in ipairs(v) do 258 | local submessage = c._wmessage_message(self, k) 259 | encode_message(submessage, message_type, v) 260 | end 261 | end 262 | 263 | function _writer:int_repeated(k,v) 264 | for _,v in ipairs(v) do 265 | c._wmessage_int(self,k,v) 266 | end 267 | end 268 | 269 | _writer[1] = function(msg) return _writer.int end 270 | _writer[2] = function(msg) return _writer.real end 271 | _writer[3] = function(msg) return _writer.bool end 272 | _writer[4] = function(msg) return _writer.string end 273 | _writer[5] = function(msg) return _writer.string end 274 | _writer[6] = function(msg) 275 | local message = _writer.message 276 | return function(self,key , v) 277 | return message(self, key, v, msg) 278 | end 279 | end 280 | _writer[7] = _writer[1] 281 | _writer[8] = _writer[1] 282 | _writer[9] = _writer[5] 283 | _writer[10] = _writer[7] 284 | _writer[11] = _writer[7] 285 | 286 | _writer[128+1] = function(msg) return _writer.int_repeated end 287 | _writer[128+2] = function(msg) return _writer.real_repeated end 288 | _writer[128+3] = function(msg) return _writer.bool_repeated end 289 | _writer[128+4] = function(msg) return _writer.string_repeated end 290 | _writer[128+5] = function(msg) return _writer.string_repeated end 291 | _writer[128+6] = function(msg) 292 | local message = _writer.message_repeated 293 | return function(self,key, v) 294 | return message(self, key, v, msg) 295 | end 296 | end 297 | 298 | _writer[128+7] = _writer[128+1] 299 | _writer[128+8] = _writer[128+1] 300 | _writer[128+9] = _writer[128+5] 301 | _writer[128+10] = _writer[128+7] 302 | _writer[128+11] = _writer[128+7] 303 | 304 | local _encode_type_meta = {} 305 | 306 | function _encode_type_meta:__index(key) 307 | local t, msg = c._env_type(P, self._CType, key) 308 | local func = assert(_writer[t],key)(msg) 309 | self[key] = func 310 | return func 311 | end 312 | 313 | setmetatable(encode_type_cache , { 314 | __index = function(self, key) 315 | local v = setmetatable({ _CType = key } , _encode_type_meta) 316 | self[key] = v 317 | return v 318 | end 319 | }) 320 | 321 | function M.encode( message, t , func , ...) 322 | local encoder = c._wmessage_new(P, message) 323 | assert(encoder , message) 324 | encode_message(encoder, message, t) 325 | if func then 326 | local buffer, len = c._wmessage_buffer(encoder) 327 | local ret = func(buffer, len, ...) 328 | c._wmessage_delete(encoder) 329 | return ret 330 | else 331 | local s = c._wmessage_buffer_string(encoder) 332 | c._wmessage_delete(encoder) 333 | return s 334 | end 335 | end 336 | 337 | --------- unpack ---------- 338 | 339 | local _pattern_type = { 340 | [1] = {"%d","i"}, 341 | [2] = {"%F","r"}, 342 | [3] = {"%d","b"}, 343 | [5] = {"%s","s"}, 344 | [6] = {"%s","m"}, 345 | [7] = {"%D","d"}, 346 | [128+1] = {"%a","I"}, 347 | [128+2] = {"%a","R"}, 348 | [128+3] = {"%a","B"}, 349 | [128+5] = {"%a","S"}, 350 | [128+6] = {"%a","M"}, 351 | [128+7] = {"%a","D"}, 352 | } 353 | 354 | _pattern_type[4] = _pattern_type[1] 355 | _pattern_type[8] = _pattern_type[1] 356 | _pattern_type[9] = _pattern_type[5] 357 | _pattern_type[10] = _pattern_type[7] 358 | _pattern_type[11] = _pattern_type[7] 359 | _pattern_type[128+4] = _pattern_type[128+1] 360 | _pattern_type[128+8] = _pattern_type[128+1] 361 | _pattern_type[128+9] = _pattern_type[128+5] 362 | _pattern_type[128+10] = _pattern_type[128+7] 363 | _pattern_type[128+11] = _pattern_type[128+7] 364 | 365 | 366 | local function _pattern_create(pattern) 367 | local iter = string.gmatch(pattern,"[^ ]+") 368 | local message = iter() 369 | local cpat = {} 370 | local lua = {} 371 | for v in iter do 372 | local tidx = c._env_type(P, message, v) 373 | local t = _pattern_type[tidx] 374 | assert(t,tidx) 375 | tinsert(cpat,v .. " " .. t[1]) 376 | tinsert(lua,t[2]) 377 | end 378 | local cobj = c._pattern_new(P, message , "@" .. table.concat(cpat," ")) 379 | if cobj == nil then 380 | return 381 | end 382 | c._add_pattern(GC, cobj) 383 | local pat = { 384 | CObj = cobj, 385 | format = table.concat(lua), 386 | size = 0 387 | } 388 | pat.size = c._pattern_size(pat.format) 389 | 390 | return pat 391 | end 392 | 393 | setmetatable(_pattern_cache, { 394 | __index = function(t, key) 395 | local v = _pattern_create(key) 396 | t[key] = v 397 | return v 398 | end 399 | }) 400 | 401 | function M.unpack(pattern, buffer, length) 402 | local pat = _pattern_cache[pattern] 403 | return c._pattern_unpack(pat.CObj , pat.format, pat.size, buffer, length) 404 | end 405 | 406 | function M.pack(pattern, ...) 407 | local pat = _pattern_cache[pattern] 408 | return c._pattern_pack(pat.CObj, pat.format, pat.size , ...) 409 | end 410 | 411 | function M.check(typename , field) 412 | if field == nil then 413 | return c._env_type(P,typename) 414 | else 415 | return c._env_type(P,typename,field) ~=0 416 | end 417 | end 418 | 419 | -------------- 420 | 421 | local default_cache = {} 422 | 423 | -- todo : clear default_cache, v._CObj 424 | 425 | local function default_table(typename) 426 | local v = default_cache[typename] 427 | if v then 428 | return v 429 | end 430 | 431 | local default_inst = assert(decode_message(typename , "")) 432 | v = { 433 | __index = function(tb, key) 434 | local ret = default_inst[key] 435 | if 'table' ~= type(ret) then 436 | return ret 437 | end 438 | ret = setmetatable({}, { __index = ret }) 439 | rawset(tb, key, ret) 440 | return ret 441 | end 442 | } 443 | 444 | default_cache[typename] = v 445 | return v 446 | end 447 | 448 | local decode_message_mt = {} 449 | 450 | local function decode_message_cb(typename, buffer) 451 | return setmetatable ( { typename, buffer } , decode_message_mt) 452 | end 453 | 454 | function M.decode(typename, buffer, length) 455 | local ret = {} 456 | local ok = c._decode(P, decode_message_cb , ret , typename, buffer, length) 457 | if ok then 458 | return setmetatable(ret , default_table(typename)) 459 | else 460 | return false , c._last_error(P) 461 | end 462 | end 463 | 464 | local function expand(tbl) 465 | local typename = rawget(tbl , 1) 466 | local buffer = rawget(tbl , 2) 467 | tbl[1] , tbl[2] = nil , nil 468 | assert(c._decode(P, decode_message_cb , tbl , typename, buffer), typename) 469 | setmetatable(tbl , default_table(typename)) 470 | end 471 | 472 | function decode_message_mt.__index(tbl, key) 473 | expand(tbl) 474 | return tbl[key] 475 | end 476 | 477 | function decode_message_mt.__pairs(tbl) 478 | expand(tbl) 479 | return pairs(tbl) 480 | end 481 | 482 | local function set_default(typename, tbl) 483 | for k,v in pairs(tbl) do 484 | if type(v) == "table" then 485 | local t, msg = c._env_type(P, typename, k) 486 | if t == 6 then 487 | set_default(msg, v) 488 | elseif t == 128+6 then 489 | for _,v in ipairs(v) do 490 | set_default(msg, v) 491 | end 492 | end 493 | end 494 | end 495 | return setmetatable(tbl , default_table(typename)) 496 | end 497 | 498 | function M.register(buffer) 499 | c._env_register(P, buffer) 500 | end 501 | 502 | function M.register_file(filename) 503 | local f = assert(io.open(filename , "rb")) 504 | local buffer = f:read "*a" 505 | c._env_register(P, buffer) 506 | f:close() 507 | end 508 | 509 | function M.enum_id(enum_type, enum_name) 510 | return c._env_enum_id(P, enum_type, enum_name) 511 | end 512 | 513 | function M.extract(tbl) 514 | local typename = rawget(tbl , 1) 515 | local buffer = rawget(tbl , 2) 516 | if type(typename) == "string" and type(buffer) == "string" then 517 | if M.check(typename) then 518 | expand(tbl) 519 | end 520 | end 521 | 522 | for k, v in pairs(tbl) do 523 | if type(v) == "table" then 524 | M.extract(v) 525 | end 526 | end 527 | end 528 | 529 | M.default=set_default 530 | 531 | return M 532 | -------------------------------------------------------------------------------- /script/protobuf.lua: -------------------------------------------------------------------------------- 1 | local c = require "protobuf.c" 2 | 3 | local setmetatable = setmetatable 4 | local type = type 5 | local table = table 6 | local assert = assert 7 | local pairs = pairs 8 | local ipairs = ipairs 9 | local string = string 10 | local print = print 11 | local io = io 12 | local tinsert = table.insert 13 | local rawget = rawget 14 | local rawset = rawset 15 | 16 | local M = {} 17 | 18 | local _pattern_cache = {} 19 | 20 | local P,GC 21 | 22 | P = debug.getregistry().PROTOBUF_ENV 23 | 24 | if P then 25 | GC = c._gc() 26 | else 27 | P= c._env_new() 28 | GC = c._gc(P) 29 | end 30 | 31 | M.GC = GC 32 | 33 | function M.lasterror() 34 | return c._last_error(P) 35 | end 36 | 37 | local decode_type_cache = {} 38 | local _R_meta = {} 39 | 40 | function _R_meta:__index(key) 41 | local v = decode_type_cache[self._CType][key](self, key) 42 | self[key] = v 43 | return v 44 | end 45 | 46 | local _reader = {} 47 | 48 | function _reader:real(key) 49 | return c._rmessage_real(self._CObj , key , 0) 50 | end 51 | 52 | function _reader:string(key) 53 | return c._rmessage_string(self._CObj , key , 0) 54 | end 55 | 56 | function _reader:bool(key) 57 | return c._rmessage_int(self._CObj , key , 0) ~= 0 58 | end 59 | 60 | function _reader:message(key, message_type) 61 | local rmessage = c._rmessage_message(self._CObj , key , 0) 62 | if rmessage then 63 | local v = { 64 | _CObj = rmessage, 65 | _CType = message_type, 66 | _Parent = self, 67 | } 68 | return setmetatable( v , _R_meta ) 69 | end 70 | end 71 | 72 | function _reader:int(key) 73 | return c._rmessage_int(self._CObj , key , 0) 74 | end 75 | 76 | function _reader:real_repeated(key) 77 | local cobj = self._CObj 78 | local n = c._rmessage_size(cobj , key) 79 | local ret = {} 80 | for i=0,n-1 do 81 | tinsert(ret, c._rmessage_real(cobj , key , i)) 82 | end 83 | return ret 84 | end 85 | 86 | function _reader:string_repeated(key) 87 | local cobj = self._CObj 88 | local n = c._rmessage_size(cobj , key) 89 | local ret = {} 90 | for i=0,n-1 do 91 | tinsert(ret, c._rmessage_string(cobj , key , i)) 92 | end 93 | return ret 94 | end 95 | 96 | function _reader:bool_repeated(key) 97 | local cobj = self._CObj 98 | local n = c._rmessage_size(cobj , key) 99 | local ret = {} 100 | for i=0,n-1 do 101 | tinsert(ret, c._rmessage_int(cobj , key , i) ~= 0) 102 | end 103 | return ret 104 | end 105 | 106 | function _reader:message_repeated(key, message_type) 107 | local cobj = self._CObj 108 | local n = c._rmessage_size(cobj , key) 109 | local ret = {} 110 | for i=0,n-1 do 111 | local m = { 112 | _CObj = c._rmessage_message(cobj , key , i), 113 | _CType = message_type, 114 | _Parent = self, 115 | } 116 | tinsert(ret, setmetatable( m , _R_meta )) 117 | end 118 | return ret 119 | end 120 | 121 | function _reader:int_repeated(key) 122 | local cobj = self._CObj 123 | local n = c._rmessage_size(cobj , key) 124 | local ret = {} 125 | for i=0,n-1 do 126 | tinsert(ret, c._rmessage_int(cobj , key , i)) 127 | end 128 | return ret 129 | end 130 | 131 | --[[ 132 | #define PBC_INT 1 133 | #define PBC_REAL 2 134 | #define PBC_BOOL 3 135 | #define PBC_ENUM 4 136 | #define PBC_STRING 5 137 | #define PBC_MESSAGE 6 138 | #define PBC_FIXED64 7 139 | #define PBC_FIXED32 8 140 | #define PBC_BYTES 9 141 | #define PBC_INT64 10 142 | #define PBC_UINT 11 143 | #define PBC_UNKNOWN 12 144 | #define PBC_REPEATED 128 145 | ]] 146 | 147 | _reader[1] = function(msg) return _reader.int end 148 | _reader[2] = function(msg) return _reader.real end 149 | _reader[3] = function(msg) return _reader.bool end 150 | _reader[4] = function(msg) return _reader.string end 151 | _reader[5] = function(msg) return _reader.string end 152 | _reader[6] = function(msg) 153 | local message = _reader.message 154 | return function(self,key) 155 | return message(self, key, msg) 156 | end 157 | end 158 | _reader[7] = _reader[1] 159 | _reader[8] = _reader[1] 160 | _reader[9] = _reader[5] 161 | _reader[10] = _reader[7] 162 | _reader[11] = _reader[7] 163 | 164 | _reader[128+1] = function(msg) return _reader.int_repeated end 165 | _reader[128+2] = function(msg) return _reader.real_repeated end 166 | _reader[128+3] = function(msg) return _reader.bool_repeated end 167 | _reader[128+4] = function(msg) return _reader.string_repeated end 168 | _reader[128+5] = function(msg) return _reader.string_repeated end 169 | _reader[128+6] = function(msg) 170 | local message = _reader.message_repeated 171 | return function(self,key) 172 | return message(self, key, msg) 173 | end 174 | end 175 | _reader[128+7] = _reader[128+1] 176 | _reader[128+8] = _reader[128+1] 177 | _reader[128+9] = _reader[128+5] 178 | _reader[128+10] = _reader[128+7] 179 | _reader[128+11] = _reader[128+7] 180 | 181 | local _decode_type_meta = {} 182 | 183 | function _decode_type_meta:__index(key) 184 | local t, msg = c._env_type(P, self._CType, key) 185 | local func = assert(_reader[t],key)(msg) 186 | self[key] = func 187 | return func 188 | end 189 | 190 | setmetatable(decode_type_cache , { 191 | __index = function(self, key) 192 | local v = setmetatable({ _CType = key } , _decode_type_meta) 193 | self[key] = v 194 | return v 195 | end 196 | }) 197 | 198 | local function decode_message( message , buffer, length) 199 | local rmessage = c._rmessage_new(P, message, buffer, length) 200 | if rmessage then 201 | local self = { 202 | _CObj = rmessage, 203 | _CType = message, 204 | } 205 | c._add_rmessage(GC,rmessage) 206 | return setmetatable( self , _R_meta ) 207 | end 208 | end 209 | 210 | ----------- encode ---------------- 211 | 212 | local encode_type_cache = {} 213 | 214 | local function encode_message(CObj, message_type, t) 215 | local type = encode_type_cache[message_type] 216 | for k,v in pairs(t) do 217 | local func = type[k] 218 | func(CObj, k , v) 219 | end 220 | end 221 | 222 | local _writer = { 223 | real = c._wmessage_real, 224 | enum = c._wmessage_string, 225 | string = c._wmessage_string, 226 | int = c._wmessage_int, 227 | } 228 | 229 | function _writer:bool(k,v) 230 | c._wmessage_int(self, k, v and 1 or 0) 231 | end 232 | 233 | function _writer:message(k, v , message_type) 234 | local submessage = c._wmessage_message(self, k) 235 | encode_message(submessage, message_type, v) 236 | end 237 | 238 | function _writer:real_repeated(k,v) 239 | for _,v in ipairs(v) do 240 | c._wmessage_real(self,k,v) 241 | end 242 | end 243 | 244 | function _writer:bool_repeated(k,v) 245 | for _,v in ipairs(v) do 246 | c._wmessage_int(self, k, v and 1 or 0) 247 | end 248 | end 249 | 250 | function _writer:string_repeated(k,v) 251 | for _,v in ipairs(v) do 252 | c._wmessage_string(self,k,v) 253 | end 254 | end 255 | 256 | function _writer:message_repeated(k,v, message_type) 257 | for _,v in ipairs(v) do 258 | local submessage = c._wmessage_message(self, k) 259 | encode_message(submessage, message_type, v) 260 | end 261 | end 262 | 263 | function _writer:int_repeated(k,v) 264 | for _,v in ipairs(v) do 265 | c._wmessage_int(self,k,v) 266 | end 267 | end 268 | 269 | _writer[1] = function(msg) return _writer.int end 270 | _writer[2] = function(msg) return _writer.real end 271 | _writer[3] = function(msg) return _writer.bool end 272 | _writer[4] = function(msg) return _writer.string end 273 | _writer[5] = function(msg) return _writer.string end 274 | _writer[6] = function(msg) 275 | local message = _writer.message 276 | return function(self,key , v) 277 | return message(self, key, v, msg) 278 | end 279 | end 280 | _writer[7] = _writer[1] 281 | _writer[8] = _writer[1] 282 | _writer[9] = _writer[5] 283 | _writer[10] = _writer[7] 284 | _writer[11] = _writer[7] 285 | 286 | _writer[128+1] = function(msg) return _writer.int_repeated end 287 | _writer[128+2] = function(msg) return _writer.real_repeated end 288 | _writer[128+3] = function(msg) return _writer.bool_repeated end 289 | _writer[128+4] = function(msg) return _writer.string_repeated end 290 | _writer[128+5] = function(msg) return _writer.string_repeated end 291 | _writer[128+6] = function(msg) 292 | local message = _writer.message_repeated 293 | return function(self,key, v) 294 | return message(self, key, v, msg) 295 | end 296 | end 297 | 298 | _writer[128+7] = _writer[128+1] 299 | _writer[128+8] = _writer[128+1] 300 | _writer[128+9] = _writer[128+5] 301 | _writer[128+10] = _writer[128+7] 302 | _writer[128+11] = _writer[128+7] 303 | 304 | local _encode_type_meta = {} 305 | 306 | function _encode_type_meta:__index(key) 307 | local t, msg = c._env_type(P, self._CType, key) 308 | local func = assert(_writer[t],key)(msg) 309 | self[key] = func 310 | return func 311 | end 312 | 313 | setmetatable(encode_type_cache , { 314 | __index = function(self, key) 315 | local v = setmetatable({ _CType = key } , _encode_type_meta) 316 | self[key] = v 317 | return v 318 | end 319 | }) 320 | 321 | function M.encode( message, t , func , ...) 322 | local encoder = c._wmessage_new(P, message) 323 | assert(encoder , message) 324 | encode_message(encoder, message, t) 325 | if func then 326 | local buffer, len = c._wmessage_buffer(encoder) 327 | local ret = func(buffer, len, ...) 328 | c._wmessage_delete(encoder) 329 | return ret 330 | else 331 | local s = c._wmessage_buffer_string(encoder) 332 | c._wmessage_delete(encoder) 333 | return s 334 | end 335 | end 336 | 337 | --------- unpack ---------- 338 | 339 | local _pattern_type = { 340 | [1] = {"%d","i"}, 341 | [2] = {"%F","r"}, 342 | [3] = {"%d","b"}, 343 | [5] = {"%s","s"}, 344 | [6] = {"%s","m"}, 345 | [7] = {"%D","d"}, 346 | [128+1] = {"%a","I"}, 347 | [128+2] = {"%a","R"}, 348 | [128+3] = {"%a","B"}, 349 | [128+5] = {"%a","S"}, 350 | [128+6] = {"%a","M"}, 351 | [128+7] = {"%a","D"}, 352 | } 353 | 354 | _pattern_type[4] = _pattern_type[1] 355 | _pattern_type[8] = _pattern_type[1] 356 | _pattern_type[9] = _pattern_type[5] 357 | _pattern_type[10] = _pattern_type[7] 358 | _pattern_type[11] = _pattern_type[7] 359 | _pattern_type[128+4] = _pattern_type[128+1] 360 | _pattern_type[128+8] = _pattern_type[128+1] 361 | _pattern_type[128+9] = _pattern_type[128+5] 362 | _pattern_type[128+10] = _pattern_type[128+7] 363 | _pattern_type[128+11] = _pattern_type[128+7] 364 | 365 | 366 | local function _pattern_create(pattern) 367 | local iter = string.gmatch(pattern,"[^ ]+") 368 | local message = iter() 369 | local cpat = {} 370 | local lua = {} 371 | for v in iter do 372 | local tidx = c._env_type(P, message, v) 373 | local t = _pattern_type[tidx] 374 | assert(t,tidx) 375 | tinsert(cpat,v .. " " .. t[1]) 376 | tinsert(lua,t[2]) 377 | end 378 | local cobj = c._pattern_new(P, message , "@" .. table.concat(cpat," ")) 379 | if cobj == nil then 380 | return 381 | end 382 | c._add_pattern(GC, cobj) 383 | local pat = { 384 | CObj = cobj, 385 | format = table.concat(lua), 386 | size = 0 387 | } 388 | pat.size = c._pattern_size(pat.format) 389 | 390 | return pat 391 | end 392 | 393 | setmetatable(_pattern_cache, { 394 | __index = function(t, key) 395 | local v = _pattern_create(key) 396 | t[key] = v 397 | return v 398 | end 399 | }) 400 | 401 | function M.unpack(pattern, buffer, length) 402 | local pat = _pattern_cache[pattern] 403 | return c._pattern_unpack(pat.CObj , pat.format, pat.size, buffer, length) 404 | end 405 | 406 | function M.pack(pattern, ...) 407 | local pat = _pattern_cache[pattern] 408 | return c._pattern_pack(pat.CObj, pat.format, pat.size , ...) 409 | end 410 | 411 | function M.check(typename , field) 412 | if field == nil then 413 | return c._env_type(P,typename) 414 | else 415 | return c._env_type(P,typename,field) ~=0 416 | end 417 | end 418 | 419 | -------------- 420 | 421 | local default_cache = {} 422 | 423 | -- todo : clear default_cache, v._CObj 424 | 425 | local function default_table(typename) 426 | local v = default_cache[typename] 427 | if v then 428 | return v 429 | end 430 | 431 | local default_inst = assert(decode_message(typename , "")) 432 | v = { 433 | __index = function(tb, key) 434 | local ret = default_inst[key] 435 | if 'table' ~= type(ret) then 436 | return ret 437 | end 438 | ret = setmetatable({}, { __index = ret }) 439 | rawset(tb, key, ret) 440 | return ret 441 | end 442 | } 443 | 444 | default_cache[typename] = v 445 | return v 446 | end 447 | 448 | local decode_message_mt = {} 449 | 450 | local function decode_message_cb(typename, buffer) 451 | return setmetatable ( { typename, buffer } , decode_message_mt) 452 | end 453 | 454 | function M.decode(typename, buffer, length) 455 | local ret = {} 456 | local ok = c._decode(P, decode_message_cb , ret , typename, buffer, length) 457 | if ok then 458 | return setmetatable(ret , default_table(typename)) 459 | else 460 | return false , c._last_error(P) 461 | end 462 | end 463 | 464 | local function expand(tbl) 465 | local typename = rawget(tbl , 1) 466 | local buffer = rawget(tbl , 2) 467 | tbl[1] , tbl[2] = nil , nil 468 | assert(c._decode(P, decode_message_cb , tbl , typename, buffer), typename) 469 | setmetatable(tbl , default_table(typename)) 470 | end 471 | 472 | function decode_message_mt.__index(tbl, key) 473 | expand(tbl) 474 | return tbl[key] 475 | end 476 | 477 | function decode_message_mt.__pairs(tbl) 478 | expand(tbl) 479 | return pairs(tbl) 480 | end 481 | 482 | local function set_default(typename, tbl) 483 | for k,v in pairs(tbl) do 484 | if type(v) == "table" then 485 | local t, msg = c._env_type(P, typename, k) 486 | if t == 6 then 487 | set_default(msg, v) 488 | elseif t == 128+6 then 489 | for _,v in ipairs(v) do 490 | set_default(msg, v) 491 | end 492 | end 493 | end 494 | end 495 | return setmetatable(tbl , default_table(typename)) 496 | end 497 | 498 | function M.register(buffer) 499 | c._env_register(P, buffer) 500 | end 501 | 502 | function M.register_file(filename) 503 | local f = assert(io.open(filename , "rb")) 504 | local buffer = f:read "*a" 505 | c._env_register(P, buffer) 506 | f:close() 507 | end 508 | 509 | function M.enum_id(enum_type, enum_name) 510 | return c._env_enum_id(P, enum_type, enum_name) 511 | end 512 | 513 | function M.extract(tbl) 514 | local typename = rawget(tbl , 1) 515 | local buffer = rawget(tbl , 2) 516 | if type(typename) == "string" and type(buffer) == "string" then 517 | if M.check(typename) then 518 | expand(tbl) 519 | end 520 | end 521 | 522 | for k, v in pairs(tbl) do 523 | if type(v) == "table" then 524 | M.extract(v) 525 | end 526 | end 527 | end 528 | 529 | M.default=set_default 530 | 531 | return M 532 | -------------------------------------------------------------------------------- /core/args.cpp: -------------------------------------------------------------------------------- 1 | #include "args.h" 2 | #include 3 | 4 | 5 | block::Args::Args() 6 | : bytes_(new Bytes()) 7 | { 8 | write_ = read_ = bytes_->buff_; 9 | tail_ = bytes_->buff_ + bytes_->total_; 10 | } 11 | 12 | block::Args::Args(const char *buf, size_t len) 13 | : bytes_(new Bytes(buf, len)) 14 | { 15 | write_ = read_ = bytes_->buff_; 16 | tail_ = bytes_->buff_ + bytes_->total_; 17 | } 18 | 19 | block::Args::~Args() 20 | { 21 | params_ = 0; 22 | write_ = read_ = nullptr; 23 | tail_ = nullptr; 24 | } 25 | 26 | void block::Args::flush() 27 | { 28 | bytes_->flush(); 29 | 30 | write_ = read_ = bytes_->buff_; 31 | tail_ = bytes_->buff_ + bytes_->total_; 32 | 33 | params_ = 0; 34 | } 35 | 36 | void block::Args::inc(size_t len) 37 | { 38 | if (bytes_->inc(len)) { 39 | write_ = bytes_->buff_ + bytes_->size_ - len; 40 | read_ = bytes_->buff_; 41 | tail_ = bytes_->buff_ + bytes_->total_; 42 | } 43 | } 44 | 45 | ////////////////////////////////////////////////////////////////////////// 46 | template 47 | void block::Args::push_impl(const T &val) 48 | { 49 | size_t _size = sizeof(T); 50 | 51 | inc(_size); 52 | 53 | *reinterpret_cast(write_) = val; 54 | write_ += _size; 55 | } 56 | 57 | /* 58 | void block::Args::push_block(const char *block, int len) 59 | { 60 | inc(len + 1 + 1); 61 | 62 | push_impl(at_block); 63 | TypeLen _len = static_cast(len); 64 | 65 | memcpy(write_, block, len); 66 | write_ += len; 67 | 68 | params_++; 69 | } 70 | */ 71 | 72 | void block::Args::push(const uint8_t &val) 73 | { 74 | push_impl(at_uint8); 75 | push_impl(val); 76 | params_++; 77 | } 78 | 79 | void block::Args::push_ui16(const uint16_t &val) 80 | { 81 | push_impl(at_uint16); 82 | push_impl(val); 83 | params_++; 84 | } 85 | 86 | void block::Args::push_ui32(const uint32_t &val) 87 | { 88 | push_impl(at_uint32); 89 | push_impl(val); 90 | params_++; 91 | } 92 | 93 | void block::Args::push_i32(const int32_t &val) 94 | { 95 | push_impl(at_int32); 96 | push_impl(val); 97 | params_++; 98 | } 99 | 100 | void block::Args::push_i64(const int64_t &val) 101 | { 102 | push_impl(at_int64); 103 | push_impl(val); 104 | params_++; 105 | } 106 | 107 | void block::Args::push_float(const float &val) 108 | { 109 | push_impl(at_float); 110 | push_impl(val); 111 | params_++; 112 | } 113 | 114 | void block::Args::push_double(const double &val) 115 | { 116 | push_impl(at_double); 117 | push_impl(val); 118 | params_++; 119 | } 120 | 121 | void block::Args::push_string(const std::string &val) 122 | { 123 | push(val.c_str(), val.length()); 124 | } 125 | 126 | void block::Args::push_bool(const bool &val) 127 | { 128 | push(val); 129 | } 130 | 131 | void block::Args::push(const int8_t &val) 132 | { 133 | push_impl(at_int8); 134 | push_impl(val); 135 | params_++; 136 | } 137 | 138 | void block::Args::push(const uint16_t &val) 139 | { 140 | push_impl(at_uint16); 141 | push_impl(val); 142 | params_++; 143 | } 144 | 145 | void block::Args::push(const int16_t &val) 146 | { 147 | push_impl(at_int16); 148 | push_impl(val); 149 | params_++; 150 | } 151 | 152 | void block::Args::push(const uint32_t &val) 153 | { 154 | push_impl(at_uint32); 155 | push_impl(val); 156 | params_++; 157 | } 158 | 159 | void block::Args::push(const int32_t & val) 160 | { 161 | push_impl(at_int32); 162 | push_impl(val); 163 | params_++; 164 | } 165 | 166 | void block::Args::push(const uint64_t &val) 167 | { 168 | push_impl(at_uint64); 169 | push_impl(val); 170 | params_++; 171 | } 172 | 173 | void block::Args::push(const int64_t &val) 174 | { 175 | push_impl(at_int64); 176 | push_impl(val); 177 | params_++; 178 | } 179 | 180 | void block::Args::push(const bool &val) 181 | { 182 | push_impl(at_bool); 183 | push_impl(val); 184 | params_++; 185 | } 186 | 187 | void block::Args::push(const float &val) 188 | { 189 | push_impl(at_float); 190 | push_impl(val); 191 | params_++; 192 | } 193 | 194 | void block::Args::push(const double &val) 195 | { 196 | push_impl(at_double); 197 | push_impl(val); 198 | params_++; 199 | } 200 | 201 | void block::Args::push(const std::string &val) 202 | { 203 | push(val.c_str(), val.length()); 204 | } 205 | 206 | template 207 | void block::Args::push(std::list &list) 208 | { 209 | push_impl(at_list); 210 | TypeLen _len = static_cast(list.size()); 211 | push_impl(_len); 212 | 213 | for (auto &it : list) 214 | { 215 | push_impl(it); 216 | } 217 | params_++; 218 | } 219 | 220 | template 221 | void block::Args::push(std::vector &vec) 222 | { 223 | push_impl(at_vec); 224 | TypeLen _len = static_cast(vec.size()); 225 | push_impl(_len); 226 | 227 | for (auto &it : vec) 228 | { 229 | push_impl(it); 230 | } 231 | params_++; 232 | } 233 | 234 | template 235 | void block::Args::push(std::map &map) 236 | { 237 | push_impl(at_map); 238 | TypeLen _len = static_cast(map.size()); 239 | push_impl(_len); 240 | 241 | for (auto &it : map) 242 | { 243 | push_impl(it.first); 244 | push_impl(it.second); 245 | } 246 | params_++; 247 | } 248 | 249 | void block::Args::push(const char * val, size_t len) 250 | { 251 | push_impl(at_string); 252 | TypeLen _len = static_cast(len); 253 | 254 | push_impl(_len); 255 | 256 | inc(_len); 257 | memcpy(write_, val, _len); 258 | write_ += _len; 259 | 260 | params_++; 261 | } 262 | ////////////////////////////////////////////////////////////////////////// 263 | 264 | uint8_t block::Args::pop_tag() 265 | { 266 | auto _ui8 = *reinterpret_cast(read_); 267 | read_ += sizeof(uint8_t); 268 | offset_ += sizeof(uint8_t); 269 | 270 | return _ui8; 271 | } 272 | 273 | uint8_t block::Args::pop_ui8() 274 | { 275 | assert(pop_tag() == at_uint8); 276 | 277 | auto _ui8 = *reinterpret_cast(read_); 278 | read_ += sizeof(uint8_t); 279 | offset_ += sizeof(uint8_t); 280 | 281 | params_--; 282 | 283 | return _ui8; 284 | } 285 | 286 | int8_t block::Args::pop_i8() 287 | { 288 | assert(pop_tag() == at_int8); 289 | 290 | auto _val = *reinterpret_cast(read_); 291 | read_ += sizeof(int8_t); 292 | offset_ += sizeof(int8_t); 293 | 294 | params_--; 295 | 296 | return _val; 297 | } 298 | 299 | uint16_t block::Args::pop_ui16() 300 | { 301 | assert(pop_tag() == at_uint16); 302 | 303 | auto _val = *reinterpret_cast(read_); 304 | read_ += sizeof(uint16_t); 305 | offset_ += sizeof(uint16_t); 306 | 307 | params_--; 308 | 309 | return _val; 310 | } 311 | 312 | int16_t block::Args::pop_i16() 313 | { 314 | assert(pop_tag() == at_int16); 315 | 316 | auto _val = *reinterpret_cast(read_); 317 | read_ += sizeof(int16_t); 318 | offset_ += sizeof(int16_t); 319 | 320 | params_--; 321 | 322 | return _val; 323 | } 324 | 325 | int32_t block::Args::pop_i32() 326 | { 327 | assert(pop_tag() == at_int32); 328 | 329 | auto _i32 = *reinterpret_cast(read_); 330 | read_ += sizeof(int32_t); 331 | offset_ += sizeof(int32_t); 332 | 333 | params_--; 334 | 335 | return _i32; 336 | } 337 | 338 | uint64_t block::Args::pop_ui64() 339 | { 340 | assert(pop_tag() == at_uint64); 341 | 342 | auto _val = *reinterpret_cast(read_); 343 | read_ += sizeof(uint64_t); 344 | offset_ += sizeof(uint64_t); 345 | 346 | params_--; 347 | 348 | return _val; 349 | } 350 | 351 | int64_t block::Args::pop_i64() 352 | { 353 | assert(pop_tag() == at_int64); 354 | 355 | auto _val = *reinterpret_cast(read_); 356 | read_ += sizeof(int64_t); 357 | offset_ += sizeof(int64_t); 358 | 359 | params_--; 360 | 361 | return _val; 362 | } 363 | 364 | bool block::Args::pop_bool() 365 | { 366 | assert(pop_tag() == at_bool); 367 | 368 | auto _val = *reinterpret_cast(read_); 369 | read_ += sizeof(bool); 370 | offset_ += sizeof(bool); 371 | 372 | params_--; 373 | 374 | return _val; 375 | } 376 | 377 | float block::Args::pop_float() 378 | { 379 | assert(pop_tag() == at_float); 380 | 381 | auto _val = *reinterpret_cast(read_); 382 | read_ += sizeof(float); 383 | offset_ += sizeof(float); 384 | 385 | params_--; 386 | 387 | return _val; 388 | } 389 | 390 | double block::Args::pop_double() 391 | { 392 | assert(pop_tag() == at_double); 393 | 394 | auto _val = *reinterpret_cast(read_); 395 | read_ += sizeof(double); 396 | offset_ += sizeof(double); 397 | 398 | params_--; 399 | 400 | return _val; 401 | } 402 | 403 | uint32_t block::Args::pop_ui32() 404 | { 405 | assert(pop_tag() == at_uint32); 406 | 407 | auto _ui32 = *reinterpret_cast(read_); 408 | read_ += sizeof(uint32_t); 409 | offset_ += sizeof(uint32_t); 410 | 411 | params_--; 412 | 413 | return _ui32; 414 | } 415 | 416 | template 417 | void block::Args::pop(T &val) 418 | { 419 | pop_impl(val); 420 | } 421 | 422 | void block::Args::pop_impl(uint8_t &val) 423 | { 424 | val = pop_ui8(); 425 | } 426 | 427 | void block::Args::pop_impl(int8_t &val) 428 | { 429 | val = pop_i8(); 430 | } 431 | 432 | void block::Args::pop_impl(uint16_t &val) 433 | { 434 | val = pop_ui16(); 435 | } 436 | 437 | void block::Args::pop_impl(int16_t &val) 438 | { 439 | val = pop_i16(); 440 | } 441 | 442 | void block::Args::pop_impl(uint32_t &val) 443 | { 444 | val = pop_ui32(); 445 | } 446 | 447 | void block::Args::pop_impl(int32_t &val) 448 | { 449 | val = pop_i32(); 450 | } 451 | 452 | void block::Args::pop_impl(uint64_t &val) 453 | { 454 | val = pop_ui64(); 455 | } 456 | 457 | void block::Args::pop_impl(int64_t &val) 458 | { 459 | val = pop_i64(); 460 | } 461 | 462 | void block::Args::pop_impl(bool &val) 463 | { 464 | val = pop_bool(); 465 | } 466 | 467 | void block::Args::pop_impl(float &val) 468 | { 469 | val = pop_float(); 470 | } 471 | 472 | void block::Args::pop_impl(double &val) 473 | { 474 | val = pop_double(); 475 | } 476 | 477 | block::Args::TypeLen block::Args::pop_typelen() 478 | { 479 | TypeLen _len = *reinterpret_cast(read_); 480 | read_ += sizeof(TypeLen); 481 | offset_ += sizeof(TypeLen); 482 | return _len; 483 | } 484 | 485 | block::SessionID block::Args::pop_fd() 486 | { 487 | return pop_ui16(); 488 | } 489 | 490 | block::MsgID block::Args::pop_msgid() 491 | { 492 | return pop_i32(); 493 | } 494 | 495 | block::ModuleID block::Args::pop_moduleid() 496 | { 497 | return pop_i64(); 498 | } 499 | 500 | block::TimerID block::Args::pop_timerid() 501 | { 502 | return pop_ui64(); 503 | } 504 | 505 | std::string block::Args::pop_string() 506 | { 507 | assert(pop_tag() == at_string); 508 | 509 | TypeLen _len = pop_typelen(); 510 | 511 | std::string _str; 512 | _str.assign(read_, _len); 513 | read_ += _len; 514 | offset_ += _len; 515 | 516 | return _str; 517 | } 518 | 519 | template 520 | std::list block::Args::pop_list() 521 | { 522 | assert(pop_tag() == at_list); 523 | 524 | TypeLen _len = pop_typelen(); 525 | 526 | std::list _list; 527 | for (TypeLen i = 0; i < _len; ++i) 528 | { 529 | T _t; 530 | pop(_t); 531 | _list.push_back(_t); 532 | } 533 | 534 | return _list; 535 | } 536 | 537 | template 538 | std::vector block::Args::pop_vec() 539 | { 540 | assert(pop_tag() == at_vec); 541 | 542 | TypeLen _len = pop_typelen(); 543 | 544 | std::vector _vec; 545 | for (TypeLen i = 0; i < _len; ++i) 546 | { 547 | T _t; 548 | pop(_t); 549 | _vec.push_back(_t); 550 | } 551 | 552 | return _vec; 553 | } 554 | 555 | template 556 | std::map block::Args::pop_map() 557 | { 558 | assert(pop_tag() == at_map); 559 | 560 | TypeLen _len = pop_typelen(); 561 | 562 | std::map _map; 563 | for (TypeLen i = 0; i < _len; ++i) 564 | { 565 | Key _k; 566 | Value _v; 567 | pop(_k); 568 | pop(_v); 569 | 570 | _map.insert(std::make_pair(_k, _v)); 571 | } 572 | 573 | return _map; 574 | } 575 | 576 | /* 577 | std::string block::Args::pop_block() 578 | { 579 | assert(pop_tag() == at_block); 580 | 581 | TypeLen _len = pop_typelen(); 582 | 583 | std::string _str; 584 | _str.append(read_, _len); 585 | 586 | read_ += _len; 587 | offset_ += _len; 588 | 589 | return _str; 590 | } 591 | */ 592 | 593 | ////////////////////////////////////////////////////////////////////////// 594 | uint8_t block::Args::peek_tag() 595 | { 596 | auto _tag = *reinterpret_cast(read_); 597 | read_ += sizeof(uint8_t); 598 | return _tag; 599 | } 600 | 601 | void * block::Args::peek(uint8_t type) 602 | { 603 | assert(type == peek_tag()); 604 | 605 | void * sp = nullptr; 606 | sp = (void*)read_; 607 | 608 | if (type == at_int8) { 609 | read_ += sizeof(int8_t); 610 | } 611 | if (type == at_uint8) { 612 | read_ += sizeof(uint8_t); 613 | } 614 | if (type == at_int16) { 615 | read_ += sizeof(int16_t); 616 | } 617 | if (type == at_uint16) { 618 | read_ += sizeof(uint16_t); 619 | } 620 | if (type == at_int32) { 621 | read_ += sizeof(int32_t); 622 | } 623 | if (type == at_uint32) { 624 | read_ += sizeof(uint32_t); 625 | } 626 | if (type == at_int64) { 627 | read_ += sizeof(int64_t); 628 | } 629 | if (type == at_uint64) { 630 | read_ += sizeof(uint64_t); 631 | } 632 | if (type == at_float) { 633 | read_ += sizeof(float); 634 | } 635 | if (type == at_double) { 636 | read_ += sizeof(double); 637 | } 638 | if (type == at_bool) { 639 | read_ += sizeof(bool); 640 | } 641 | 642 | return sp; 643 | } 644 | 645 | std::pair block::Args::peek_str() 646 | { 647 | void *sp = nullptr; 648 | 649 | assert(peek_tag() == at_string); 650 | 651 | TypeLen _len = pop_typelen(); 652 | sp = (void*)read_; 653 | 654 | read_ += _len; 655 | 656 | return std::make_pair(sp, _len); 657 | } 658 | 659 | ////////////////////////////////////////////////////////////////////////// 660 | int block::Args::get_tag() 661 | { 662 | auto _ui8 = *reinterpret_cast(read_); 663 | return _ui8; 664 | } 665 | 666 | uint32_t block::Args::get_size() const 667 | { 668 | return bytes_->size_; 669 | } 670 | 671 | uint32_t block::Args::get_params_count() const 672 | { 673 | return params_; 674 | } 675 | 676 | uint32_t block::Args::get_offset() const 677 | { 678 | return offset_; 679 | } 680 | 681 | std::string block::Args::exportBuf() 682 | { 683 | std::string _str; 684 | _str.append(bytes_->buff_, get_size()); 685 | return _str; 686 | } 687 | 688 | void block::Args::importBuf(const std::string &str) 689 | { 690 | size_t _len = str.length(); 691 | inc(_len); 692 | 693 | memcpy(write_, str.c_str(), _len); 694 | write_ += _len; 695 | } 696 | 697 | std::string block::Args::print() const 698 | { 699 | auto _args = Args(bytes_->buff_, get_size()); 700 | std::stringstream ss; 701 | 702 | auto tag = _args.get_tag(); 703 | ss << "test->" << std::endl; 704 | while (tag != 0) 705 | { 706 | switch (tag) 707 | { 708 | case at_bool: 709 | ss << "bool:" << _args.pop_bool() << std::endl; 710 | break; 711 | case at_uint8: 712 | ss << "uint8:" << _args.pop_ui8() << std::endl; 713 | break; 714 | case at_int8: 715 | ss << "int8:" << _args.pop_i8() << std::endl; 716 | break; 717 | case at_int16: 718 | ss << "int16:" << _args.pop_i16() << std::endl; 719 | break; 720 | case at_uint16: 721 | ss << "uint16:" << _args.pop_ui16() << std::endl; 722 | break; 723 | case at_int32: 724 | ss << "int32:" << _args.pop_i32() << std::endl; 725 | break; 726 | case at_uint32: 727 | ss << "uint32:" << _args.pop_ui32() << std::endl; 728 | break; 729 | case at_int64: 730 | ss << "int64:" << _args.pop_i64() << std::endl; 731 | break; 732 | case at_uint64: 733 | ss << "uint64:" << _args.pop_ui64() << std::endl; 734 | break; 735 | case at_string: 736 | ss << "string:" << _args.pop_string() << std::endl; 737 | break; 738 | } 739 | tag = _args.get_tag(); 740 | } 741 | 742 | ss << "<-end" << std::endl; 743 | return ss.str(); 744 | } 745 | --------------------------------------------------------------------------------